In HackSpace magazine issue 28 we had a look at how to create an ultrasonic controller for a version of Pong called Boing!. This month, we’re going to take a step further forward through video game history and look at the game Frogger. In this classic game, you control a frog as it makes its way across logs, roads, and train tracks, avoiding falling in the water or getting hit.
The tribute to Frogger in the new Code the Classics Volume 1 book is called Infinite Bunner, and works in much the same way, except you control a bunny.
Jump along the logs, dodge the traffic, avoid the trains, and keep your bunny alive for as long as possible
All this hopping got us thinking about a controller. Our initial idea was that since the animals jump, so should the controller. An accelerometer can detect freefall, so it shouldn’t be too hard to convert that into button presses. However, it turns out that computer-controlled frogs and rabbits can jump much, much faster than humans can, and we really struggled to get a working game mechanic, so we compromised a little and worked with ‘flicks’.
The basic idea is that you tilt the controller left or right to move left or right, but you have to flick it up to register a jump (simply holding it upright won’t work).
We’ve used a Circuit Playground Bluefruit as our hardware, but it would work equally well with a Circuit Playground Express. There are two key parts to the software. The first is reading in accelerometer values and use these to know what orientation the board is in, and the second is the board mimicing a USB keyboard and sending keystrokes to any software running on it.
The first step is to get Infinite Bunner working on your machine.
Get your copy of Code the Classics today
You can download the code for all the Code the Classics Volume 1 games here. Click on
Clone or Download > Download ZIP. Unzip the download somewhere.
You’ll need Python 3 with Pygame Zero installed. The process for this differs a little between different computers, but there’s a good overview of all the different options on page 186 of Code the Classics.
Subscribe to HackSpace magazine for twelve months and you get a Circuit Playground Express for free! Then you can make your very own Infinite Bunner controller
Once everything’s set up, open a terminal and navigate to the directory you unzipped the code in. Then, inside that, you should find a folder called
bunner-master and move into that. You can then run:
Have a few goes playing the game, and you’ll find that you need the left, right, and up arrow keys to play (there is also the down arrow, but we’ve ignored this since we’ve never actually used it in gameplay – if you’re a Frogger/Bunner aficionado, you may wish to implement this as well).
Reading the accelerometer is as easy as importing the appropriate module and running one line:
from adafruit_circuitplayground import cpx, y, z = cp.acceleration
Sending key presses is similarly easy. You can set up a keyboard with the following:
from adafruit_hid.keyboard import Keyboard from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS from adafruit_hid.keycode import Keycode keyboard = Keyboard(usb_hid.devices)
Then send key presses with code such as this:
time.keyboard.press(Keycode.LEFT_ARROW) time.sleep(0.1) keyboard.release_all()
The only thing left is to slot in our mechanics. The X-axis on the accelerometer can determine if the controller is tilted left or right. The output is between 10 (all the way left) and -10 (all the way right). We chose to threshold it at 7 and -7 to require the user to tilt it most of the way. There’s a little bit of fuzz in the readings, especially as the user flicks the controller up, so having a high threshold helps avoid erroneous readings.
The Y-axis is for jumping. In this case, we require a ‘flap’ where the user first lifts it up (over a threshold of 5), then back down again.
The full code for our controller is:
import time from adafruit_circuitplayground import cp import usb_hid from adafruit_hid.keyboard import Keyboard from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS from adafruit_hid.keycode import Keycode keyboard = Keyboard(usb_hid.devices) jumping = 0 up=False while True: x, y, z = cp.acceleration if abs(y) > 5: up=True if y < 5 and up: keyboard.press(Keycode.UP_ARROW) time.sleep(0.3) keyboard.release_all() up=False if x < -7 : keyboard.press(Keycode.LEFT_ARROW) time.sleep(0.1) keyboard.release_all() if x < 7 : keyboard.press(Keycode.RIGHT_ARROW) time.sleep(0.1) keyboard.release_all() time.sleep(0.1) if jumping > 0: jumping=jumping-1
It doesn’t take much CircuitPython to convert a microcontroller into a games controller
The final challenge we had was that there’s a bit of wobble when moving the controller around – especially when trying to jump repeatedly and quickly. After fiddling with thresholds for a while, we found that there’s a much simpler solution: increase the weight of the controller. The easiest way to do this is to place it inside a book. If you’ve ever held a copy of Code the Classics, you’ll know that it’s a fairly weighty tome. Just place the board inside and close the book around it, and all the jitter disappears.
That’s all there is to the controller. You can use it to play the game, just as you would any joypad. Start the game as usual, then start flapping the book around to get hopping.
Code the Classics is available from Raspberry Pi Press as well, and comes with free UK shipping. And here’s a lovely video about Code the Classics artist Dan Malone and the gorgeous artwork he created for the book:
The post Build a physical game controller for Infinite Bunner appeared first on Raspberry Pi.
Following on from yesterday’s introduction to Pong, we’re sharing Boing!, the Python-based tribute to Pong created by Eben Upton exclusively for Code the Classics. Read on to get a detailed look at the code for Boing!
You can find the download link for the Boing! code in the Code the Classics book, available now in a variety of formats. Be sure to stick with today’s blog post until the end, for a special Code the Classics offer.
To show how a game like Pong can be coded, we’ve created Boing! using Pygame Zero, a beginner-friendly tool for making games in Python. It’s a good starting point for learning how games work – it takes place on a single screen without any scrolling, there are only three moving objects in the game (two bats and a ball), and the artificial intelligence for the computer player can be very simple – or even non-existent, if you’re happy for the game to be multiplayer only. In this case, we have both single-player and two-player modes.
The code can be divided into three parts. First, there’s the initial startup code. We import from other Python modules so we can use their code from ours. Then we check to make sure that the player has sufficiently up-to-date versions of Python and Pygame Zero. We set the
HEIGHT variables, which are used by Pygame Zero when creating the game window. We also create two small helper functions which are used by the code.
The next section is the largest. We create four classes:
Game. The first three classes inherit from Pygame Zero’s Actor class, which amongst other things keeps track of an object’s location in the game world, and takes care of loading and displaying sprites.
Ball define the behaviour of the corresponding objects in the game, while
Impact is used for an animation which is displayed briefly whenever the ball bounces off something. The
Game class’s job is to create and keep track of the key game objects, such as the two bats and the ball.
Further down, we find the
draw functions. Pygame Zero calls these each frame, and aims to maintain a frame rate of 60 frames per second. Gameplay logic, such as updating the position of an object or working out if a point has been scored, should go in
update, while in
draw we tell each of the Actor objects to draw itself, as well as displaying backgrounds, text, and suchlike.
draw functions make use of two global variables:
game. At any given moment, the game can be in one of three states: the main menu, playing the game, or the game-over screen. The
draw functions read the
state variable and run only the code relevant to the current state. So if
state is currently
State.MENU, for example,
update checks to see if the SPACE bar or the up/down arrows are pressed and updates the menu accordingly, and
draw displays the menu on the screen. The technical term for this kind of system is ‘finite state machine’.
The Game class’s job is to create and keep track of the key game objects
game variable references an instance of the
Game class as described above. The
__init__ (constructor) method of
Game optionally receives a parameter named
controls. When we create a new
Game object for the main menu, we don’t provide this parameter and so the game will therefore run in attract mode – in other words, while you’re on the main menu, you’ll see two computer-controlled players playing against each other in the background. When the player chooses to start a new game, we replace the existing
Game instance with a new one, initialising it with information about the controls to be used for each player – if the controls for the second player are not specified, this indicates that the player has chosen a single-player game, so the second will be computer-controlled.
In Boing!, the
Ball classes inherit from Pygame Zero’s Actor class, which provides a number of ways to specify an object’s position. In this game, as well as games in later chapters, we’re setting positions using the
y attributes, which by default specify where the centre of the sprite will be on the screen. Of course, we can’t just set an object’s position at the start and be done with it – if we want it to move as the game progresses, we need to update its position each frame. In the case of a
Bat, movement is very simple. Each frame, we check to see if the relevant player (which could be a human or the computer) wants to move – if they do, we either subtract or add 4 from the bat’s Y coordinate, depending on whether they want to move up or down. We also ensure that the bat does not go off the top or bottom of the screen. So, not only are we only moving along a single axis, our Y coordinate will always be an integer (i.e. a whole number). For many games, this kind of simple movement is sufficient. Even in games where an object can move along both the X and Y axes, we can often think of the movement along each axis as being separate. For example, in the next chapter’s game, Cavern, the player might be pressing the right arrow key and therefore moving along the X axis at 4 pixels per frame, while also moving along the Y axis at 10 pixels per frame due to gravity. The movement along each axis is independent of the other.
Able to move at any angle, the ball needs to move at the same speed regardless of its direction
Ball, things get a bit more complicated. Not only can it move at any angle, it also needs to move at the same speed regardless of its direction. Imagine the ball moving at one pixel per frame to the right. Now imagine trying to make it move at a 45° angle from that by making it move one pixel right and one pixel up per frame. That’s a longer distance, so it would be moving faster overall. That’s not great, and that’s before we’ve even started to think about movement in any possible direction.
The solution is to make use of vector mathematics and trigonometry. In the context of a 2D game, a vector is simply a pair of numbers: X and Y. There are many ways in which vectors can be used, but most commonly they represent positions or directions.
You’ll notice that the
Ball class has a pair of attributes,
dy. Together these form a vector representing the direction in which the ball is heading. If
dy are 1 and 0.5, then each time the ball moves, it’ll move by one pixel on the X axis and a half a pixel on the Y axis. What does it mean to move half a pixel? When a sprite is drawn, Pygame Zero will round its position to the nearest pixel. So the end result is that our sprite will move down the screen by one pixel every other frame, and one pixel to the right every frame (Figure 1).
We still need to make sure that our object moves at a consistent speed regardless of its direction. What we need to do is ensure that our direction vector is always a ‘unit vector’ – a vector which represents a distance of one (in this case, one means one pixel, but in some games it will represent a different distance, such as one metre). Near the top of the code you’ll notice a function named
normalised. This takes a pair of numbers representing a vector, uses Python’s
math.hypot function to calculate the length of that vector, and then divides both the X and Y components of the vector by that length, resulting in a vector which points in the same direction but has a length of one (Figure 2).
Vector maths is a big field, and we’ve only scratched the surface here. You can find many tutorials online, and we also recommend checking out the Vector2 class in Pygame (the library on top of which Pygame Zero is built).
Update Raspbian to try Boing! and other Code the Classics games on your Raspberry Pi.
The full BOING! tutorial, including challenges, further explanations, and a link to the downloadable code can be found in Code the Classics, the latest book from Raspberry Pi Press.
We’re offering £1 off Code the Classics if you order it before midnight tomorrow from the Raspberry Pi Press online store. Visit the store now, or use the discount code PONG at checkout if you make a purchase before midnight tomorrow.
As always, Code the Classics is available as a free PDF from the Wireframe website, but we highly recommend purchasing the physical book, as it’s rather lovely to look at and would make a great gift for any gaming and/or coding enthusiast.
One topic explored in Code the Classics from Raspberry Pi Press is the origin story and success of Pong, one of the most prominent games in early video game history.
‘The success of Pong led to the creation of Pong home consoles (and numerous unofficial clones) that could be connected to a television. Versions have also appeared on many home computers.’
Ask anyone to describe a game of table tennis and they’ll invariably tell you the same thing: the sport involves a table split into quarters, a net dividing the two halves, a couple of paddles, and a nice round ping-pong ball to bat back and forth between two players. Take a look at the 1972 video game Pong, however, and you’ll notice some differences. The table, for instance, is simply split in half and it’s viewed side-on, the paddles look like simple lines, and the ball is square. Yet no one – not even now – would have much trouble equating the two.
Back in the early 1970s, this was literally as good as it got. The smattering of low-powered arcade machines of the time were incapable of realistic-looking graphics, so developers had to be creative, hoping imaginative gamers would fill the gaps and buy into whatever they were trying to achieve. It helped enormously that there was a huge appetite for the new, emerging video game industry at that time. Nolan Bushnell was certainly hungry for more – and had he turned his nose up at Spacewar!, a space combat game created by Steve Russell in 1962, then Pong would never even have come about.
“The most important game I played was Spacewar! on a PDP-1 when I was in college,” he says, of the two-player space shooter that was popular among computer scientists and required a $120,000 machine to run. Although the visuals were nothing to write home about, the game was one of the first graphical video games ever made. It pitted two spaceships against each other and its popularity spread, in part, because the makers decided the code could be distributed freely to anyone who wanted it. “It was a great game, fun, challenging, but only playable on a very expensive computer late at night and the wee hours of the morning,” Nolan says. “In my opinion, it was a very important step.”
Nolan was so taken by Spacewar! that he made a version of the game with a colleague, Ted Dabney. Released in 1971, Computer Space allowed gamers to control a rocket in a battle against flying saucers, with the aim being to get more hits than the enemy in a set period of time. To make it attractive to players, it was placed in a series of colourful, space-age, moulded arcade cabinets. Nolan and Ted sold 1500 of them; even though they made just $500 from the venture, it was enough to spur them into continuing. They came up with the idea for Pong and created a company called Atari.
One of their best moves was employing engineer Al Alcorn, who had worked with Nolan at the American electronics company Ampex. Al was asked to create a table tennis game based on a similar title that had been released on the Magnavox Odyssey console, on the pretence that the game would be released by General Electric. In truth, Nolan simply wanted to work out Al’s potential, but he was blown away by what his employee came up with. Addictive and instantly recognisable, Atari realised Pong could be a major hit. The game’s familiarity with players meant it could be picked up and played by just about anyone.
Even so, Nolan had a hard time convincing others. Manufacturers turned the company down, so he visited the manager of a bar called Andy Capp’s in Sunnyvale, California and asked them to take Pong for a week. The manager soon had to call Nolan to tell him the machine had broken: it had become stuffed full of quarters from gamers who loved the game. By 1973, production of the cabinet was in overdrive and 8000 were sold. It led to the creation of a Pong home console which sold more than 150,000 machines. People queued to get their hands on one and Atari was on its way to become a legendary games company.
For Nolan, it was justification for his perseverance and belief. Suddenly, the man who had become interested in electronics at school, where he would spend time creating devices and connecting bulbs and batteries, was being talked of as a key player in the fledgling video game industry. But what did Nolan, Ted, Al, and the rest of the Atari team do to make the game so special? “We made it a good, solid, fun game to play,” says Nolan. “And we made it simple, easy, and quickly understood. Keeping things simple is more difficult to do than building something complex. You can’t dress up bad gameplay with good graphics.”
On the face of it, Pong didn’t look like much. Each side had a paddle that could be moved directly up and down using the controller, and the ball would be hit from one side to the other. The score was kept at the top of the screen and the idea was to force the opposing player to miss. It meant the game program needed to determine how the ball was hit and where the ball would go from that point. And that’s the crux of Pong’s success: the game encouraged people to keep playing and learning in the hope of attaining the skills to become a master.
When creating Pong, then, the designers had a few things in mind. One of the most important parts of the game was the movement of the paddles. This involved a simple, vertical rectangle that went up and down. One of the benefits Atari had when it created Pong was that it controlled not just the software but the hardware too. By building the cabinet, it was able to determine how those paddles should be moved. “The most important thing if you want to get the gameplay right is to use a knob to move the paddle,” advises Nolan. “No one has done a good Pong using touchscreens or a joystick.”
Look at a Pong cabinet close up – there are plenty of YouTube videos which show the game in action on the original machine – and you will see what Nolan means. You’ll notice that players turned a knob anticlockwise to move the paddle down, and clockwise to move it up. Far from being confusing, it felt intuitive.
With the paddles moving, Atari’s developers were able to look at the movement of the ball. At its most basic, if the ball continued to make contact with the paddles, it would constantly move back and forth. If it did not make contact, then it would continue moving in the direction it had embarked upon and leave the screen. At this stage, a new ball was introduced in the centre of the screen and the advantage was given to the player who had just chalked up a point. If you watch footage of the original Pong, you will see that the new ball was aimed at the player who had just let the ball go past. There was a chance he or she would miss again.
To avoid defeat, players had to be quite nifty on the controls and stay alert. Watching the ball go back and forth at great speed could be quite mesmerising as it left a blurred trail across the cathode ray tube display. There was no need to waste computing power by animating the ball because the main attention was focused on what would happen when it collided with the paddle. It had to behave as you’d expect. “The game did not exist without collisions of the ball to the paddle,” says Nolan.
Al realised that the ball needed to behave differently depending on where it hit the paddle. When playing a real game of tennis, if the ball hits the centre of the racket, it will behave differently from a ball that hits the edge. Certainly, the ball is not going to be travelling in a simple, straight path back and forth as you hit it; it is always likely to go off at an angle. This, though, is the trickiest part of making Pong “The ball should bounce up from an upper collision with more obtuse angles as the edge of the paddle is approached,” Nolan says. “This balances the risk of missing with the fact that an obtuse angle is harder to return.” This is what Pong is all about: making sure you hit the ball with the paddle, but in a manner that makes it difficult for the opposing player to return it. “A player wants the ball to be just out of reach for the opponent or be hard for him or her to predict.”
This post is part of a much longer deep dive into the history of Pong in Code the Classics, our 224-page hardback book that not only tells the stories of some of the seminal video games of the 1970s and 1980s, but also shows you how to use Python and Pygame Zero to create your own games inspired by them, following examples programmed by Raspberry Pi founder Eben Upton.
In conjunction with today’s blog post, we’re offering £1 off Code the Classics when you order your copy between now and midnight Wednesday 26 Feb 2020 from the Raspberry Pi Press online store. Simply follow this link or enter the discount code PONG at checkout to get your copy for only £11, with free shipping in the UK.