Difference between revisions of "Tutorial:Baseline 2D Platformer"

m (Edited indentation to 2 tab spaces and fixed love.keypressed function so that it's compatible with 0.10.0)
Line 8: Line 8:
 
<source lang="lua">
 
<source lang="lua">
 
function love.load()
 
function love.load()
player = { -- nice and organised.
+
  -- Nice and organised
x = 0,
+
  player = {
y = 0,
+
    x = 0,
image = love.graphics.newImage("hamster.png") -- let's just re-use this sprite.
+
    y = 0,
}
+
   
 +
    image = love.graphics.newImage("hamster.png") -- Let's just re-use this sprite
 +
  }
  
winW, winH = love.graphics.getWidth(), love.graphics.getHeight() -- this is just
+
  winW, winH = love.graphics.getWidth(), love.graphics.getHeight() -- This is just so we can draw it in a fabulous manner
-- so we can draw it in a fabulous manner.
 
 
end
 
end
  
 
function love.draw()
 
function love.draw()
love.graphics.rectangle("fill", 0, winH / 2, winW, winH / 2)
+
  love.graphics.rectangle("fill", 0, winH / 2, winW, winH / 2)
love.graphics.translate(winW / 2, winH / 2) -- you don't need to understand this
+
  love.graphics.translate(winW / 2, winH / 2) -- You don't need to understand this
  
love.graphics.draw(player.image, player.x, -player.y, 0, 1, 1, 64, 103) -- trust me
+
  love.graphics.draw(player.image, player.x, -player.y, 0, 1, 1, 64, 103) -- Trust me on the origin position. Just trust me
-- on the origin position. just trust me.
 
 
end
 
end
 
</source>
 
</source>
Line 36: Line 36:
 
Add this to your love.load function:
 
Add this to your love.load function:
 
<source lang="lua">
 
<source lang="lua">
player = {
+
player = {
...
+
  ...
y_velocity = 0,
+
  y_velocity = 0,
}
+
  ...
...
+
}
gravity = 400
+
 
jump_height = 300
+
...
 +
gravity = 400
 +
jump_height = 300
 +
...
 
</source>
 
</source>
  
Line 51: Line 54:
 
<source lang="lua">
 
<source lang="lua">
 
function love.update(dt)
 
function love.update(dt)
if player.y_velocity ~= 0 then -- we're probably jumping
+
  if player.y_velocity ~= 0 then -- we're probably jumping
player.y = player.y + player.y_velocity * dt -- dt means we wont move at
+
    player.y = player.y + player.y_velocity * dt -- dt means we wont move at different speeds if the game lags
-- different speeds if the game lags
+
    player.y_velocity = player.y_velocity - gravity * dt
player.y_velocity = player.y_velocity - gravity * dt
+
if player.y < 0 then -- we hit the ground again
+
    if player.y < 0 then -- we hit the ground again
player.y_velocity = 0
+
      player.y_velocity = 0
player.y = 0
+
      player.y = 0
end
+
    end
end
+
  end
 
end
 
end
  
function love.keypressed(key)
+
function love.keypressed(key, scancode, isrepeat)
if key == " " then
+
  if key == " " then
if player.y_velocity == 0 then -- we're probably on the ground, let's jump
+
    if player.y_velocity == 0 then -- we're probably on the ground, let's jump
player.y_velocity = jump_height
+
      player.y_velocity = jump_height
end
+
    end
end
+
  end
 
end
 
end
 
</source>
 
</source>
Line 78: Line 81:
  
 
<source lang="lua">
 
<source lang="lua">
player = {
+
player = {
...
+
  ...
jetpack_fuel = 0.5, -- note: not an actual jetpack. variable is the time (in seconds)
+
  jetpack_fuel = 0.5, -- Note: not an actual jetpack. variable is the time (in seconds) you can hold spacebar and jump higher.
-- you can hold spacebar and jump higher.
+
  jetpack_fuel_max = 0.5,
jetpack_fuel_max = 0.5,
+
  ...
}
+
}
 
</source>
 
</source>
  
 
Now, we remove our love.keypressed callback. We won't exact time, which is just bothersome to find out using keypressed and keyreleased. Instead, we'll move that logic to love.update.
 
Now, we remove our love.keypressed callback. We won't exact time, which is just bothersome to find out using keypressed and keyreleased. Instead, we'll move that logic to love.update.
 
....glhf
 
  
 
<source lang="lua">
 
<source lang="lua">
 
function love.update(dt)
 
function love.update(dt)
if player.jetpack_fuel > 0 -- we can still move upwards
+
  if player.jetpack_fuel > 0 and love.keyboard.isDown(" ") then -- we can still move upwards and we're actually holding space
and love.keyboard.isDown(" ") then -- and we're actually holding space
+
    player.jetpack_fuel = player.jetpack_fuel - dt -- decrease the fuel meter
player.jetpack_fuel = player.jetpack_fuel - dt -- decrease the fuel meter
+
    player.y_velocity = player.y_velocity + jump_height * (dt / player.jetpack_fuel_max)
player.y_velocity = player.y_velocity + jump_height * (dt / player.jetpack_fuel_max)
+
  end
end
+
 
if player.y_velocity ~= 0 then -- we're probably jumping
+
  if player.y_velocity ~= 0 then -- we're probably jumping
player.y = player.y + player.y_velocity * dt -- dt means we wont move at
+
    player.y = player.y + player.y_velocity * dt -- dt means we wont move at different speeds if the game lags
-- different speeds if the game lags
+
    player.y_velocity = player.y_velocity - gravity * dt
player.y_velocity = player.y_velocity - gravity * dt
+
   
if player.y < 0 then -- we hit the ground again
+
    if player.y < 0 then -- we hit the ground again
player.y_velocity = 0
+
      player.y_velocity = 0
player.y = 0
+
      player.y = 0
player.jetpack_fuel = player.jetpack_fuel_max
+
      player.jetpack_fuel = player.jetpack_fuel_max
end
+
    end
end
+
  end
end</source>
+
end
 +
</source>
  
 
[[Category:Tutorials]]
 
[[Category:Tutorials]]
{{#set:LOVE Version=0.7.2}}
+
{{#set:LOVE Version=0.10.0}}
 
{{#set:Description=A basic implementation of platformer-style jumping physics.}}
 
{{#set:Description=A basic implementation of platformer-style jumping physics.}}
  
 
== Other languages ==
 
== Other languages ==
 
{{i18n|Tutorial:Platformer_Jumping}}
 
{{i18n|Tutorial:Platformer_Jumping}}

Revision as of 00:27, 31 January 2016

O.png This tutorial is incomplete. Do you want to complete it?  


Due to a request on IRC, this guide has been written to show a basic implementation of platformer-style jumping physics for a player character.

The tutorial is fairly basic and even a newbie should have no issue understanding.

First, let's start off with our basic code, without any jumping.

function love.load()
  -- Nice and organised
  player = {
    x = 0,
    y = 0,
    
    image = love.graphics.newImage("hamster.png") -- Let's just re-use this sprite
  }

  winW, winH = love.graphics.getWidth(), love.graphics.getHeight() -- This is just so we can draw it in a fabulous manner
end

function love.draw()
  love.graphics.rectangle("fill", 0, winH / 2, winW, winH / 2)
  love.graphics.translate(winW / 2, winH / 2) -- You don't need to understand this

  love.graphics.draw(player.image, player.x, -player.y, 0, 1, 1, 64, 103) -- Trust me on the origin position. Just trust me
end
Note: The hamster.png file is File:Resource-HamsterBall.png.

You should get something that looks like this:

PlatformerJumpingStepOne.jpg

Now, it's time to make it jump. To do this, we'll give the player an upwards velocity, create a gravity variable and a jump height variable.

Add this to your love.load function:

player = {
  ...
  y_velocity = 0,
  ...
}

...
gravity = 400
jump_height = 300
...

When the player presses the jump button (spacebar for this tutorial) we will increase the x_velocity by the jump_height.

Then, we will move the player upwards while decreasing the velocity by the gravity. We'll add a love.update and love.keypressed callback to make this work.

function love.update(dt)
  if player.y_velocity ~= 0 then -- we're probably jumping
    player.y = player.y + player.y_velocity * dt -- dt means we wont move at different speeds if the game lags
    player.y_velocity = player.y_velocity - gravity * dt
		
    if player.y < 0 then -- we hit the ground again
      player.y_velocity = 0
      player.y = 0
    end
  end
end

function love.keypressed(key, scancode, isrepeat)
  if key == " " then
    if player.y_velocity == 0 then -- we're probably on the ground, let's jump
      player.y_velocity = jump_height
    end
  end
end

Yay, jumping!

However, this is not true platformer-style jumping. In a lot of platformers, holding the jump key makes you jump higher. Let's implement this.

First, let's create a new player variable in love.load.

player = {
  ...
  jetpack_fuel = 0.5, -- Note: not an actual jetpack. variable is the time (in seconds) you can hold spacebar and jump higher.
  jetpack_fuel_max = 0.5,
  ...
}

Now, we remove our love.keypressed callback. We won't exact time, which is just bothersome to find out using keypressed and keyreleased. Instead, we'll move that logic to love.update.

function love.update(dt)
  if player.jetpack_fuel > 0 and love.keyboard.isDown(" ") then -- we can still move upwards and we're actually holding space
    player.jetpack_fuel = player.jetpack_fuel - dt -- decrease the fuel meter
    player.y_velocity = player.y_velocity + jump_height * (dt / player.jetpack_fuel_max)
  end

  if player.y_velocity ~= 0 then -- we're probably jumping
    player.y = player.y + player.y_velocity * dt -- dt means we wont move at different speeds if the game lags
    player.y_velocity = player.y_velocity - gravity * dt
    
    if player.y < 0 then -- we hit the ground again
      player.y_velocity = 0
      player.y = 0
      player.jetpack_fuel = player.jetpack_fuel_max
    end
  end
end


Other languages