Below is my
2D Vector Library which you can #include in your own code. And attached is a usage example using seek and evade steering behaviours as described in Craig Reynold's research paper on on autonomous agents.
In the usage example, the 'target' sprite
seeks a random waypoint. When it finds it, it will choose another waypoint and steer/accelerate towards that and so on...
The 'enemy' sprite will
seek the player unless they get too close and then then will
evade it instead.
Any enemies that collide with the target will be respawned in a random location and continue as before.
type tVector
x as float
y as float
endtype
//**********************************
// Set Vector Random heading
//**********************************
//Create A unit vector in a random direction
function SetVectorRandom(v ref as tVector)
v.x = Random2()
v.y = Random2()
SetVectorNormalize(v)
endfunction
//**********************************
// Set Vector
//**********************************
//Sets an existing vector directly
function SetVector(x#, y#)
vr as tVector
vr.x = x#
vr.y = y#
endfunction vr
//**********************************
// Set Vector from Heading and magnitude
//**********************************
//Sets an existing vector from heading and magnitude
function SetVectorHM(v ref as tVector, head#, mag#)
v.x = cos(head#) * mag#
v.y = sin(head#) * mag#
endfunction
//**********************************
// Create Vector
//**********************************
//Creates a new vector by heading and magnitude
function CreateVectorHM(head#, mag#)
v as tVector
v.x = cos(head#) * mag#
v.y = sin(head#) * mag#
endfunction v
//**********************************
// Set Vector Heading
//**********************************
//Sets the vectors heading (direction)
function SetVectorHeading(v ref as tVector, head#)
mag# = GetVectorLength(v)
v.x = Cos(head#) * mag#
v.y = Sin(head#) * mag#
endfunction
//**********************************
// Rotate Vector
//**********************************
//Sets the vectors heading by rotating it by the given value
function RotateVector(v ref as tVector, a#)
SetVectorHeading(v, GetVectorAngle(v) + a#)
endfunction
//**********************************
// Set Vector Magnitude
//**********************************
//Sets the vectors magnitude (length)
function SetVectorMagnitude(v ref as tVector, mag#)
SetVectorNormalize(v)
SetVectorMultiply(v, mag#)
endfunction
//**********************************
// Copy Vector
//**********************************
//Sets Vector 2 to be the same as Vector 1
function CopyVector(v1 as tVector, v2 ref as tVector)
v2.x = v1.x
v2.y = v1.y
endfunction
//Same thing - different name
function SetVectorCopy(v1 as tVector, v2 ref as tVector)
v2.x = v1.x
v2.y = v1.y
endfunction
//**********************************
// Copy Vector
//**********************************
//Create a new vector that is a copy of an existing one
function GetVectorCopy(v as tVector)
vr as tVector
vr.x = v.x
vr.y = v.y
endfunction vr
//**********************************
// Normalise
//**********************************
//Directly normalise the passed vector
//Spelling of normalise has been "Americanised" as per coding standards :(
function SetVectorNormalize(v ref as tVector)
l# = GetVectorLength(v)
v.x = v.x / l#
v.y = v.y / l#
endfunction
//Normalise v and return the result
function GetVectorNormalize(v as tVector)
vr as tVector
l# = GetVectorLength(v)
vr.x = v.x / l#
vr.y = v.y / l#
endfunction vr
// A direct copy of GetVectorNormalize() with a different name
function GetUnitVector(v as tVector)
vr as tVector
l# = GetVectorLength(v)
vr.x = v.x / l#
vr.y = v.y / l#
endfunction vr
//**********************************
// Set Vector Zero
//**********************************
//Sets the vector to zero
function SetVectorZero(v ref as tVector)
v.x = 0
v.y = 0
endfunction
//**********************************
// Addition
//**********************************
//Adds two vectors and puts the return value in v1
function SetVectorAdd(v1 ref as tVector, v2 ref as tVector)
inc v1.x, v2.x
inc v1.y, v2.y
endfunction
//Adds v1 to v2 and returns a vector
function GetVectorAdd(v1 as tVector, v2 as tVector)
vr as tVector
vr.x = v1.x + v2.x
vr.y = v1.y + v2.y
endfunction vr
//**********************************
// Subtraction
//**********************************
//Subtracts two vectors and puts the return value in v1
function SetVectorSubtract(v1 ref as tVector, v2 ref as tVector)
dec v1.x, v2.x
dec v1.y, v2.y
endfunction
//Subtracts v2 from v1 and returns a vector
function GetVectorSubtract(v1 as tVector, v2 as tVector)
vr as tVector
vr.x = v1.x - v2.x
vr.y = v1.y - v2.y
endfunction vr
//**********************************
// Multiplication
//**********************************
//Directly multiplies a vector value
function SetVectorMultiply(v ref as tVector, m#)
v.x = v.x * m#
v.y = v.y * m#
endfunction
//Multiplies v1 by m# and returns a vector
function GetVectorMultiply(v as tVector, m#)
vr as tVector
vr.x = v.x * m#
vr.y = v.y * m#
endfunction vr
//**********************************
// Division
//**********************************
//Divides a vector and puts the return value in v1
function SetVectorDivide(v ref as tVector, d#)
v.x = v.x / d#
v.y = v.y / d#
endfunction
//Divides v1 by m# and returns a vector
function GetVectorDivide(v as tVector, m#)
vr as tVector
vr.x = v.x / m#
vr.y = v.y / m#
endfunction vr
//**********************************
// Negate Vector
//**********************************
//Points the vector in the opposite direction
function SetVectorNegate(v ref as tVector)
v.x = -v.x
v.y = -v.y
endfunction
//Returns a vector that is in the opposite direction to that of v
function GetVectorNegate(v as tVector)
vr as tVector
vr.x = -v.x
vr.y = -v.y
endfunction vr
//**********************************
// Set Vector Limit
//**********************************
//Directly sets a limit to the passed in vector
function SetVectorLimit(v ref as tVector, limit#)
mag# = GetVectorLength(v)
if mag# <= limit# then exitfunction
SetVectorNormalize(v)
SetVectorMultiply(v, limit#)
endfunction
//********************************** G E T T E R S **********************************
//**********************************
// GetVectorRandom
//**********************************
//Get a unit vector in a random direction
function GetVectorRandom()
v as tVector
v.x = random2()
v.y = random2()
SetVectorNormalize(v)
endfunction v
//**********************************
// Get Vector Distance
//**********************************
//Returns a float that is the distance between v1 and v2
function GetVectorDistance(v1 as tVector, v2 as tVector)
vx# = v1.x - v2.x
vy# = v1.y - v2.y
d# = sqrt((vx# * vx#) + (vy# * vy#))
endfunction d#
//**********************************
// Get Vector Distance Sqr
//**********************************
//Returns a float that is the SQUARED distance between v1 and v2
function GetVectorDistanceSqr(v1 as tVector, v2 as tVector)
vx# = v1.x - v2.x
vy# = v1.y - v2.y
d# = (vx# * vx#) + (vy# * vy#)
endfunction d#
//**********************************
// Get Vector Length
//**********************************
function GetVectorLength(v as tVector)
l# = sqrt( (v.x*v.x) + (v.y*v.y) )
endfunction l#
//**********************************
// Get Vector Length Length
//**********************************
function GetVectorSquareLength(v as tVector)
endfunction (v.x*v.x) + (v.y*v.y)
//**********************************
// Get Vector Magnitude
//**********************************
//Same as GetVectorLength() with a different name
function GetVectorMagnitude(v as tVector)
l# = sqrt( (v.x*v.x) + (v.y*v.y) )
endfunction l#
//**********************************
// Get Vector Midpoint
//**********************************
//Returns a vector that is the midpoint between v1 and v2
function GetVectorMidpoint(v1 as tVector, v2 as tVector)
vr as tVector
vr.x = (v1.x + v2.x)/2.0
vr.y = (v1.y + v2.y)/2.0
endfunction vr
//**********************************
// Get Vector Zero
//**********************************
//Creates a zeroed vector
function GetVectorZero()
v as tVector
v.x = 0
v.y = 0
endfunction v
//**********************************
// Get Angle as a scaler
//**********************************
//Gets the vectors angle as a scaler
function GetVectorAngle(v as tVector)
angle# = WrapAngle(ATanFull(v.x, v.y) - 90)
endfunction angle#
//A copy of GetVectorAngle() with a different name
function GetVectorHeading(v as tVector)
angle# = WrapAngle(ATanFull(v.x, v.y) - 90)
endfunction angle#
//**********************************
// Dot Product
//**********************************
function GetDotProduct(v1 as tVector, v2 as tVector)
endfunction (v1.x * v2.x) + (v1.y * v2.y)
//Same as above but a different name
function GetVectorDotProduct(v1 as tVector, v2 as tVector)
endfunction (v1.x * v2.x) + (v1.y * v2.y)
//**********************************
// Get Angle Between Two Vectors
//**********************************
function GetAngleBetween(v1 as tVector, v2 as tVector)
m1# = GetVectorLength(v1)
m2# = GetVectorLength(v2)
dot# = GetDotProduct(v1, v2)
a# = ACos(dot#/(m1#*m2#))
endfunction a#
//**********************************
// Get Vector Projection
//**********************************
function GetVectorProjection(v1 as tVector, v2 as tVector)
p as tVector
mag# = GetVectorSquareLength(v2)
dot# = GetVectorDotProduct(v1, v2)
s# = dot# / mag#
CopyVector(v2, p)
SetVectorMultiply(p, s#)
endfunction p
//**********************************
// Equals
//**********************************
//Returns 1 (TRUE) if the two passed vectors are equal
function GetVectorEquals(v1 as tVector, v2 as tVector)
if v1.x = v2.x
if v1.y = v2.y
exitfunction 1
endif
endif
endfunction 0
//**********************************
// Set Vector Wrap Screen
//**********************************
// If a positional vector has move beyond the screen limints then
// Wrap it to the other side
function SetVectorWrapScreen(v REF as tVector)
if v.x > GetScreenBoundsRight()
v.x = GetScreenBoundsLeft() + (v.x - GetScreenBoundsRight())
elseif v.x < GetScreenBoundsLeft()
v.x = GetScreenBoundsRight() - (GetScreenBoundsLeft() - v.x)
endif
if v.y > GetScreenBoundsBottom()
v.y = GetScreenBoundsTop() + (v.y - GetScreenBoundsBottom())
elseif v.y < GetScreenBoundsTop()
v.y = GetScreenBoundsBottom() - (GetScreenBoundsTop() - v.y)
endif
endfunction
//**********************************
// Wrap Angle
//**********************************
//Returns a value that does not exceed the range of 0 to 360.
function WrapAngle(angle as float)
angle = fmod(angle, 360.0)
if angle <0 then angle=angle+360
endfunction angle
/************************************************************************************
* *
D E B U G *
* *
************************************************************************************/
//**********************************
// DEBUG - DRAW VECTOR
//**********************************
//Draw a line from pos in the direction and magnitude of v
//multi# is a multiplier that can extend/shrink the debug line
function DrawVector(pos as tVector, v as tVector, multi#, r, g, b)
c = MakeColor(r, g, b)
v2 as tVector
CopyVector(v, v2)
SetVectorMultiply(v2, multi#)
DrawLine(pos.x, pos.y, pos.x + v2.x, pos.y+v2.y, c, c)
DrawEllipse(pos.x + v2.x, pos.y+v2.y, 0.75, 0.75, c, c, 1)
endfunction
//**********************************
// DEBUG - DRAW VECTOR RANGE
//**********************************
//Draw a circle around a position vector
function DrawVectorRange(v as tVector, range#, r, g, b)
c = MakeColor(r, g, b)
DrawEllipse(v.x, v.y, range#, range#, c, c, 0)
endfunction