library Collision2D uses Table
globals
private constant real INTERVAL = 0.03
private unit tempUnit
private Collision2D enum
private Table table
private unit lastSourceUnitCol
private unit lastLeavingUnitCol
private unit lastEnteringUnitCol
endglobals
private function Distance takes real x1, real y1, real x2, real y2 returns real
return SquareRoot(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)))
endfunction
function GetCollisionSource takes nothing returns unit
return lastSourceUnitCol
endfunction
function GetCollisionLeavingUnit takes nothing returns unit
return lastLeavingUnitCol
endfunction
function GetCollisionEnteringUnit takes nothing returns unit
return lastEnteringUnitCol
endfunction
struct Collision2D
private timer t
private group withinGroup
unit u
real range
trigger trgEnter
trigger trgLeave
static method create takes unit u, real range returns thistype
local thistype this = .allocate()
set this.u = u
set this.range = range
set this.t = CreateTimer()
set this.withinGroup = CreateGroup()
call TimerStart(this.t, INTERVAL, true, function thistype.update)
set table[GetHandleId(this.t)] = this
return this
endmethod
method destroy takes nothing returns nothing
call table.remove(GetHandleId(.t))
set .u = null
call PauseTimer(.t)
call DestroyTimer(.t)
call DestroyGroup(.withinGroup)
if .trgEnter != null then
call TriggerClearConditions(.trgEnter)
call DestroyTrigger(.trgEnter)
set .trgEnter = null
endif
if .trgLeave != null then
call TriggerClearConditions(.trgLeave)
call DestroyTrigger(.trgLeave)
set .trgLeave = null
endif
call .deallocate()
endmethod
method disable takes nothing returns nothing
call PauseTimer(.t)
endmethod
method enable takes nothing returns nothing
call ResumeTimer(.t)
endmethod
method setOnEnterListener takes code callback returns nothing
if .trgEnter != null then
call TriggerClearConditions(.trgEnter)
else
set .trgEnter = CreateTrigger()
endif
if callback != null then
call TriggerAddCondition(.trgEnter, Condition(callback))
endif
endmethod
method setOnLeaveListener takes code callback returns nothing
if .trgLeave != null then
call TriggerClearConditions(.trgLeave)
else
set .trgLeave = CreateTrigger()
endif
if callback != null then
call TriggerAddCondition(.trgLeave, Condition(callback))
endif
endmethod
private static method leaving takes nothing returns nothing
set tempUnit = GetEnumUnit()
if Distance(GetUnitX(tempUnit), GetUnitY(tempUnit), GetUnitX(enum.u), GetUnitY(enum.u)) > enum.range then
call GroupRemoveUnit(enum.withinGroup, tempUnit)
set lastLeavingUnitCol = tempUnit
set lastSourceUnitCol = enum.u
if enum.trgLeave != null then
call TriggerEvaluate(enum.trgLeave)
endif
call BJDebugMsg(GetUnitName(tempUnit) + " has left " + R2S(enum.range) + " of source: " + GetUnitName(enum.u))
endif
endmethod
private static method entering takes nothing returns nothing
set tempUnit = GetEnumUnit()
call GroupAddUnit(enum.withinGroup, tempUnit)
call BJDebugMsg(GetUnitName(tempUnit) + " is within " + R2S(enum.range) + " of source: " + GetUnitName(enum.u))
set lastEnteringUnitCol = tempUnit
set lastSourceUnitCol = enum.u
if enum.trgEnter != null then
call TriggerEvaluate(enum.trgEnter)
endif
endmethod
private static method filter takes nothing returns boolean
set tempUnit = GetFilterUnit()
return enum.u != tempUnit and not(IsUnitInGroup(tempUnit, enum.withinGroup))
endmethod
private static method update takes nothing returns nothing
local location point
set enum = table[GetHandleId(GetExpiredTimer())]
set point = GetUnitLoc(enum.u)
set bj_wantDestroyGroup = true
call ForGroup(GetUnitsInRangeOfLocMatching(enum.range, point, Condition(function thistype.filter)), function thistype.entering)
call ForGroup(enum.withinGroup, function thistype.leaving)
call RemoveLocation(point)
set point = null
endmethod
private static method onInit takes nothing returns nothing
set table = Table.create()
endmethod
endstruct
endlibrary