dark mode light mode Search Menu
Search

TIC-80 Maps and Music

Sagie on Flickr

This issue, we’re back to working on TIC-80, the fantasy computer for making retro games!

As a refresher, last time we started the basics of a platformer. We talked about how to make a character react to gravity and make the ground solid. We also played with the sound wave generator in order to make custom sound effects. This time we’ll be talking about:

  • How to use the full map system in order to have more than one screen for our game
  • How to refactor the code we wrote last time so we can more easily add features
  • How to use the music tracker to create a little background tune in our game

As a refresher, our code from last time looked like:

t=0
x=96
y=0
vy=0
 
function TIC()
   cls(0)
   map(0,0)
   if btn(2) then x=x-1 end
   if btn(3) then x=x+1 end
 
   if mget(x//8,(y+6)//8) == 2 or
      (mget(x//8,(y+6)//8) == 1) 
   then vy = 0 
   else vy = vy +1 end
 
   if btn(0) and mget(x//8,(y+6)//8) == 2
   then 
      vy=-8
      sfx(0,"C#4",20) 
   end
   y = y + vy
   spr(3+t%60//30,x,y,0,1)
   t=t+1
end

We used a number of global variables – x, y, vy — to represent the state of the player: their x and y coordinates and their velocity in the y direction. We then wrote a main game loop, the TIC function, that handled keyboard inputs for movement. We drew the one screen we painted with a call to map(0,0). Our code used the mget function extensively to ask TIC what kind of tile was in a location: we used this to figure out if we were standing on the ground.

This time around we’ll be moving between screens. As a reminder, in TIC-80 you have a map editor that shows you the full map of the game, split visually into a bunch screen-sized chunks:

What we want is for the player to move across this big map as they move left and right or up and down.

There are multiple ways to do this. I’m showing a way that I personally think is pretty simple, but linked below is another tutorial by Bruno Oliveira that takes a very different approach to handling levels and multiple screens in TIC. Check his platformer out and see which way you like better!

In our version, we’ll be treating the screen-sized segments you can see in the map editor as individual screens in our game and we’ll switch between them as the player moves. If their y-coordinate is less than 0, we’ll move to the screen above. If their y-coordinate is greater than 136, we’ll move to the screen below. Similarly if the x-coordinate is less than 0, we’ll move to the screen to the left and if it’s greater than 240 we’ll move to the screen to the right. In terms of retro games, this means we’re treating screens more like Megaman than Mario!

First, we’ll add two more global variables at the top of our code. This time we’ll call them mapIndexX and mapIndexY. We’ll use them to keep track of which screen we’re on. Initialize them both to 0 like in the following:

mapIndexX = 0
mapIndexY = 0

These variables are like macro x and y coordinates. The mapIndexX and mapIndexY variables are both 0 at the upper-left corner of the map, increasing to 7 and 7 for the bottom-right corner of the map.

Next, we write a helper function to figure out what kind of tile is currently drawn to a part of the screen, calculated from x and y coordinates and the values of the mapIndex variables.

function currTile(x,y)
		local realX = x + 240*mapIndexX
		local realY = y + 136*mapIndexY
		return mget(realX//8,realY//8)
end

We can use this currTile function to refactor out our constant tests for whether our player is touching the ground.

function isGround(x,y)
 local t = currTile(x,y)
	return t == 1 or 
	       t == 2 or 
	       t == 11 or 
	       t == 12
end

If you’re following along, change the numbers in this function to be the indices of all the ground sprites you’re using in your game!

Now we can finally mess around with the main game loop to finish our refactoring and make the game switch screens as the player moves.

function TIC()
  cls(0)
  map(30*mapIndexX,17*mapIndexY)
  if btn(2) 
   then x=x-1
	if isGround(x,y) 
	then x = x + 1 end
   end
  if btn(3) 
   then x=x+1
	if isGround(x,y)
	then x = x - 1 end
   end
 
  if isGround(x,y+6) 
  then vy = 0 
  else vy = vy +1 end
 
  if btn(0) and isGround(x,y+6)
  then 
     vy=-8
     sfx(0,"C#4",20) 
  end
  y = y + vy
  if x > 240 
  then 
   mapIndexX = mapIndexX + 1
   x = 0 
  end
  if x < 0
  then
   mapIndexX = mapIndexX - 1
   x=240
  end	
 
  if y < 0 
  then 
   mapIndexY = mapIndexY - 1
   y = 136 
  end
  if y > 136
   then
    mapIndexY = mapIndexY + 1
    y=0
   end
 
  spr(3+t%60//30,x,y,0,1)
  t=t+1
end

Experiment to try: We’ve coded our game so that screens are discrete units—if you leave one screen you are wholly on another. There’s nothing about TIC that requires us to treat screens that way! Instead, try making the screen move incrementally when you cross the edge.

Now let’s add a little background music. Last time we made simple sound waves in the sound editor. What’s new this time is that once you’ve made those custom sounds, you can use them as your instruments in the music editor!

This music editor is an example of a tracker. Trackers are used a lot in making retro chiptune music, particularly the kind where you’re literally reprogramming an old game boy or other hardware to make the song with their built-in soundchips. You can read the tracker from top to bottom: the start of the song is at the top and the end of the song is the bottom. The different columns are all the notes that can play at the same time. So, for example, the middle C major chord of C-4, E-4, G-4 would look like:

Try typing in this little snippet! Can you figure out what it’s the start of? Hint: it’s a song for tiny babies.

Exercise: How close can you come to replicating the sound of those Otamatone meme song covers using custom sound waves and the tracker?

One thing that might not be obvious about a tracker is that the last note played continues until you add a rest or a different note!

To go deeper into making a platformer check out my full game – with comments – here. In this version of the game, we’ll also have code to add in a few enemy types, a big boss fight, and a projectile attack.

Learn More

Bruno’s platformer tutorial

https://medium.com/@btco_code/writing-a-platformer-for-the-tic-80-virtual-console-6fa737abe476

A neat, free, tracker for making chiptunes

http://deflemask.com/

Tutorial to make a simple platformer on the TIC-80

https://www.infinitelimit.net/article/simple-platformer-tic-80