!Edit! with workaround below
kikito wrote: ↑Wed Aug 30, 2017 6:36 pm
MadByte wrote: ↑Wed Aug 30, 2017 5:57 pm
it seems like "cross" doesn't allow me to teleport using world:update, while setting the filter to any of the others result in the object to teleport where I want it to go
That should not happen.
world:update doesn't even look at filters.
If you can, please provide a .love example showing this behavior. Other than that, the only suggestion I have is trying to remove other stuff that you might be doing before/after calling update.
Thanks for your quick response.
I guess I may be doing something I shouldn't do in my code then. I can provide a *.love but everything is pretty much splitted into different files, so it might be a pain in the a** to find the problem. Here it is anyway:
Relevant snippets:
Code: Select all
-- OBJECT.lua
local updateCollisionWorld = function(self)
if not self.collidable then return end
if self.collisionWorld:hasItem(self) then self.collisionWorld:update(self, self.x, self.y, self.width, self.height)
else print("Unable to update collision world for Obj ID'"..tostring(self.type)..", "..tostring(self.id).."': object not found!") end
end
function Object:setPosition(x, y)
self.x = x or self.x or 0
self.y = y or self.y or 0
updateCollisionWorld(self)
end
function Object:move(dx, dy)
local newx, newy = self.x + dx, self.y + dy
if self.x == newx and self.y == newy then return end
if self.velocity.y ~= 0 then self.onGround = false end
if self.collidable then newx, newy = self:processCollisions(newx, newy) end
self.x = newx
self.y = newy
end
function Object:processCollisions(x, y)
local newx, newy = x, y
local wx, wy, cols, len = self.collisionWorld:move(self, newx, newy, self.filter)
if len > 0 then
for i=1, #cols do
local other = cols[i].other
if self.resolveCollision and other.collidable then
self:resolveCollision(other)
end
end
newx = wx
newy = wy
else
self.onGround = false
end
return newx, newy
end
-- ACTOR.lua
function Actor:filter(other)
if other.type == "Wall" then return "slide" end
if other.type == "Portal" then return "cross" end
end
function Actor:resolveCollision(other)
if other.type == "Wall" then
-- Ground collision
if self.y+self.height <= other.y then
self.onGround = true
self.velocity.y = 0
end
elseif other.type == "Portal" then
other:teleport(self)
end
end
-- PORTAL.lua
function Portal:teleport(object)
local dx, dy = self.destination:getPosition()
local dw, dh = self.destination:getDimensions()
if self.used then return end
self:use()
if self.destination then self.destination:use() end
object:setPosition(dx+dw/2 - object.width/2, dy+dh/2 - object.height/2)
end
Edit Okay I found my problem. It's the Object:processCollision method I posted above. To be more specific, it's this part:
Code: Select all
local wx, wy, cols, len = self.collisionWorld:move(self, newx, newy, self.filter)
if len > 0 then
for i=1, #cols do
local other = cols[i].other
if self.resolveCollision and other.collidable then
self:resolveCollision(other) -- in here I try to teleport the player(actor) as result of an detected collision...
end
end
newx = wx -- ... but here I basically ignore the changes I made to the position
newy = wy -- in the resolveCollision method and use the old ones instead.
else
To solve it I just let the resolveCollision method return the new x and y position and I use them as newx and newy instead of wx, wy.
It works but I hate the way it is done... I would love to hear some better ideas from you guys..
And what I still don't understand is why does it work without these changes if I use "touch" or "slide" instead of "cross" ?