The code I've posted may be easier to understand than ivan's solution.
But his is definitely better and it would be worth to try to understand it (I also have to dig a bit more into it
.
Just consider a major drawback of my simple code:
If you have fast player movement or low FPS (or a combination of both) which result in a player movement of
more than one pixels per update() then you might notice something strange:
The player seems to stop some pixels *before* the obstacle leaving a gap of some pixels between player and obstacle.
Consider this example:
Your frame rate is slow and the player moves quite fast, so it moves, lets say, 6 pixels per update().
The routine checks and sees, that the player moves towards an object which is in reality lets say 4 pixels away. Even though there should be no collision yet, the collision routine returns "true", thus preventing the player to move this 6 pixels.
This will result in a gap of 4 pixels between the player and the obstacle.
If your framerate is going up and down for some reason, you might also notice some unstable movement just before the obstacle, sometimes the player seems to advance a pixel more, sometimes a pixel less.
I could think of 2 solutions here: 1th the one ivan presented or 2nd this one which came to my mind:
Once a collision is detected you start a "repeat ... until" loop, which advances the player pixel per pixel towards the direction the player intented to go.
You test for a collision at each step and stop when the collision *really* happens.
There's a second drawback:
If the framerate is *really* low, let's say around 1 fps, then the routine could miss a collision and traverse an obstacle although it shouldn't.
I'm not sure if ivan's routine considers that, but I think in general this can only be prevented, if you use fixed time intervals between updates, not the plain dt delta time provided by the love.update() routine.
But you also might think that if your framerate is really *that* low, you wouldn't be able to play the game anyway
I've added some code to your program to implement the "repeat ... until" solution, there's a line in main.lua in love.update() which you can comment out to test it with low framerates:
Code: Select all
function box_update(dt)
box.left=love.keyboard.isDown("a")
box.right=love.keyboard.isDown("d")
box.up=love.keyboard.isDown("w")
box.down=love.keyboard.isDown("s")
-- normalize diagonal movement
if (box.left and box.up) or (box.left and box.down) or (box.right and box.up) or (box.right and box.down) then speed=box.speed_norm
else speed=box.speed end
if box.left then
local _x=box.x - speed * dt
while _x<box.x do
if not box_checkCollision(box.x-1,box.y) then box.x = box.x-1
else break end
end
end
if box.right then
local _x=box.x + speed * dt
while _x>box.x do
if not box_checkCollision(box.x+1,box.y) then box.x = box.x+1
else break end
end
end
if box.up then
local _y=box.y - speed * dt
while _y<box.y do
if not box_checkCollision(box.x,box.y-1) then box.y = box.y-1
else break end
end
end
if box.down then
local _y=box.y + speed * dt
while _y>box.y do
if not box_checkCollision(box.x,box.y+1) then box.y = box.y+1
else break end
end
end
end
Greets,
vitaminx