Page 1 of 2

Smooth movement. (SOLVED)

Posted: Fri Apr 12, 2013 4:40 am
by Rafer45
My first post!

I have been learning LÖVE through sockmunkeedev's tutorials, but sometimes the "narrator" or "tutor" (don't know what term I should use) tells the audience to look up things he can't explain.
I've got some programming experience with javascript (Made rock, paper, scissor, lizard, Spock with vannila JavaScript :nyu:)
Now, this is the video that stumped me. Note I had only seen the basic tutorials before this one:
[youtube]http://www.youtube.com/watch?v=zCAYHKYDPr8[/youtube]
I was able to write the code for x and y axes, but i didn't understand a lot that was going on. Why was 50 speed suddenly so fast? wahat the hay did this line mean?

Code: Select all

player.xvel = player.xvel * (1 - math.min(dt*player.friction, 1))
and How did it actually work? I understood that you raised velocity so it accelerated, but it didn't quite click.
Help?

Also, if I'm breaking any forum rules with this post, I am terribly sorry :|

Re: Smooth movement.

Posted: Fri Apr 12, 2013 5:53 am
by micha
The key idea of smooth movement is to change velocity gradually not in jumps.

Before doing smooth movement you usually have something like this:

Code: Select all

if arrowKeyIsPressed then
  movePlayerAtConstantVelocity
else
  dontMovePlayer
end
That means that in the moment you press the button, the player accelerates from zero to full speed in no time. For some sorts of games, this is alright (old Zelda games, Megaman), but not for others. Smooth movements means you need some time to change from zero velocity to full velocity.

Now for the line of code, you are struggling with:

Code: Select all

player.xvel = player.xvel * (1 - math.min(dt*player.friction, 1))
First, ignore the math.min and look at that:

Code: Select all

player.xvel = player.xvel * (1 - dt*player.friction)
this can be expanded and you get:

Code: Select all

player.xvel = player.xvel - player.xvel * dt * player.friction
That means that the player's x-velocity is changed by (player.xvel*dt*player.friction). This term defines how fast the player slows down. You can see, that if the player is very fast, then he slows down fast. If he is slow (player.xvel almost zero) then the slowing down is slow.

Now for the math.min. This function returns the smaller of the two values inside. So

Code: Select all

math.min(dt*player.friction,1)
returns dt*player.friction if it is smaller than 1, and 1 otherwise. Putting this into the formula simply makes the code a bit shorter. The point is, if the player is moving left and is then slowed down due to acceleration, you don't want the player to "overshoot" and start moving to the right. This would happen if the term in the brackets

Code: Select all

(1 - math.min(dt*player.friction, 1))
becomes negative. In that case, the velocity would change sign (direction). To avoid that, this math.min-function ensures that if the term becomes negativ, then it is put to zero.

Re: Smooth movement.

Posted: Fri Apr 12, 2013 9:57 am
by kikito
Believe it or not, a little physics might help here.

You know what velocity is. Velocity = Space * Time. In other words, how much space something travels in a given time.

In love, something moving with a velocity {vx,vy} moves like this:

Code: Select all

obj.x = obj.x + obj.vx * dt
obj.y = obj.y + obj.vy * dt
vx and vy can be positive (right/bottom), negative(left/top) or 0 (no movement).

Now, when velocity changes over time, that also has a name. It's called Acceleration. Acceleration = Velocity * Time. It's the "velocity of the velocity": How much the velocity of something changes given a period of time. In code, if {ax,ay} is the acceleration, the velocity of an object would change like this:

Code: Select all

obj.vx = obj.vx + obj.ax * dt;
obj.vy = obj.vy + obj.ay * dt;
ax and ay can be positive (velocity increases with time), negative (velocity decreases with time) or 0 (velocity stays constant).

If you put everything together:

Code: Select all

local player = {x=400,y=300,vx=0,vy=0,ax=0,ay=0}
function love.draw()
  love.graphics.circle("line", player.x, player.y, 50)
end
function love.update(dt)
  if(love.keyboard.isDown('up'))    then player.ay = player.ay - 5*dt end
  if(love.keyboard.isDown('down'))  then player.ay = player.ay + 5*dt end
  if(love.keyboard.isDown('left'))  then player.ax = player.ax - 5*dt end
  if(love.keyboard.isDown('right')) then player.ax = player.ax + 5*dt end

  player.vx = player.vx + player.ax * dt
  player.vy = player.vy + player.ay * dt
  player.x = player.x + player.vx * dt
  player.y = player.y + player.vy * dt
end
The code above allows you to (barely) move a player changing its acceleration, not its velocity. This makes it very unmanageable, since velocity keeps changing up/down, even when acceleration stops changing. But I hope you get the idea.

Re: Smooth movement.

Posted: Fri Apr 12, 2013 1:15 pm
by micha
kikito wrote:Velocity = Space * Time.
Small correction: You probably mean "Velocity = Space / Time"

I prefer "Displacement / Time", because space is volumetric. Space/Time would be the correct description for a flow in cubic meters per second (e.g. how much water comes out of a tap).

Re: Smooth movement. (SOLVED)

Posted: Fri Apr 12, 2013 3:15 pm
by Rafer45
Thanks for the help! It feels great to finally undestand the logic behind it. You were very clear, especially by stating x(1 - d) as (x - xd)
I'd like to give you both karma, but I can't seem to find the button.
Also, whgat is it that every single image has "obey"? Just curious.

If this is outruled for being out of topic, please inform me so I can delete it.

Re: Smooth movement. (SOLVED)

Posted: Fri Apr 12, 2013 3:24 pm
by micha
Rafer45 wrote:Also, whgat is it that every single image has "obey"? Just curious.

If this is outruled for being out of topic, please inform me so I can delete it.
I say: No worries. The answer lies in this thread: Obey

Re: Smooth movement.

Posted: Fri Apr 12, 2013 3:29 pm
by kikito
micha wrote:
kikito wrote:Velocity = Space * Time.
Small correction: You probably mean "Velocity = Space / Time"

I prefer "Displacement / Time", because space is volumetric. Space/Time would be the correct description for a flow in cubic meters per second (e.g. how much water comes out of a tap).
+1 to everything you said.

Re: Smooth movement.

Posted: Wed Apr 24, 2013 3:33 pm
by Rafer45
Oh I'm sorry about this, but I'd like to ask one more thing. How can I make people raise friction without having it stuck on 1 or pushing the player back?
It's for a physics project on friction and movement

Re: Smooth movement. (SOLVED)

Posted: Wed Apr 24, 2013 4:10 pm
by micha
The friction itself may have any value, even larger than 1. Only the product dt*friction has to be smaller than 1.

However there is nothing "between" having dt*friction equal 1 and moving the player backwards. The factor dt*fiction tells you how much of the current velocity is removed in one frame. So if it is 1, all of the velocity is removed and the player stops instantly. If it is larger than one then the new velocity is backwards.

Re: Smooth movement. (SOLVED)

Posted: Wed May 01, 2013 3:15 am
by spynaz
This is the function I use for my games and it works perfectly and friction works too. I'd 50 speed and 7 friction is about perfect in this case.

Code: Select all

local dt1 = math.min(dt, 0.07)

frame = dt1 * 30
player.x = player.x + player.xVel * frame
player.xVel = player.xVel * (1 - math.sin(dt * player.friction, 1)) 
EDIT: Opps, it's already solved. Well, anyway, you can use my code if you want.