mirror of
https://github.com/vrld/HC.git
synced 2024-11-18 12:54:23 +00:00
Report collisions immediately instead of collecting first.
Collecting collisions and then reporting leads to confusing behavior when a previous collision callback resolved the collision, e.g. platforms in jump in runs pushing the player upwards when standing on two platforms at the same time.
This commit is contained in:
parent
68de65f22e
commit
ed495d3306
41
init.lua
41
init.lua
@ -46,7 +46,7 @@ function HC:init(cell_size, callback_collide, callback_stop)
|
|||||||
self._current_shape_id = 0
|
self._current_shape_id = 0
|
||||||
self._shape_ids = setmetatable({}, {__mode = "k"}) -- reverse lookup
|
self._shape_ids = setmetatable({}, {__mode = "k"}) -- reverse lookup
|
||||||
self.groups = {}
|
self.groups = {}
|
||||||
self._colliding_last_frame = {}
|
self._colliding_only_last_frame = {}
|
||||||
|
|
||||||
self.on_collide = callback_collide or __NULL__
|
self.on_collide = callback_collide or __NULL__
|
||||||
self.on_stop = callback_stop or __NULL__
|
self.on_stop = callback_stop or __NULL__
|
||||||
@ -60,7 +60,7 @@ function HC:clear()
|
|||||||
self._current_shape_id = 0
|
self._current_shape_id = 0
|
||||||
self._shape_ids = setmetatable({}, {__mode = "k"}) -- reverse lookup
|
self._shape_ids = setmetatable({}, {__mode = "k"}) -- reverse lookup
|
||||||
self.groups = {}
|
self.groups = {}
|
||||||
self._colliding_last_frame = {}
|
self._colliding_only_last_frame = {}
|
||||||
self._hash = common.instance(Spatialhash, self._hash.cell_size)
|
self._hash = common.instance(Spatialhash, self._hash.cell_size)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -167,39 +167,48 @@ function HC:update(dt)
|
|||||||
or self:share_group(shape, other)
|
or self:share_group(shape, other)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- collect colliding shapes
|
-- collect active shapes. necessary, because a callback might add shapes to
|
||||||
for shape in self:activeShapes() do
|
-- _active_shapes, which will lead to undefined behavior (=random crashes) in
|
||||||
|
-- next()
|
||||||
|
local active = {}
|
||||||
|
for id,shape in pairs(self._active_shapes) do
|
||||||
|
active[id] = shape
|
||||||
|
end
|
||||||
|
|
||||||
|
local only_last_frame = self._colliding_only_last_frame
|
||||||
|
for id,shape in pairs(active) do
|
||||||
tested[shape] = {}
|
tested[shape] = {}
|
||||||
for other in self._hash:rangeIter(shape:bbox()) do
|
for other in self._hash:rangeIter(shape:bbox()) do
|
||||||
|
if not self._active_shapes[id] then
|
||||||
|
-- break out of this loop is shape was removed in a callback
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
if not may_skip_test(shape, other) then
|
if not may_skip_test(shape, other) then
|
||||||
local collide, sx,sy = shape:collidesWith(other)
|
local collide, sx,sy = shape:collidesWith(other)
|
||||||
if collide then
|
if collide then
|
||||||
if not colliding[shape] then colliding[shape] = {} end
|
if not colliding[shape] then colliding[shape] = {} end
|
||||||
colliding[shape][other] = {sx, sy}
|
colliding[shape][other] = {sx, sy}
|
||||||
|
|
||||||
|
-- flag shape colliding this frame and call collision callback
|
||||||
|
if only_last_frame[shape] then
|
||||||
|
only_last_frame[shape][other] = nil
|
||||||
|
end
|
||||||
|
self.on_collide(dt, shape, other, sx, sy)
|
||||||
end
|
end
|
||||||
tested[shape][other] = true
|
tested[shape][other] = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- call colliding callbacks on colliding shapes
|
|
||||||
for a, reg in pairs(colliding) do
|
|
||||||
for b, info in pairs(reg) do
|
|
||||||
if self._colliding_last_frame[a] then
|
|
||||||
self._colliding_last_frame[a][b] = nil
|
|
||||||
end
|
|
||||||
self.on_collide(dt, a, b, info[1], info[2])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- call stop callback on shapes that do not collide anymore
|
-- call stop callback on shapes that do not collide anymore
|
||||||
for a,reg in pairs(self._colliding_last_frame) do
|
for a,reg in pairs(only_last_frame) do
|
||||||
for b, info in pairs(reg) do
|
for b, info in pairs(reg) do
|
||||||
self.on_stop(dt, a, b, info[1], info[2])
|
self.on_stop(dt, a, b, info[1], info[2])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self._colliding_last_frame = colliding
|
self._colliding_only_last_frame = colliding
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get list of shapes at point (x,y)
|
-- get list of shapes at point (x,y)
|
||||||
|
Loading…
Reference in New Issue
Block a user