Player's yvel is still accelerating on the "ground" [Bump]
Player's yvel is still accelerating on the "ground" [Bump]
So I'm working on a very basic platformer and decided to use kikito's bump.lua. So far it was going well (it's actually really cool) with a practice block, but I have a simple problem with probably a simple answer. If you view the .love and go off the block, you can tell the player's yvel is still accelerating even though it has hit the "ground". How do you check a collision with the block so I can reset the yvel? Is the solution afterwards to even reset the yvel?
- Attachments
-
- tiles.love
- (7.44 KiB) Downloaded 72 times
Re: Player's yvel is still accelerating on the "ground" [Bum
You can useredsled wrote:So I'm working on a very basic platformer and decided to use kikito's bump.lua. So far it was going well (it's actually really cool) with a practice block, but I have a simple problem with probably a simple answer. If you view the .love and go off the block, you can tell the player's yvel is still accelerating even though it has hit the "ground". How do you check a collision with the block so I can reset the yvel? Is the solution afterwards to even reset the yvel?
Code: Select all
local items, len = world:queryRect(l,t,w,h, filter)
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: Player's yvel is still accelerating on the "ground" [Bum
There's a simpler way to do that, without using queryRect.
The short version is this: on every frame, you use the cols attribute that you get from world:move to detect when the player is "on ground". You do so by checking the 'y' normal of each collision that you get. Then, if you are on ground, you reset the yvel to 0.
This is done in the bump demo's player code. Here's a step-by-step explanation:
UPDATE: there is a simpler solution than what I explain on this list. See explanation after EDIT 2 below:
EDIT: Now that I think about it, it's possible that the call to changeVelocityByCollisionNormal already takes care of resetting the yvel to 0 on ground collisions. It would be interesting to see if removing the call to changeVelocityByBeingOnGround to see if it changes anything (probably it won't).
EDIT 2: My suspicion was correct. changeVelocityByBeingOnGround was redundant. I have removed it from the repo. Updated explanation:
The short version is this: on every frame, you use the cols attribute that you get from world:move to detect when the player is "on ground". You do so by checking the 'y' normal of each collision that you get. Then, if you are on ground, you reset the yvel to 0.
This is done in the bump demo's player code. Here's a step-by-step explanation:
UPDATE: there is a simpler solution than what I explain on this list. See explanation after EDIT 2 below:
- At the start of every frame, when you start moving+colliding, set a player variable (which I called self.onGround) to false.
- For every collision that you get, check if you are touching ground. (You might also want to change other velocities; for example if you are moving "right" and you hit a wall to your right, the xvel should be reset to 0 too).
- To see wether the player is on ground, you see that that the collision's normal.y attribute is negative. If it is, you set self.onGround to true (remember that it was set to false at the beginning of the frame).
- After you have finished moving+colliding, you check whether you must reset yvel to 0 - you must be on the ground and not be "moving up" (otherwise you would not be able to "jump")
EDIT: Now that I think about it, it's possible that the call to changeVelocityByCollisionNormal already takes care of resetting the yvel to 0 on ground collisions. It would be interesting to see if removing the call to changeVelocityByBeingOnGround to see if it changes anything (probably it won't).
EDIT 2: My suspicion was correct. changeVelocityByBeingOnGround was redundant. I have removed it from the repo. Updated explanation:
- For every collision that you get, reset the velocities like so: if you are moving right and you collide with something that is to the right (col.normal.x is negative) then you reset the xvel to 0. And the same for the rest of velocities (right, up, down), including xvel. In player this is done in this call to changeVelocityByCollisionNormal,which is defined in the Entity class.
When I write def I mean function.
Re: Player's yvel is still accelerating on the "ground" [Bum
I'm sorry, but I can't seem to follow with your code. Could you take a look at mine and show me vaguely how to do what you suggested?
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: Player's yvel is still accelerating on the "ground" [Bum
The main problem is here:
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:
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:
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):
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:
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.
You can see the changes in bump's simpledemo branch.
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
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
Code: Select all
var1, var2, var3, var4 = f()
Code: Select all
var1, var2, _, var4 = f()
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
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
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
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.
You can see the changes in bump's simpledemo branch.
When I write def I mean function.
Who is online
Users browsing this forum: Bing [Bot] and 2 guests