Smooth movement. (SOLVED)

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
Rafer45
Prole
Posts: 12
Joined: Wed Apr 10, 2013 3:22 pm

Smooth movement. (SOLVED)

Post 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 :|
Last edited by Rafer45 on Fri Apr 12, 2013 3:10 pm, edited 1 time in total.

Code: Select all

while game.engine == "LÖVE2D" do
	game.awesome = true
	community.helpful = true
end
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: Smooth movement.

Post 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.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Smooth movement.

Post 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.
When I write def I mean function.
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: Smooth movement.

Post 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).
User avatar
Rafer45
Prole
Posts: 12
Joined: Wed Apr 10, 2013 3:22 pm

Re: Smooth movement. (SOLVED)

Post 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.

Code: Select all

while game.engine == "LÖVE2D" do
	game.awesome = true
	community.helpful = true
end
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: Smooth movement. (SOLVED)

Post 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
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Smooth movement.

Post 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.
When I write def I mean function.
User avatar
Rafer45
Prole
Posts: 12
Joined: Wed Apr 10, 2013 3:22 pm

Re: Smooth movement.

Post 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

Code: Select all

while game.engine == "LÖVE2D" do
	game.awesome = true
	community.helpful = true
end
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: Smooth movement. (SOLVED)

Post 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.
User avatar
spynaz
Party member
Posts: 152
Joined: Thu Feb 28, 2013 5:49 am

Re: Smooth movement. (SOLVED)

Post 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.
Post Reply

Who is online

Users browsing this forum: Bing [Bot], ChocolateLoxtl and 4 guests