I'm hoping that someone has a solution to this problem. I'm trying to find a way to do this without using libraries, more so I can understand how it works, and because this game is supposed to be extremely simple physics-wise.
Collisions:
Code: Select all
function Collision:new(x,y,width,height,strength)
Collision.super.new(self,x,y,width,height)
--Collsions
if strength == nil then strength = 0 end
self.strength = strength
self.tempStr = strength
self.last = {}
self.last.x = x
self.last.y = y
end
function Collision:setStrength(val)
if val < 0 then val = 0 end
self.strength = val
end
function Collision:update(dt)
self.last.x = self.x
self.last.y = self.y
self.tempStr = self.strength
end
function Collision:check(col)
if col:is(Collision) then return self:overlap(col) end
return false
end
function Collision:collide(e,dir)
if dir == "left" then
local pushback = self.x + self.width - e.x
self.x = self.x - pushback
elseif dir == "right" then
local pushback = e.x + e.width - self.x
self.x = self.x + pushback
elseif dir == "up" then
local pushback = e.y + e.height - self.y
self.y = self.y + pushback
elseif dir == "down" then
local pushback = self.y + self.height - e.y
self.y = self.y - pushback
end
end
function Collision:wasVerticalAligned(e)
return self.last.y < e.last.y + e.height and self.last.y + self.height > e.last.y
end
function Collision:wasHorizontalAligned(e)
return self.last.x < e.last.x + e.width and self.last.x + self.width > e.last.x
end
--Overwritten by other functions
function Collision:checkResolve(e,dir)
return true
end
function Collision:resolve(e)
--Check if stronger; if true, reverse
if self.tempStr > e.tempStr then
return e:resolve(self)
end
--Check if colliding
if self:check(e) then
self.tempStr = e.tempStr
if self:wasVerticalAligned(e) then
if self.x + (self.width/2) < e.x + (e.width/2) then
self:collide(e,"left")
else
self:collide(e,"right")
end
debugStrings[2] = "Horizontal Collision"
elseif self:wasHorizontalAligned(e) then
if self.y + (self.height/2) < e.y + (e.height/2) then
self:collide(e,"down")
else
self:collide(e,"up")
end
debugStrings[2] = "Vertical Collision"
end
return true
end
return false
end
Code: Select all
function Actor:canCollide(b)
if b == nil then b = false end
self.canCollide = b
end
function Actor:collide(a)
if a == nil then return false end
if a:is(Actor) then
if a:hasCollision() then
--Resolve
local t = self.col:resolve(a.col)
--Set position
if t then
self.x = self.col.x
self.y = self.col.y
a.x = a.col.x
a.y = a.col.y
end
return t
end
end
return false
end
function BasicData.collisions(dt,loops)
if loops == nil then loops = 100 end
--Sort in priority order
table.sort(BasicData.actors,function(a1,a2)
if a1.priority ~= a2.priority then
return a1.priority > a2.priority
end
return a1.id < a2.id
end)
--Check collide
local can_loop = true
local limit = 0
while can_loop do
--Breaking the loop
can_loop = false
limit = limit + 1
if limit >= loops then break end
--Collisions
for i=1,#BasicData.actors-1 do
for j=i+1,#BasicData.actors do
local col = BasicData.actors[i]:collide(BasicData.actors[j])
if col then can_loop = true end
end
end
end
end
EDIT: Forgot to add the file. [EDIT2] Was solved by pgimeno! Thank you for your help!