I have discovered an other "limitation" of HardonCollider that did not really fit my system and that is if I was calling polygon:scale() multiple times, it is constantly multiplied the scale and keep increased the size of the collider.
For example if I set :scale(2) and then scale(3) inside a loop maybe, HardonCollider basically do 2*1 and then 3*2 and then 3*6 and then 3*18 and just keep going forever. But this is not what I wanted.
What I want if I set scale 2 and then 3 even if I keep repeat inside a loop, the scale always remain the same it does not multiply constantly, so if I set it to 2 it is 2*1 and if I set it 3 it is 3*1 instead of 2*1 and 3*2, 3*6 and so on.
I decided to handle this in my library instead of changing the way HC works internally and I have implemented my own setPosition, setRotation and setScale methods for this purpose only.
In case someone hit the same wall, this is the code, note that I have no idea how the code works I did just copy most of it from HC itself and I was using common sense to add what I need without actually understanding the math behind it:
Inside constructor or at the very beginning of your code
Code: Select all
hc = require "HardonCollider"
vector = require "HardonCollider.vector-light"
t = hc.rectangle(x,y,width,height)
--set center of collider to be at the origin of the object
--it is necessary hack so after we can move, rotate, scale the collider around the origin point instead of the center
t._polygon.centroid.x = _object:getX()
t._polygon.centroid.y = _object:getY()
t._polygon.centroid.ix = _object:getX() --we also need the initial position so we can reset when we change the scale
t._polygon.centroid.iy = _object:getY()
setPosition
Code: Select all
t.setPosition = function(self, _x, _y)
local cx,cy = self._polygon.centroid.x, self._polygon.centroid.y
local x = _x - cx
local y = _y - cy
local icx,icy = self._polygon.centroid.ix, self._polygon.centroid.iy
local ix = _x - icx
local iy = _y - icy
for i,v in ipairs(self._polygon.vertices) do
v.x = v.x + x
v.y = v.y + y
v.ix = v.ix + ix
v.iy = v.iy + iy
end
--apply position also to the center point
self._polygon.centroid.x = self._polygon.centroid.x + x
self._polygon.centroid.y = self._polygon.centroid.y + y
self._polygon.centroid.ix = self._polygon.centroid.ix + ix
self._polygon.centroid.iy = self._polygon.centroid.iy + iy
end
setRotation
Code: Select all
t.setRotation = function(self, _rotation)
local angle = math.rad(_rotation) - self._rotation
self._rotation = self._rotation + angle
local cx,cy = self._polygon.centroid.x, self._polygon.centroid.y
local icx,icy = self._polygon.centroid.ix, self._polygon.centroid.iy
for i,v in ipairs(self._polygon.vertices) do
-- v = (v - center):rotate(angle) + center
v.ix,v.iy = vector.add(icx,icy, vector.rotate(angle, v.ix-icx, v.iy-icy))
v.x,v.y = vector.add(cx,cy, vector.rotate(angle, v.x-cx, v.y-cy))
end
--apply rotation also to the center point
local v = self._polygon.centroid
v.ix,v.iy = vector.add(icx,icy, vector.rotate(angle, v.ix-icx, v.iy-icy))
v.x,v.y = vector.add(cx,cy, vector.rotate(angle, v.x-cx, v.y-cy))
end
setScale
Code: Select all
t.setScale = function(self, s)
local cx,cy = self._polygon.centroid.x, self._polygon.centroid.y
for i,v in ipairs(self._polygon.vertices) do
-- v = (v - center) * s + center
--before doing anything, reset vertices back to initial position
v.x = v.ix
v.y = v.iy
--now we can apply new scale
v.x,v.y = vector.add(cx,cy, vector.mul(s, v.x-cx, v.y-cy))
end
end
I do realise it is not perfect and ugly and I don't really understand the math, but it works and I hope it is going to be useful for some people who struggling with vector math and collision as much as I do.
With this hack, majority of collision related things works fine now I think. I can move, rotate, scale as much as I want and collision detection is working as expected now.