The main problem is here:
Code: Select all
-- collision?
if player.xvel ~= 0 or player.yvel ~= 0 then
player.x, player.y, _, col_len = world:move(player, player.x + dx, player.y + dy)
end
local cols, len = world:check(player, 0, 0)
if len > 0 then
player.yvel = 0
end
World:move and world:check do very similar things; if you are using one, chances are that you don't need the other. In your case I think using move is more appropiate. That leaves us with this:
Code: Select all
if player.xvel ~= 0 or player.yvel ~= 0 then
player.x, player.y, _, col_len = world:move(player, player.x + dx, player.y + dy)
end
world:move returns 4 parameters: actualX, actualY, cols & len. In lua, when a function f returns several values, you can assign them to variables by doing:
If you are not going to use one of the values, the convention is naming that variable _ (a single underscore). For example, if you don't need var3 in the previous example, you can do this:
Now back to your code: Since you are using _ on the third variable, you are basically saying "I don't need cols". But you need it. cols is what will tell you what kind of collisions you are having. You can use that to change the velocity. So start by setting it to a variable:
Code: Select all
if player.xvel ~= 0 or player.yvel ~= 0 then
local cols, len
player.x, player.y, cols, len = world:move(player, player.x + dx, player.y + dy)
end
Now you can use cols and len to check every collision using a loop. Here I am going to print the normal of each collision in the terminal (you will have to launch love from the terminal to see them):
Code: Select all
if player.xvel ~= 0 or player.yvel ~= 0 then
local cols, len
player.x, player.y, cols, len = world:move(player, player.x + dx, player.y + dy)
for i=1,len do
print(cols[i].normal.x, cols[i].normal.y)
end
end
cols
.normal.x and cols.normal.y are two vectors which indicate "on which direction" the collision happened. For example, if the collision happened with an object "to the right", then normal.x is -1, and normal.y is 0.
Once you have the normals, you can set xvel and yvel to 0 when it corresponds. For example, if the player was moving to the right, and the collision happened with an object to the right, you can reset it like this:
Code: Select all
if player.xvel ~= 0 or player.yvel ~= 0 then
local cols, len
player.x, player.y, cols, len = world:move(player, player.x + dx, player.y + dy)
for i=1,len do
if cols[i].normal.x < 0 and player.xvel > 0 then player.xvel = 0 end
end
end
Add conditions for the other 3 directions (left, up and down), and that should be enough. If you have doubts about which values the normals have, print them on the console.
Let me know if you need more help.
EDIT: I have made some changes to the simpledemo so that it now shows collision info when in debug mode. That way it uses cols instead of ignoring it.
- Screen Shot 2015-03-21 at 21.12.40 .png (77.05 KiB) Viewed 1433 times
You can see the changes in
bump's simpledemo branch.