Difference between revisions of "Tutorial:Gridlocked Player"

Line 1: Line 1:
In this tutorial, we will create a VERY basic game wherein you can move a "player" around the screen in fixed increments. This could be useful if you are creating a game that is tile-based, and want your player to stay aligned to the grid.
+
In this tutorial, we will create a VERY basic game wherein you can move a "player" around the screen in fixed increments, but the player graphic moves in smaller increments. This could be useful if you are creating a game that is tile-based, and want your player to stay aligned to the grid, but don't want them to appear to teleport around.
  
== Starting Elements ==
+
== Starting Code ==
  
To start with, we need to create a player. The player will have several aspects before we're done, so we're going to make the player variable a table.
+
To start with, we need to create a player. The player will have several aspects before we're done, so we're going to make the player variable a table inside of [[love.load]]().
 
<source lang="lua">
 
<source lang="lua">
 
function love.load()
 
function love.load()
Line 10: Line 10:
 
</source>
 
</source>
  
Next we'll need to see what we're doing. We can render the player as a rectangle using love.graphics.rectangle() in love.draw().
+
Next we'll need to see what we're doing. We can render the player as a rectangle using [[love.graphics.rectangle]]() in [[love.draw]]().
 
<source lang="lua">
 
<source lang="lua">
 
function love.draw()
 
function love.draw()
Line 31: Line 31:
 
</source>
 
</source>
  
Now that the player has position, let's add in some controls using love.keypressed(). All we do is check to see if the key matches, and change the a value in the player table.
+
Now that the player has position, let's add in some controls using [[love.keypressed]](). All we do is check to see if the key matches, and change the a value in the player table.
 
<source lang="lua">
 
<source lang="lua">
 
function love.keypressed(key, uni)
 
function love.keypressed(key, uni)
Line 40: Line 40:
 
</source>
 
</source>
  
We can expand this to more keys using elseif. Notice that everything is in units of 32, a common time size.
+
So we now have a little square that can teleport down by one grid unit (32 pixels in our case, the same length that we made our player).
 +
 
 +
== Expansion ==
 +
 
 +
We can expand this to more keys using elseif. Notice that everything is still in units of 32, a common tile size that plays nice with [[PO2_Syndrome]].
 
<source lang="lua">
 
<source lang="lua">
 
function love.keypressed(key, uni)
 
function love.keypressed(key, uni)
Line 94: Line 98:
 
</source>
 
</source>
  
As you probably noticed, you probably can't see any difference. We need dt to control speed, and then a speed property to further control that:
+
As you probably noticed, you probably can't see any difference. We need to use [[love.update]]'s [[dt]] parameter to control speed, by multiplying the difference of the positions by dt:
 +
<source lang="lua">
 +
function love.update(dt)
 +
player.act_y = player.act_y - ((player.act_y - player.grid_y) * dt)
 +
player.act_x = player.act_x - ((player.act_x - player.grid_x) * dt)
 +
end
 +
</source>
 +
 
 +
Still not quite right though. Now the player is unbearably slow (but at least he's consistent from computer to computer!). Let's give the player a speed attribute to control how fast he moves, by multiplying dt by the speed:
 +
<source lang="lua">
 +
function love.load()
 +
player = {
 +
grid_x = 256,
 +
grid_y = 256,
 +
act_x = 200,
 +
act_y = 200,
 +
speed = 10
 +
}
 +
end
 +
 
 +
function love.update(dt)
 +
player.act_y = player.act_y - ((player.act_y - player.grid_y) * player.speed * dt)
 +
player.act_x = player.act_x - ((player.act_x - player.grid_x) * player.speed * dt)
 +
end
 +
</source>
 +
 
 +
== Putting it all together ==
 +
 
 +
Here is the full code:
 
<source lang="lua">
 
<source lang="lua">
 
function love.load()
 
function love.load()
Line 126: Line 158:
 
end
 
end
 
end
 
end
 
</source>
 
 
== Polishing Touches ==
 
 
There are several ways this could be improved.
 
<source lang="lua">
 
 
</source>
 
</source>
  
 +
There are several ways this could be improved. The art could be touched up, of course, using the techniques covered in this article: [http://tommybrunn.com/2011/01/how-to-make-placeholder-art/] We could also implement some extra controls, such as binding the Escape key to love.events.push('q'), which would quit the game. We could keep the player on screen by checking that grid_x never dips below 0 or above 800, that kind of thing. But for the purposes of this tutorial we have enough already.
  
 
== See Also ==
 
== See Also ==
 +
How to make placeholder art suck less: [http://tommybrunn.com/2011/01/how-to-make-placeholder-art/]
  
 
[[Category:Tutorials]]
 
[[Category:Tutorials]]

Revision as of 15:50, 26 July 2011

In this tutorial, we will create a VERY basic game wherein you can move a "player" around the screen in fixed increments, but the player graphic moves in smaller increments. This could be useful if you are creating a game that is tile-based, and want your player to stay aligned to the grid, but don't want them to appear to teleport around.

Starting Code

To start with, we need to create a player. The player will have several aspects before we're done, so we're going to make the player variable a table inside of love.load().

function love.load()
	player = {}
end

Next we'll need to see what we're doing. We can render the player as a rectangle using love.graphics.rectangle() in love.draw().

function love.draw()
	love.graphics.rectangle("fill", 0, 0, 32, 32)
end

Let's fill in the player table a little so that the player has a position. Note that we're using the shorthand way of putting variables into a table: just define them inside the curly brackets, using commas to separate them.

function love.load()
	player = {
		x = 256,
		y = 256
	}
end

function love.draw()
	love.graphics.rectangle("fill", player.x, player.y, 32, 32)
end

Now that the player has position, let's add in some controls using love.keypressed(). All we do is check to see if the key matches, and change the a value in the player table.

function love.keypressed(key, uni)
	if key == "down" then
		player.y = player.y + 32
	end
end

So we now have a little square that can teleport down by one grid unit (32 pixels in our case, the same length that we made our player).

Expansion

We can expand this to more keys using elseif. Notice that everything is still in units of 32, a common tile size that plays nice with PO2_Syndrome.

function love.keypressed(key, uni)
	if key == "up" then
		player.y = player.y - 32
	elseif key == "down" then
		player.y = player.y + 32
	elseif key == "left" then
		player.x = player.x - 32
	elseif key == "right" then
		player.x = player.x + 32
	end
end

So we now have a happy little square that can jump around the screen as fast as you can hit the keyboard. Now let's add in the smooth transitions. To do this, we're going to need to shift up the variables in the player table. Don't forget that this will affect all reference to the player table.

There are two things that we will now need. One, we need actual XY coordinates as opposed to the gridlocked coordinates that will now serve as destination coordinates. Two, we need to update the actual coordinates in love.update() to move towards the destination coordinates. We can do that with a simple math problem:

	actual_x = actual_x - (actual_x - destination_x)

Or, in real Lua this time:

function love.load()
	player = {
		grid_x = 256,
		grid_y = 256,
		act_x = 200,
		act_y = 200
	}
end

function love.update(dt)
	player.act_y = player.act_y - (player.act_y - player.grid_y)
	player.act_x = player.act_x - (player.act_x - player.grid_x)
end

function love.draw()
	love.graphics.rectangle("fill", player.act_x, player.act_y, 32, 32)
end

function love.keypressed(key, uni)
	if key == "up" then
		player.grid_y = player.grid_y - 32
	elseif key == "down" then
		player.grid_y = player.grid_y + 32
	elseif key == "left" then
		player.grid_x = player.grid_x - 32
	elseif key == "right" then
		player.grid_x = player.grid_x + 32
	end
end

As you probably noticed, you probably can't see any difference. We need to use love.update's dt parameter to control speed, by multiplying the difference of the positions by dt:

function love.update(dt)
	player.act_y = player.act_y - ((player.act_y - player.grid_y) * dt)
	player.act_x = player.act_x - ((player.act_x - player.grid_x) * dt)
end

Still not quite right though. Now the player is unbearably slow (but at least he's consistent from computer to computer!). Let's give the player a speed attribute to control how fast he moves, by multiplying dt by the speed:

function love.load()
	player = {
		grid_x = 256,
		grid_y = 256,
		act_x = 200,
		act_y = 200,
		speed = 10
	}
end

function love.update(dt)
	player.act_y = player.act_y - ((player.act_y - player.grid_y) * player.speed * dt)
	player.act_x = player.act_x - ((player.act_x - player.grid_x) * player.speed * dt)
end

Putting it all together

Here is the full code:

function love.load()
	player = {
		grid_x = 256,
		grid_y = 256,
		act_x = 200,
		act_y = 200,
		speed = 10
	}
end

function love.update(dt)
	player.act_y = player.act_y - ((player.act_y - player.grid_y) * player.speed * dt)
	player.act_x = player.act_x - ((player.act_x - player.grid_x) * player.speed * dt)
end

function love.draw()
	love.graphics.rectangle("fill", player.act_x, player.act_y, 32, 32)
end

function love.keypressed(key, uni)
	if key == "up" then
		player.grid_y = player.grid_y - 32
	elseif key == "down" then
		player.grid_y = player.grid_y + 32
	elseif key == "left" then
		player.grid_x = player.grid_x - 32
	elseif key == "right" then
		player.grid_x = player.grid_x + 32
	end
end

There are several ways this could be improved. The art could be touched up, of course, using the techniques covered in this article: [1] We could also implement some extra controls, such as binding the Escape key to love.events.push('q'), which would quit the game. We could keep the player on screen by checking that grid_x never dips below 0 or above 800, that kind of thing. But for the purposes of this tutorial we have enough already.

See Also

How to make placeholder art suck less: [2]