- Joined
- Jan 21, 2006
- Messages
- 2,552
Tell me what you guys think.
This is kind of a simple sketch of a Physics engine I was planning. If you're going to use the test-map, it creates 21 particles at initialization (they bounce around terrain) and you can use the ESC key to create a field at the current camera position.
I'm pretty sure that the game will crash if you let any of the particles start wondering outside of the map area (since I do not do any sentinel checks yet), so be sure you make a field that will suck them back in.
I was actually planning on using this primarily for cool looking special effects on spells, but if you guys happen to see any other use for it perhaps I could add some functionality.
This is kind of a simple sketch of a Physics engine I was planning. If you're going to use the test-map, it creates 21 particles at initialization (they bounce around terrain) and you can use the ESC key to create a field at the current camera position.
I'm pretty sure that the game will crash if you let any of the particles start wondering outside of the map area (since I do not do any sentinel checks yet), so be sure you make a field that will suck them back in.
I was actually planning on using this primarily for cool looking special effects on spells, but if you guys happen to see any other use for it perhaps I could add some functionality.
JASS:
library Vector
//*****************************************************************
//* VECTOR LIBRARY
//*
//* written by: Anitarf
//*
//* The library contains a struct named vector, which represents a
//* point in 3D space. As such, it has three real members, one for
//* each coordinate: x, y, z. It also has the following methods:
//*
//* static method create takes real x, real y, real z returns vector
//* Creates a new vector with the given coordinates.
//*
//* method getLength takes nothing returns real
//* Returns the length of the vector it is called on.
//*
//* static method sum takes vector augend, vector addend returns vector
//* Returns the sum of two vectors as a new vector.
//*
//* method add takes vector addend returns nothing
//* Similar to sum, except that it doesn't create a new vector for the result,
//* but changes the vector it is called on by adding the "added" to it.
//*
//* static method difference takes vector minuend, vector subtrahend returns vector
//* Returns the difference between two vectors as a new vector.
//*
//* method subtract takes vector subtrahend returns nothing
//* Similar to difference, except that it doesn't create a new vector for the result,
//* but changes the vector it is called on by subtracting the "subtrahend" from it.
//*
//* method scale takes real factor returns nothing
//* Scales the vector it is called on by the given factor.
//*
//* method setLength takes real length returns nothing
//* Sets the length of the vector it is called on to the given value, maintaining it's orientation.
//*
//* static method dotProduct takes vector a, vector b returns real
//* Calculates the dot product (also called scalar product) of two vectors.
//*
//* static method crossProduct takes vector a, vector b returns vector
//* Calculates the cross product (also called vector product) of two vectors
//* and returns it as a new vector.
//*
//* static method tripleProductScalar takes vector a, vector b, vector c returns real
//* Calculates the triple scalar product of three vectors.
//*
//* static method tripleProductVector takes vector a, vector b, vector c returns vector
//* Calculates the triple vector product of three vectors and returns it as a new vector.
//*
//*
//* static method projectionVector takes vector projected, vector direction returns vector
//* Calculates the projection of the vector "projected" onto the vector "direction"
//* and returns it as a new vector.
//* Returns null if the vector direction has a length of 0.
//*
//* method projectVector takes vector direction returns nothing
//* Projects the vector it is called on onto the vector "direction".
//* Does nothing if the vector "direction" has a length of 0.
//*
//* static method projectionPlane takes vector projected, vector normal returns vector
//* Calculates the projection of the vector projected onto a plane defined by
//* it's normal vector and returns it as a new vector.
//* Returns null if the vector "normal" has a length of 0.
//*
//* method projectPlane takes vector normal returns nothing
//* Projects the vector it is called on onto a plane defined by it's normal vector.
//* Does nothing if the vector "normal" has a length of 0.
//*
//* static method getAngle takes vector a, vector b returns real
//* Returns the angle between two vectors, in radians, returns a value between 0 and pi.
//* Returns 0.0 if any of the vectors are 0 units long.
//*
//* method rotate takes vector axis, real angle returns nothing
//* Rotates the vector it is called on around the axis defined by the vector "axis"
//* by the given angle, which should be input in radians.
//* Does nothing if axis is 0 units long.
//*
//*
//* static method createTerrainPoint takes real x, real y returns vector
//* Creates a vector to the given terrain coordinate, taking it's z height into account.
//*
//* method getTerrainPoint takes real x, real y returns nothing
//* Sets the vector it is called on to the given terrain coordinate, taking it's z height into account.
//*
//* static method createTerrainNormal takes real x, real y, real sampleRadius returns vector
//* Creates the normal vector of the terrain at given coordinates. "sampleRadius" defines
//* how far apart the reference points will be, if they are further apart, the result will
//* be an impression of smoother terrain; normaly the value should be between 0 and 128.
//*
//* method getTerrainNormal takes real x, real y, real sampleRadius returns nothing
//* Sets the vector it is called on to the normal of the terrain at given coordinates.
//*
//*
//* method isInCylinder takes vector cylinderOrigin, vector cylinderHeight, real cylinderRadius returns boolean
//* Determines if a point is within a given cylinder. The cylinder's origin vector points
//* to the center of one of the two paralel circular sides, and the height vector points
//* from the origin point to the center of the other of the two paralel circular sides.
//* Returns false if the point is not in the cylinder or if the vector cylinderHeight is 0 units long.
//*
//* method isInCone takes vector coneOrigin, vector coneHeight, real coneRadius returns boolean
//* Determines if a point is within a given cone. The cone's origin vector points to the
//* center of the circular side, and the height vector points from the origin point to
//* the tip of the cone.
//* Returns false if the point is not in the cylinder or if the vector coneHeight is 0 units long.
//*
//* method isInSphere takes vector sphereOrigin, real sphereRadius returns boolean
//* Determines if a point is within a give sphere. The sphere's origin vector points to the
//* center of the sphere.
//* Returns false if the point is not in the sphere.
//*****************************************************************
struct vector
real x
real y
real z
static method create takes real x, real y, real z returns vector
local vector v = vector.allocate()
set v.x=x
set v.y=y
set v.z=z
return v
endmethod
method getLength takes nothing returns real
return SquareRoot(.x*.x + .y*.y + .z*.z)
endmethod
method copy takes nothing returns thistype
local thistype v = allocate()
set v.x = x
set v.y = y
set v.z = z
return v
endmethod
static method sum takes vector augend, vector addend returns vector
local vector v = vector.allocate()
set v.x = augend.x+addend.x
set v.y = augend.y+addend.y
set v.z = augend.z+addend.z
return v
endmethod
method add takes vector addend returns nothing
set this.x=this.x+addend.x
set this.y=this.y+addend.y
set this.z=this.z+addend.z
endmethod
static method difference takes vector minuend, vector subtrahend returns vector
local vector v = vector.allocate()
set v.x = minuend.x-subtrahend.x
set v.y = minuend.y-subtrahend.y
set v.z = minuend.z-subtrahend.z
return v
endmethod
method subtract takes vector subtrahend returns nothing
set this.x=this.x-subtrahend.x
set this.y=this.y-subtrahend.y
set this.z=this.z-subtrahend.z
endmethod
method scale takes real factor returns nothing
set this.x=this.x*factor
set this.y=this.y*factor
set this.z=this.z*factor
endmethod
method setLength takes real length returns nothing
local real l = SquareRoot(.x*.x + .y*.y + .z*.z)
if l == 0.0 then
debug call BJDebugMsg("Attempted to set the length of a vector with no length!")
return
endif
set l = length/l
set this.x = this.x*l
set this.y = this.y*l
set this.z = this.z*l
endmethod
static method dotProduct takes vector a, vector b returns real
return (a.x*b.x+a.y*b.y+a.z*b.z)
endmethod
static method crossProduct takes vector a, vector b returns vector
local vector v = vector.allocate()
set v.x = a.y*b.z - a.z*b.y
set v.y = a.z*b.x - a.x*b.z
set v.z = a.x*b.y - a.y*b.x
return v
endmethod
static method tripleProductScalar takes vector a, vector b, vector c returns real
return ((a.y*b.z - a.z*b.y)*c.x+(a.z*b.x - a.x*b.z)*c.y+(a.x*b.y - a.y*b.x)*c.z)
endmethod
static method tripleProductVector takes vector a, vector b, vector c returns vector
local vector v = vector.allocate()
local real n = a.x*c.x+a.y*c.y+a.z*c.z
local real m = a.x*b.x+a.y*b.y+a.z*b.z
set v.x = b.x*n-c.x*m
set v.y = b.y*n-c.y*m
set v.z = b.z*n-c.z*m
return v
endmethod
// ================================================================
static method projectionVector takes vector projected, vector direction returns vector
local vector v = vector.allocate()
local real l = direction.x*direction.x+direction.y*direction.y+direction.z*direction.z
if l == 0.0 then
call v.destroy()
debug call BJDebugMsg("Attempted to project onto a vector with no length!")
return null
endif
set l = (projected.x*direction.x+projected.y*direction.y+projected.z*direction.z) / l
set v.x = direction.x*l
set v.y = direction.y*l
set v.z = direction.z*l
return v
endmethod
method projectVector takes vector direction returns nothing
local real l = direction.x*direction.x+direction.y*direction.y+direction.z*direction.z
if l == 0.0 then
debug call BJDebugMsg("Attempted to project onto a vector with no length!")
return
endif
set l = (this.x*direction.x+this.y*direction.y+this.z*direction.z) / l
set this.x = direction.x*l
set this.y = direction.y*l
set this.z = direction.z*l
endmethod
static method projectionPlane takes vector projected, vector normal returns vector
local vector v = vector.allocate()
local real l = normal.x*normal.x+normal.y*normal.y+normal.z*normal.z
if l == 0.0 then
call v.destroy()
debug call BJDebugMsg("Attempted to project onto an undefined plane!")
return null
endif
set l = (projected.x*normal.x+projected.y*normal.y+projected.z*normal.z) / l
set v.x = projected.x - normal.x*l
set v.y = projected.y - normal.y*l
set v.z = projected.z - normal.z*l
return v
endmethod
method projectPlane takes vector normal returns nothing
local real l = normal.x*normal.x+normal.y*normal.y+normal.z*normal.z
if l == 0.0 then
debug call BJDebugMsg("Attempted to project onto an undefined plane!")
return
endif
set l = (this.x*normal.x+this.y*normal.y+this.z*normal.z) / l
set this.x = this.x - normal.x*l
set this.y = this.y - normal.y*l
set this.z = this.z - normal.z*l
endmethod
static method getAngle takes vector a, vector b returns real
local real l = SquareRoot(a.x*a.x + a.y*a.y + a.z*a.z)*SquareRoot(b.x*b.x + b.y*b.y + b.z*b.z)
if l == 0 then
debug call BJDebugMsg("Attempted to get angle between vectors with no length!")
return 0.0
endif
return Acos((a.x*b.x+a.y*b.y+a.z*b.z)/l) //angle is returned in radians
endmethod
method rotate takes vector axis, real angle returns nothing //angle is taken in radians
local real xx
local real xy
local real xz
local real yx
local real yy
local real yz
local real zx
local real zy
local real zz
local real al = axis.x*axis.x+axis.y*axis.y+axis.z*axis.z //axis length^2
local real f
local real c = Cos(angle)
local real s = Sin(angle)
if al == 0.0 then
debug call BJDebugMsg("Attempted to project onto a vector with no length!")
return
endif
set f = (this.x*axis.x+this.y*axis.y+this.z*axis.z) / al
set zx = axis.x*f
set zy = axis.y*f
set zz = axis.z*f //axis component of rotated vector
set xx = this.x-zx
set xy = this.y-zy
set xz = this.z-zz //component of vector perpendicular to axis
set al = SquareRoot(al)
set yx = (axis.y*xz - axis.z*xy)/al
set yy = (axis.z*xx - axis.x*xz)/al //y same length as x by using cross product and dividing with axis length
set yz = (axis.x*xy - axis.y*xx)/al //x,y - coordinate system in which we rotate
set this.x=xx*c+yx*s+zx
set this.y=xy*c+yy*s+zy
set this.z=xz*c+yz*s+zz
endmethod
// ================================================================
private static location loc = Location(0.0,0.0)
static method createTerrainPoint takes real x, real y returns vector
local vector v = vector.allocate()
call MoveLocation(vector.loc,x,y)
set v.x=x
set v.y=y
set v.z=GetLocationZ(loc)
return v
endmethod
method getTerrainPoint takes real x, real y returns nothing
call MoveLocation(vector.loc,x,y)
set this.x=x
set this.y=y
set this.z=GetLocationZ(loc)
endmethod
static method createTerrainNormal takes real x, real y, real sampleRadius returns vector
local vector v = vector.allocate()
local real zx
local real zy
call MoveLocation(vector.loc, x-sampleRadius, y)
set zx=GetLocationZ(vector.loc)
call MoveLocation(vector.loc, x+sampleRadius, y)
set zx=zx-GetLocationZ(vector.loc)
call MoveLocation(vector.loc, x, y-sampleRadius)
set zy=GetLocationZ(vector.loc)
call MoveLocation(vector.loc, x, y+sampleRadius)
set zy=zy-GetLocationZ(vector.loc)
set sampleRadius=2*sampleRadius
set v.x = zx*sampleRadius
set v.y = zy*sampleRadius
set v.z = sampleRadius*sampleRadius
return v
endmethod
method getTerrainNormal takes real x, real y, real sampleRadius returns nothing
local real zx
local real zy
call MoveLocation(vector.loc, x-sampleRadius, y)
set zx=GetLocationZ(vector.loc)
call MoveLocation(vector.loc, x+sampleRadius, y)
set zx=zx-GetLocationZ(vector.loc)
call MoveLocation(vector.loc, x, y-sampleRadius)
set zy=GetLocationZ(vector.loc)
call MoveLocation(vector.loc, x, y+sampleRadius)
set zy=zy-GetLocationZ(vector.loc)
set sampleRadius=2*sampleRadius
set this.x = zx*sampleRadius
set this.y = zy*sampleRadius
set this.z = sampleRadius*sampleRadius
endmethod
// ================================================================
method isInCylinder takes vector cylinderOrigin, vector cylinderHeight, real cylinderRadius returns boolean
local real l
local real x = this.x-cylinderOrigin.x
local real y = this.y-cylinderOrigin.y
local real z = this.z-cylinderOrigin.z
if x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z < 0.0 then //point below cylinder
return false
endif
set x = x-cylinderHeight.x
set y = y-cylinderHeight.y
set z = z-cylinderHeight.z
if x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z > 0.0 then //point above cylinder
return false
endif
set l = cylinderHeight.x*cylinderHeight.x+cylinderHeight.y*cylinderHeight.y+cylinderHeight.z*cylinderHeight.z
if l == 0.0 then
debug call BJDebugMsg("Cylinder with no height!")
return false
endif
set l = (x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z) / l
set x = x - cylinderHeight.x*l
set y = y - cylinderHeight.y*l
set z = z - cylinderHeight.z*l
if x*x+y*y+z*z > cylinderRadius*cylinderRadius then //point outside cylinder
return false
endif
return true
endmethod
method isInCone takes vector coneOrigin, vector coneHeight, real coneRadius returns boolean
local real l
local real x = this.x-coneOrigin.x
local real y = this.y-coneOrigin.y
local real z = this.z-coneOrigin.z
if x*coneHeight.x+y*coneHeight.y+z*coneHeight.z < 0.0 then //point below cone
return false
endif
set l = coneHeight.x*coneHeight.x+coneHeight.y*coneHeight.y+coneHeight.z*coneHeight.z
if l == 0.0 then
debug call BJDebugMsg("cone with no height!")
return false
endif
set l = (x*coneHeight.x+y*coneHeight.y+z*coneHeight.z) / l
set x = x - coneHeight.x*l
set y = y - coneHeight.y*l
set z = z - coneHeight.z*l
if SquareRoot(x*x+y*y+z*z) > coneRadius*(1.0-l) then //point outside cone
return false
endif
return true
endmethod
method isInSphere takes vector sphereOrigin, real sphereRadius returns boolean
if sphereRadius*sphereRadius < ((this.x-sphereOrigin.x)*(this.x-sphereOrigin.x)+(this.y-sphereOrigin.y)*(this.y-sphereOrigin.y)+(this.z-sphereOrigin.z)*(this.z-sphereOrigin.z)) then
return false
endif
return true
endmethod
method toString takes nothing returns string
return "("+I2S(R2I(x))+", "+I2S(R2I(y))+", "+I2S(R2I(z))+")"
endmethod
endstruct
endlibrary
JASS:
library Stack
module Stack
//******************************
//* Stack Module
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
public static thistype array stackdata
public static integer stacksize = 0
public integer stackindex
//* ____________________________________________________________________________________________
method stackremove takes nothing returns nothing
set stacksize = stacksize - 1
set stackdata[stackindex] = stackdata[stacksize]
set stackdata[stackindex].stackindex = stackindex
endmethod
//* ____________________________________________________________________________________________
method stackadd takes nothing returns nothing
set stackdata[stacksize] = this
set stackindex = stacksize
set stacksize = stacksize + 1
endmethod
//*
//**********************************************************************************************
endmodule
endlibrary
JASS:
library ParticleInterface
interface particleinterface
//******************************
//* Particle Interface
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
method onGround takes nothing returns nothing defaults nothing
method onGroundLeave takes nothing returns nothing defaults nothing
//*
//**********************************************************************************************
endinterface
endlibrary
JASS:
library Particle requires ParticleInterface, PMotion, PData
struct particle extends particleinterface
//******************************
//* Particle
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
public static timer looptmr = CreateTimer()
public static constant real looptmrfreq = 0.015
//* ____________________________________________________________________________________________
implement AutoData
//* @ .me
implement PMotion
//* @ .coord
//* @ .veloc
//* @ .accel
//* @ .timescale
implement PData
//* @ .mass
//* @ .bounce
//* @ .friction
implement Stack
//* @ .stackdata
//* @ .stacksize
//* @ .stackindex
//* ____________________________________________________________________________________________
method applyForce takes vector forceVector returns nothing
local vector v = forceVector.copy()
call v.scale(looptmrfreq)
set veloc.x = veloc.x + v.x
set veloc.y = veloc.y + v.y
set veloc.z = veloc.z + v.z
call v.destroy( )
endmethod
//* ____________________________________________________________________________________________
method onDestroy takes nothing returns nothing
call killvectors( )
call stackremove( )
if (stacksize == 0) then
call PauseTimer(looptmr)
endif
endmethod
//* ____________________________________________________________________________________________
static method loopfunc takes nothing returns nothing
local integer i = stacksize - 1
local thistype p
loop
exitwhen (i < 0)
set p = stackdata[i]
if (p != 0) then
// Update vector components.
call p.updatevectors( )
if (p == 1) then
call BJDebugMsg("Velocity ("+R2S(p.veloc.x)+", "+R2S(p.veloc.y)+", "+R2S(p.veloc.z)+")")
call BJDebugMsg("Coordinates ("+R2S(p.coord.x)+", "+R2S(p.coord.y)+", "+R2S(p.coord.z)+")")
endif
// Inflict any friction forces that may apply.
if (p.flagGround) and (p.coord.z <= UnitZ_tempLocZ) then
set p.veloc.x = p.veloc.x * p.friction * p.timescale
set p.veloc.y = p.veloc.y * p.friction * p.timescale
set p.veloc.z = 0
endif
// Execute interface methods.
if not (p.flagGround) and (p.coord.z <= UnitZ_tempLocZ) then
set p.flagGround = true
call p.onGround( )
elseif (p.flagGround) and (p.coord.z > UnitZ_tempLocZ) then
set p.flagGround = false
call p.onGroundLeave( )
endif
endif
set i = i - 1
endloop
endmethod
//* ____________________________________________________________________________________________
static method create takes unit u, boolean typeflag returns thistype
local thistype p = allocate()
set p.me = u
if (stacksize == 0) then
call TimerStart(looptmr, looptmrfreq, true, function thistype.loopfunc)
endif
call p.setupvectors() // Gives accessibility to 3 vectors defined in PMotion.
call p.stackadd() // Adds particle to stack via Stack module.
if (typeflag) then
call UnitAddAbility(u, 'Aloc')
endif
call UnitAddAbility(u, 'Amrf')
call UnitRemoveAbility(u, 'Amrf')
return p
endmethod
//*
//**********************************************************************************************
endstruct
endlibrary
JASS:
library PMotion requires Vector, UnitZ
globals
//******************************
//* Definitions
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
public constant real def__GRAVITY = -750
//*
//**********************************************************************************************
endglobals
module PMotion
//******************************
//* PMotion Module
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
public vector coord
public vector veloc
public vector accel
//*
private real timescaleref = 1.000
private boolean isPaused = false
//*
//* ____________________________________________________________________________________________
method operator timescale takes nothing returns real
if (isPaused) then
return 0.00
else
return timescaleref
endif
endmethod
method operator timescale= takes real n returns nothing
if (n == 0.00) then
set isPaused = true
else
set timescaleref = n
endif
endmethod
//* ____________________________________________________________________________________________
method updatevectors takes nothing returns nothing
if not (isPaused) then
set veloc.x = veloc.x + accel.x * timescaleref
set veloc.y = veloc.y + accel.y * timescaleref
set veloc.z = veloc.z + accel.z * timescaleref
set coord.x = coord.x + veloc.x * timescaleref
set coord.y = coord.y + veloc.y * timescaleref
set coord.z = coord.z + veloc.z * timescaleref
call SetUnitX(me, coord.x)
call SetUnitY(me, coord.y)
call SetUnitZ(me, coord.z)
if (coord.z <= UnitZ_tempLocZ) then
set coord.z = UnitZ_tempLocZ
endif
endif
endmethod
//* ____________________________________________________________________________________________
method killvectors takes nothing returns nothing
call coord.destroy( )
call veloc.destroy( )
call accel.destroy( )
endmethod
//* ____________________________________________________________________________________________
method setupvectors takes nothing returns nothing
set coord = vector.create(GetUnitX(me), GetUnitY(me), GetUnitZ(me))
set veloc = vector.create(0, 0, 0)
set accel = vector.create(0, 0, def__GRAVITY * looptmrfreq * looptmrfreq)
endmethod
//*
//**********************************************************************************************
endmodule
endlibrary
JASS:
library PData
globals
//******************************
//* Definitions
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
public constant real def__MASS = 20
public constant real def__BOUNCE = 0.98
public constant real def__FRICTION = 0.9
//*
//**********************************************************************************************
endglobals
module PData
//******************************
//* PData Module
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
public real mass = def__MASS
public real bounce = def__BOUNCE
public real friction = def__FRICTION
//*
public boolean flagGround = false
//*
//**********************************************************************************************
endmodule
endlibrary
JASS:
library UnitZ
globals
//******************************
//* Definitions
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
public location tempLoc = Location(0, 0)
public real tempLocZ
//*
//**********************************************************************************************
endglobals
//**
//* Returns the -absolute- Z-coordinate of a unit based on its fly height and the height
//* of the terran below the unit.
//*
function GetUnitZ takes unit u returns real
call MoveLocation(tempLoc, GetUnitX(u), GetUnitY(u))
set tempLocZ = GetLocationZ(tempLoc)
return tempLocZ + GetUnitFlyHeight(u)
endfunction
//**
//* Adjusts a unit's fly-height based on an absolute Z-coordinate value "h" and the height
//* of the terran its on.
//*
function SetUnitZ takes unit u, real h returns nothing
call MoveLocation(tempLoc, GetUnitX(u), GetUnitY(u))
set tempLocZ = GetLocationZ(tempLoc)
call SetUnitFlyHeight(u, h-tempLocZ, 0)
endfunction
endlibrary
JASS:
library Field requires FieldInterface
struct field extends fieldinterface
//******************************
//* Field
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
public real x
public real y
public real z
public real magnitude
public real radius
//* ____________________________________________________________________________________________
public static timer looptmr = CreateTimer()
public static constant real looptmrfreq = 0.015
//* ____________________________________________________________________________________________
implement Stack
//* ____________________________________________________________________________________________
static method loopfunc takes nothing returns nothing
local integer i = stacksize - 1
local integer j
local field f
local particle p
local vector vf
local real distance
local real amplitude
loop
exitwhen (i < 0)
set f = stackdata[i]
if (f != 0) then
set j = particle.stacksize - 1
loop
exitwhen (j < 0)
set p = particle.stackdata[j]
if (p != 0) then
set distance = SquareRoot( /*
*/ (f.x - p.coord.x) * (f.x - p.coord.x) + /*
*/ (f.y - p.coord.y) * (f.y - p.coord.y) + /*
*/ (f.z - p.coord.z) * (f.z - p.coord.z) )
if (distance <= f.radius) and (f.particleFilter(p)) then
set vf = vector.create(f.x-p.coord.x, f.y-p.coord.y, f.z-p.coord.z)
set amplitude = (f.radius - distance) * (f.magnitude/f.radius)
call vf.setLength(amplitude)
call p.applyForce(vf)
call vf.destroy( )
endif
endif
set j = j - 1
endloop
endif
set i = i - 1
endloop
endmethod
//* ____________________________________________________________________________________________
method onDestroy takes nothing returns nothing
call stackremove( )
if (stacksize == 0) then
call PauseTimer(looptmr)
endif
endmethod
//* ____________________________________________________________________________________________
static method create takes real x, real y, real z, real magnitude, real radius returns thistype
local thistype f = allocate()
set f.x = x
set f.y = y
set f.z = z
set f.magnitude = magnitude
set f.radius = radius
if (stacksize == 0) then
call TimerStart(looptmr, looptmrfreq, true, function thistype.loopfunc)
endif
call f.stackadd()
return f
endmethod
//*
//**********************************************************************************************
endstruct
endlibrary
JASS:
library FieldInterface
interface fieldinterface
//******************************
//* Field Interface
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
method particleFilter takes particle p returns boolean defaults true
//*
//**********************************************************************************************
endinterface
endlibrary