Make your own side-scrolling racer in the vein of the NES classic Excitebike. Mark Vanstone has the code, straight from this month’s brand new edition of Wireframe magazine, out now.
Most early games started out as coin-ops, but in 1984, Nintendo first released Excitebike on the NES. Later that year, Nintendo ported Excitebike to arcades as it became one of its best-selling console games. The smooth, side-scrolling motorcycle racer laid the technical foundations for the way Super Mario later moved around his world.
Excitebike allows a player to race against three computer-controlled opponents along a track that has ramps to jump and debris to avoid. The player must try to keep the momentum of their bike going to get the best time. In this example, we’ll replicate the scrolling track, which moves faster as the player speeds up. We’ll add ramps to jump and bits of debris to avoid.
Using Pygame Zero and the time module for keeping track of our lap times, we need to set up our bike Actor that will stay in the same X coordinate position. The bike’s Y coordinate will change as the bike moves from lane to lane or jumps over ramps. We can set up our track data with a list of integers that will represent track blocks. To keep it simple, we’ll have 0 representing a plain track block, 1 for a jump block, and 2 for the start/finish line. We also have another list to show where the bits of debris need to be; the numbers represent the track lanes 1 to 4, with 0 being no debris.
draw() function is straightforward and just draws a background, then calls the
drawTrack() function, draws the bike Actor, and then writes text to show us the lap timer and the last lap completion time. In the
update() function, we need to capture the left and right keys to slow down and speed up the bike, and then calculate the track position based on the bike’s current speed. We can keep the track looping round by detecting when we’ve reached the end of the data, and then set the
trackPos variable back to 0 and reset our lap time counter. We want to snap the bike to the four lanes of the track, but we also need to allow the player to move the bike from lane to lane, which we do by capturing the up and down keys in the
We can set the
bike.direction to -1 or 1, and the
update() function will move the bike up or down one lane. We can also make the bike look like it’s vibrating a little by alternating between two frames, depending on how fast the bike is going.
drawTrack() function looks at our track list, starting from the block determined by the
trackPos variable. Each block is 100 pixels wide, and we get the smooth scrolling effect by drawing the blocks at an offset based on the
trackOffset variable that cycles between 99 and 0. This is the remainder when we divide the
trackPos variable by 100. We then draw nine blocks across the screen, depending on our track and debris data.
We also need to check if the bike has hit a ramp, and if so, the angle of the bike needs to start turning upwards, and the Y coordinate needs to follow the line of the ramp. Then, when the bike is at the top of the ramp, it needs to fall back onto the track. We tilt the angle of the bike forwards as it falls, and if the angle is too great when it hits the ground, the bike slows down and loses momentum. By judging the speed going into each ramp, the player can get better times on the lap. We also have the debris to test for – if the bike runs over a patch, we slow the bike down.
There it is, our very own Excitebike homage. The original game had AI rivals and different-sized ramps, but we’ll leave you to add those in.
Get your copy of Wireframe #66
And if you prefer your magazines in digital form, you can also download Wireframe issue 66 as a free PDF!