Programming Games

Class 7 - Debugging, Working with Tiles and the Camera

Play homework

Blake Andrews’s games

Suggested:

Katamari Damacy

Sokpop games

Topics

Description

In this week we cover creating a map out of a series of drawn sprites and then how to draw that map to the screen. We also use the camera, aiming it at the player, so that we can create maps that are bigger than just a single screen, and that the player can navigate through.Finally, we learn how to get information about the tiles on the map, and use it to detect collision. We also cover various debugging strategies when creating a complex program.

Class notes

Formatting Your Code

Make your code easier to read. You can alter some parts of the coding environment.

config

Let’s alter the default spacing of tabs.

config tab_width 2

Alternatively, set it to 3 or 4.

Setting a reasonable tab_width will make it easier to scan our code when we are browsing it and looking for particularly important (or ignoring less important) sections as we work on our code. If we are taking a high level view of the overall functionality of our code, we look on the function names, which will be toward the left and in one color. If we need to zoom in on the code of a particular function, we will look to the right side where that code is inside the function.

config draw_tabs on

This will turn on the (previously) invisible tab characters, which helps us visually scan and organize our code.

Working with the Camera

I’ve created two sprites: a player sprite and a wall sprite. Then I opened the map editor to draw a level with the wall sprite. My level goes beyond just the single 128 by 128 pixel square. By using the hand drag tool I can draw much farther. To be able to see this part of the level, I’ll need to be able to position the camera at different locations.

One common way to do this is to have the camera follow the player character as it moves around, keeping the player always in the center of the screen as it moves around the level.

We set up our game loop like any other game.

function _init()
	p={x=64,y=64}
end

function _update()
	move_player()
end

In our _draw() function is where we both draw the map and use the camera() function to follow the player.

The camera() function takes two arguments, a -x and -y to offset the drawing screen. In other words, the camera will move to the x,y location stated. Since our player starts in the center of the screen, we will subtract 64 from x and 64 from y to keep it centered even as the player moves around. Try moving the player around and consider what is happening as you move to the right for example, and the player’s x increases.

function _draw()
	cls()
	map()
	camera(p.x-64,p.y-64)
	spr(1,p.x,p.y)
end

Even though as you press right the player’s x increases, we are subtracting 64 so the player is centered.

Try changing the camera() function line to see what happens with a fixed location for example:

camera(64,64)

Tile flags

In the past, we moved the player character whenever we held down an arrow key.

function move_player()
	if btn(⬆️) then p.y-=1 end
	if btn(⬇️) then p.y+=1 end
	if btn(➡️) then p.x+=1 end
	if btn(⬅️) then p.x-=1 end
end

On the sprite sheet, you’ll see 8 radio buttons that can be toggled on and off. These are called “flags” and function as a kind of boolean.

We will toggle on the first flag next to the dungeon wall tag. Select your wall tile and click the radio button on the left so it turns red.

Let’s first make an in-between step. We will make temporary values that will hold what should be the new player x and y positions if the player presses the button. Then we’ll test to see if a wall tile is in that location, by checking to see if the tile at that position has its first flag on. If the wall is there, we do nothing. If no flag, then we change the player’s x and y to the temporary x and y we set earlier.

The concept should look something like this:

--create a newx, newy at the player's position
newx=p.x
newy=p.y
--set the newx or new y to the possible position the player will move into if there is no block there
if btn(R) then newx=p.x+1 end --for example
if btn(L) then newx=p.x-1 end 
if btn(U) then newy=p.y-1 end 
if btn(D) then newy=p.y+1 end 

Next we need to check if a wall is at that position

if can_move(newx,newy) then
  p.x=newx
  p.y=newy
else
  --player is blocked, can't move
end

Our can_move() function

function can_move(x,y)
  local w=7
  local h=7
	
  if solid(x,y) or solid(x+w,y) or solid(x,y+h) or solid(x+w,y+h) then 
    return false 
  else
    return true
  end
end

We use an offset 7 because we are on a grid. We will have to round down.

--adapted from mboffin pixel collision
function solid(x,y)
 local map_x=flr(x/8)
 local map_y=flr(y/8)
 local map_sprite=mget(map_x,map_y)
 local flag=fget(map_sprite)
 
 --tests whether the flag is 1, returns true or false
 return flag==1
end

Debugging Strategies

When we are having trouble with our code, it helps to print out our variables, and/or trigger a sound effect. But what if we want to understand how multiple objects are interacting, for example?

In those cases, I tend to make an overlay with debugging information:

function _draw()
  for i=1,#enemies do
    spr(1,enemies[i].x,enemies[i].y)
    --draw each enemy's speed for example, to the right
    print(enemies[i].speed,enemies[i].x+8,enemies[i].y)
  end
end

Other times, I may make a place on the screen displaying my variables as I debug:

function _draw()
  debug()
end

function debug()
  rectfill(100,0,128,20)
  
  print("x: "..p.x.." y: "..p.y,100,0)
  print("speed: "..p.speed.." score: "..p.score,100,10)
end

Asking for help

Now maybe you have tried the above method of debugging by printing out your variables, and you still can’t fix it and can’t figure out why it won’t work, and you feel like you need help. Well then lucky for you there are plenty of people on the internet that are happy to help you, in addition to your professor and Learning Assistant. Other places to ask your question are on forums or discords for example. But asking a question is not simply asking “Hey guys I got this bug where this happens, what do I do?”. You need to provide them information that they can use to help you. For example:

But before you ask for help you may want to search for your question. It just might be that it’s a common question and it has been answered multiple times.

And remember, no one is obligated to help you, and the ones that do all do it for free, so be kind :)


Rubber duck debugging

You could also get a rubber duck. There’s this thing called rubber duck debugging. The idea is that when you explain what you’re doing in your code, you often realize what you’re doing wrong and fix the bug yourself. So instead of explaining it to someone, you explain it to your rubber duck.


Summary

We can use print to find the source of our bug. Error message tell us exactly what is going wrong. Syntax errors are errors that occur because it can’t “read” the code correctly. Indentation is useful because it prevents us from getting end of line-errors. We can ask for help on the internet but we should provide enough information on what is going on to make it less difficult on the people helping us.


Code homework

Play robotfindskitten. It is available for several dozen different operating systems, game consoles, handhelds, emulators, playable online. I recommend this first link to play it in a DOS emulator online.

robotfindskitten (rfk) is a “Zen simulation”, originally written by Leonard Richardson for MS-DOS. It is a free video game with an ASCII interface in which the user (playing the eponymous robot and represented by a number sign “#”) must find kitten (represented by a random character) on a field of other random characters. Walking up to items allows robot to identify them as either kitten, or any of a variety of “Non-kitten Items” (NKIs) with whimsical, strange or simply random text descriptions. It is not possible to lose (though there is a patch that adds a 1 in 10 probability of the NKI killing robot). Simon Carless has characterized robotfindskitten as “less a game and more a way of life … It’s fun to wander around until you find a kitten, at which point you feel happy and can start again”.

robotfindskitten website.

Your assignment:

Possible Strategies:

Credits