- Joined
- Apr 24, 2012
- Messages
- 5,113
Don't know what I came into my mind but I'm currently developing this system:
Current problems:
- Needs better performance(can process 40-50 boids in a map on average)
- Better Deflection method
JASS:
library Boid requires MapBounds, Vector, Alloc
globals
private constant integer BOID_ID = 'boid'
private constant real ALIGNMENT_WEIGHT = 1.
private constant real COHESION_WEIGHT = 1.
private constant real SEPERATION_WEIGHT = 2.
private constant real SEPERATION_RANGE = 32
private constant real NEIGHBOR_RANGE = 64
private constant real TIMEOUT = 0.031250000
endglobals
private function GetAngleRad takes real x, real y, real x2, real y2 returns real
return Atan2(y2 - y, x2 - x)
endfunction
struct Boid extends array
implement Alloc
private unit u
private vector velocity
private real spd
private real x
private real y
private effect sfx
private thistype n
private thistype p
private static integer c = 0
private static constant timer t = CreateTimer()
method destroy takes nothing returns nothing
call deallocate()
set c = c - 1
if c == 0 then
call PauseTimer(t)
endif
set p.n = n
set n.p = p
call DestroyEffect(sfx)
call velocity.destroy()
set x = 0
set y = 0
set spd = 0
set u = null
set sfx = null
endmethod
private static method periodic takes nothing returns nothing
local thistype this = thistype(0).n
local real a
local real tx
local real ty
local real ax
local real ay
local real cx
local real cy
local real sx
local real sy
local real nc
local thistype id
loop
exitwhen this == 0
set nc = 0
set ax = 0
set ay = 0
set cx = 0
set cy = 0
set sx = 0
set sy = 0
set id = thistype(0).n
loop
exitwhen id == 0
if id != this then
if IsUnitInRange(id.u, u, NEIGHBOR_RANGE) then
set ax = ax + id.velocity.x
set ay = ay + id.velocity.y
set cx = cx + id.x
set cy = cy + id.y
if IsUnitInRange(id.u, u, SEPERATION_RANGE) then
set sx = sx + id.x - x
set sy = sy + id.y - y
endif
set nc = nc + 1
endif
endif
set id = id.n
endloop
if nc > 0 then
set ax = ay/nc
set ax = ay/nc
set cx = cx/nc - x
set cy = cy/nc - y
set sx = -sx/nc
set sy = -sy/nc
endif
set velocity.x = velocity.x + ax*ALIGNMENT_WEIGHT + cx*COHESION_WEIGHT + sx*SEPERATION_WEIGHT
set velocity.y = velocity.y + ay*ALIGNMENT_WEIGHT + cy*COHESION_WEIGHT + sy*SEPERATION_WEIGHT
call velocity.setLength(spd)
set a = GetAngleRad(0, 0, velocity.x, velocity.y)
set tx = 0
set ty = 0
if not (MapContainsX(x + velocity.x/TIMEOUT) and MapContainsY(y + velocity.y/TIMEOUT)) then
set a = a - bj_PI/2
set tx = spd*Cos(a)
set ty = spd*Sin(a)
if not (MapContainsX(x + tx/TIMEOUT) and MapContainsY(y + ty/TIMEOUT)) then
set a = a+bj_PI
set tx = spd*Cos(a)
set ty = spd*Sin(a)
if not (MapContainsX(x + tx/TIMEOUT) and MapContainsY(y + ty/TIMEOUT)) then
set a = a + bj_PI/2
set tx = spd*Cos(a)
set ty = spd*Sin(a)
endif
endif
endif
set velocity.x = velocity.x + tx
set velocity.y = velocity.y + ty
call velocity.setLength(spd)
set x = x + velocity.x
set y = y + velocity.y
call SetUnitX(u, x)
call SetUnitY(u, y)
call SetUnitFacing(u, GetAngleRad(0, 0, velocity.x, velocity.y)*bj_RADTODEG)
set this = n
endloop
endmethod
static method create takes string model, real tx, real ty, real z, real scale, real speed returns thistype
local thistype this = allocate()
local real face = GetRandomReal(-bj_PI, bj_PI)
set u = CreateUnit(Player(15), BOID_ID, tx, ty, face*bj_RADTODEG)
set spd = speed*TIMEOUT
set velocity = vector.create(spd*Cos(face), spd*Sin(face), 0)
set x = tx
set y = ty
set n = 0
set p = thistype(0).p
set thistype(0).p.n = this
set thistype(0).p = this
if UnitAddAbility(u, 'Amrf') and UnitRemoveAbility(u, 'Amrf') then
endif
call SetUnitFlyHeight(u, z, 0)
call SetUnitScale(u, scale, 0, 0)
set sfx = AddSpecialEffectTarget(model, u, "chest")
set c = c + 1
if c == 1 then
call TimerStart(t, TIMEOUT, true, function thistype.periodic)
endif
return this
endmethod
endstruct
endlibrary
Current problems:
- Needs better performance(can process 40-50 boids in a map on average)
- Better Deflection method
Attachments
Last edited: