You are on page 1of 11



6.6 Writing Your Own Game
To test our game controller, we will program a simple Breakout3 clone in Processing. The game’s goal is to destroy all bricks in the upper half of the screen with a ball. You can control the ball with the paddle at the bottom of the screen, and you can tilt the controller around the x-axis to move the paddle horizontally. It’ll look something like this:

Although this is not a book about game programming, it will not hurt to take a look at the game’s innards, especially because game programming with Processing is really pure fun! Download the code from the book’s website4 and play the game before you dive into the code. Because we will connect our game controller to the serial port, we have to initialize it:
Download MotionSensor/Game/Game.pde

import processing.serial.*; Serial arduinoPort;

3. 4.

Report erratum

Download from Wow! eBook <>

this copy is (P1.0 printing, Janurary, 2011)

MARGIN = 10. X_AXIS_MIN = 252. we need to store the possible states of the game: Download MotionSensor/Game/Game. boolean paused = true. Report erratum Download from Wow! eBook <www.pde final final final final final final final final final final final final final final final final int int int int int int int int int int int int int int int int COLUMNS = 7. bricks is a two-dimensional array and contains the current state of the bricks on the screen. We store the balls’ current x and y coordinates in px and py. For example.pde boolean buttonPressed = false.4. X_AXIS_MAX = 443. MAX_VELOCITY = 8. PADDLE_WIDTH = 60. We store the paddle’s x position in xpos. 0 means that it has been destroyed already. int vx. PADDLE_HEIGHT => this copy is (P1. BALL_DIAMETER = BALL_RADIUS * 2. the corresponding brick is still on the screen. For its current x and y velocity. You should replace X_AXIS_MIN and X_AXIS_MAX the minimum and maximum values you measured for your sensor in Section 6. int xpos = WIDTH / 2. Janurary. vy. WIDTH = COLUMNS * BRICK_WIDTH + 2 * MARGIN. HEIGHT = 300. we use vx and vy. and COLUMNS and ROWS set the layout of the bricks.wowebook. BAUD_RATE = 19200. BRICK_WIDTH = 40. BRICK_HEIGHT = 20. PADDLE_WIDTH is width of the paddle measured in pixels. on page 137. int[][] bricks = new int[COLUMNS][ROWS]. ROWS = 4. boolean done = true.W RITING Y OUR O WN G AME 145 Then we define some constants that will help us to customize the game easily: Download MotionSensor/Game/Game. Next we choose how to represent the game’s objects: Download MotionSensor/Game/Game. If an array element is set to 1. Finding and Polishing Edge Values. BALL_RADIUS = 8.pde int px. py.0 printing. 2011) . LINE_FEED = 10. Most of these values should be self-explanatory—they define the size of the objects that appear on the screen. Finally.

= height / 2. x++) for (int y = 0. The setup( ) function initializes the screen. Otherwise. arduinoPort = new Serial(this. initBall().W RITING Y OUR O WN G AME 146 Unsurprisingly. we set buttonPressed to true when the button on the controller is pressed.bufferUntil(LINE_FEED). and done is true when the current level is done. x < COLUMNS. MAX_VELOCITY)).com> this copy is (P1.0 printing. textFont(loadFont("Verdana-Bold-36. and sets the font that we will use to output messages (create the font using Processing’s Tools > Create Font menu). initGame(). println(Serial. noCursor(). Now that everything is initialized. } void px py vx vy } initBall() { = width / 2. Then we call initGame( ) to initialize the bricks array and the ball’s current position and velocity. = int(random(-MAX_VELOCITY. Processing’s draw( ) method is a perfect place:5 5. we can implement the game’s main loop.vlw")). y++ ) bricks[x][y] = 1. Every Processing program needs a setup( ) has excellent documentation for all Processing classes.wowebook. paused tells you whether the game is currently paused. } void initBricks() { for (int x = 0.list()[0].list()). and here is ours: Download MotionSensor/Game/Game. when all bricks have been destroyed. hides the mouse pointer with noCursor( ). BAUD_RATE).pde void setup() { size(WIDTH. which makes the ball fall at a reasonable speed. it is false. arduinoPort. 2011) . that is. We set the velocity for the y direction to -2. y < ROWS. HEIGHT). Report erratum Download from Wow! eBook <www. = -2. Serial. } void initGame() { initBricks(). To make things more interesting. http://processing. the velocity in x direction is set to a random value. Janurary.

drawBall(). stroke(255). } } } return allEmpty. Finally. we print a corresponding message.pde boolean drawBricks() { boolean allEmpty = true. strokeWeight(3). y < ROWS. rect( MARGIN + x * BRICK_WIDTH. 100 + y * 8). 0. Then we set the stroke color to white and the stroke weight to three> this copy is (P1. and if it’s not.pde void draw() { background(0). done = drawBricks().0 printing. x++) { for (int y = 0. } Report erratum Download from Wow! eBook <www. } We clear the screen and paint it black using background( ). If the game is paused. y++) { if (bricks[x][y] > 0) { allEmpty = false. we pause the game and print a “You Win!” message. for (int x = 0. x < COLUMNS. 2011) . BRICK_WIDTH. Janurary. If no bricks are left. fill(0. else updateGame(). printWinMessage(). } if (paused) printPauseMessage(). MARGIN + y * BRICK_HEIGHT.wowebook. After that we draw the remaining bricks. we update the game’s current state. drawPaddle(). we draw the ball and the paddle at their current positions using the following functions: Download MotionSensor/Game/Game.W RITING Y OUR O WN G AME 147 Download MotionSensor/Game/Game. BRICK_HEIGHT ). if (done) { paused = true.

width / 2. paused = true.PADDLE_WIDTH / 2.pde void updateGame() { if (ballDropped()) { initBall(). } As you can see.W RITING Y OUR O WN G AME 148 void drawBall() { strokeWeight(1). 2011) . too: Download MotionSensor/Game/Game. px += vx. checkWallCollision(). ellipse(px. BALL_DIAMETER. and the bricks and the paddle are simple rectangles. PADDLE_WIDTH. } void printPauseMessage() { fill(128). To make them look more appealing. textSize(36). } void drawPaddle() { int x = xpos . Janurary. height * 2 / 3).com> this copy is (P1. textSize(16). textAlign(CENTER). and so on: Download MotionSensor/Game/Game. we give them a nice border. 0). the ball is nothing but a circle. textAlign(CENTER). height * 5 / 6). text("Press Button to Continue". } else { checkBrickCollision().pde void printWinMessage() { fill(255). moves the ball. because it updates the game’s state—it checks for collisions. int y = height . py += vy. width / 2. text("YOU WIN!". fill(128. py. rect(x.wowebook. } The update( ) function is very important. checkPaddleCollision(). Printing the game’s messages is easy. BALL_DIAMETER). strokeWeight(1). y. } } Report erratum Download from Wow! eBook <www. PADDLE_HEIGHT).0 printing.(PADDLE_HEIGHT + MARGIN). 0. fill(128).

we check for various collisions.BALL_RADIUS) vx = -vx. the game stops.0 printing.BALL_RADIUS) vy = -vy. or if it has hit the paddle. vy = -vy. The collision checks look complicated. you’d decrease some kind of a life counter and print a “Game Over” message when the counter reaches zero. We check if the ball has hit one or more bricks. 0)) // Hit left or right side of brick. Then we calculate the ball’s new position. 2011) . } boolean inXRange(final int row. vy)) { bricks[x][y] = 0. x++) { for (int y = 0.BALL_RADIUS.pde boolean ballDropped() { return py + vy > height . y < ROWS.W RITING Y OUR O WN G AME 149 When the player does not hit the ball with the paddle and it drops out of the playfield. but they are fairly simple and only compare the ball’s coordinates with the coordinates of all the other objects on the screen: Download MotionSensor/Game/Game. vx = -vx. } void checkBrickCollision() { for (int x = 0. vx) && inYRange(y. } Report erratum Download from Wow! eBook <www. 0)) // Hit top or bottom of brick. In the final game. and the user is allowed to continue after pressing the button. x < COLUMNS. y++) { if (bricks[x][y] > 0) { if (inXRange(x. final int v) { return py + v > col * BRICK_HEIGHT && py + v < (col + 1) * BRICK_HEIGHT + BALL_DIAMETER. Janurary.wowebook. if (inXRange(x. If the ball is still in play. final int v) { return px + v > row * BRICK_WIDTH && px + v < (row + 1) * BRICK_WIDTH +> this copy is (P1. } } } } } void checkWallCollision() { if (px + vx < BALL_RADIUS || px + vx > width . if (py + vy < BALL_RADIUS || py + vy > height . } boolean inYRange(final int col. if (inYRange(y. if it has hit a wall.

it plays some music from the Super Mario Brothers video> this copy is (P1. you control the paddle by tilting the game controller Report erratum Download from Wow! eBook <www.wowebook.† This hacky-sack blinks and beeps whenever you kick it. PADDLE_WIDTH / 2. The Brushduino indicates which section of the mouth to brush next using LEDs. An ordinary tilt sensor is sufficient to build an interactive hacky-sack game.∗ A father built it to encourage his young children to brush their teeth people have used them to create some unbelievably cool and funny projects. it’d be only fair to move the paddle.W RITING Y OUR O WN G AME 150 More Fun with Motion-Sensing Technologies Since motion-sensing technologies became popular and cheap. for example. -MAX_VELOCITY.html void checkPaddleCollision() { final int cx = xpos. } } Note that the collision checks also change the velocity of the ball if necessary. if (py + vy >= height .(PADDLE_HEIGHT + MARGIN + 6) && px >= cx .blogspot.makezine.html http://blog. Janurary. Now that the ball is moving. and whenever the child has successfully finished a section. ∗. too. it plays a song. But you do not need an accelerometer to detect motion and to create cool new electronic toys.PADDLE_WIDTH / 2 && px <= cx + PADDLE_WIDTH / 2) { vy = -vy. and after 30 successful kicks. Its main component—apart from an Arduino— is a three-axis accelerometer. 2011) . †. As said MAX_VELOCITY ) ).0 A hilarious example is the Brushduino. vx = int( map( px . http://camelpunch. -(PADDLE_WIDTH / 2).

This all happens in line 5. X_AXIS_MIN. in serialEvent( ). X_AXIS_MAX.pde Line 1 5 10 15 20 void serialEvent(Serial port) { final String arduinoData = port. we continue the game. You only have to read four integer values from the serial port when you need them. we check whether the game has been finished. initGame(). split it at the blank characters. But you should Report erratum Download from Wow! eBook <www. It separates all attributes by blanks.length == 4) { buttonPressed = (data[3] == 1). We check whether we actually got all four attributes.readStringUntil(LINE_FEED). If yes. That’s really all we have to do to move the paddle using our own game controller. } } if (!paused) xpos = int(map(data[0]. we toggle the pause state: if the game currently is in pause mode. it doesn’t matter if you use the controller to control a game or a completely different type of software. ' ')). Also. and convert the resulting strings into int values. we read the new line. Each line contains the current acceleration of the x-. and then we see whether the player has pushed the button on the game controller. if (buttonPressed) { paused = !paused. WIDTH)). we read the current X acceleration in line 17 and map it to the possible x positions of our paddle. you have learned much more about game programming than about Arduino programming or hardware. 0. Finally.W RITING Y OUR O WN G AME 151 around the x-axis. we pause it. } } } Processing calls the serialEvent( ) function whenever new data is available on the serial port. Here’s the code that gets the controller data via the serial port: Download MotionSensor/Game/Game. In this section. Also.0 printing. if (arduinoData != null) { final int[] data = int(split(trim(arduinoData). we start a new game. If yes. and z-axes and the current state of the button. y-. otherwise. if (done) { done = false. 2011) . if (data. The controller sends its data line by line. So.> this copy is (P1.wowebook.

we have measured only direct acceleration. Here’s a small collection of both commercial and free products: • Nike’s iPod Sport Kit supports you in your daily exercise. and even an vibration motor for force feedback effects. ∗. 6.runnerplus.7 More Projects If you keep your eyes too. that is.† It’s a perfect example of the unbelievable creativity that the Arduino sets free.6 • It’s a lot of fun to create a marble maze computer game and control it using the game controller we build in this chapter. 2011) . We carefully analyzed the analog data returned by the http://www. but suddenly your Arduino has a 320x200 pixel OLED touch screen. and it’s based on an> this copy is ( and we will use it again in the next chapter. You can also use it to build some cool games.electronicsinfoline.makezine.0 printing.html have also learned that it’s easy to integrate a well-designed electronics project into your regular software projects.html Report erratum Download from Wow! eBook <www.blogspot. 7. †. 6. This is a technique you’ll use often in your electronics projects.wowebook. and then we eliminated all unwanted jitter. someone built a Super Mario Bros clone with minimal hardware requirements. Janurary.M ORE P ROJECTS 152 Creating Games with the Arduino You can use the Arduino to build more than your own cool game controllers.html http://blog. How much more fun will it be to build a real marble maze?7 • In this chapter. http://www. you’ll quickly find many more applications for accelerometers than you might imagine. an analog stick. With the right extension∗ It’s pricey. You can learn a lot from its inner workings. you can even turn an Arduino into a powerful gaming console. two buttons. we usually have the accelerometer in our hand and move it. While looking for a cheaper solution. http://antipastohw.> this copy is (P1.and y-axes. on page 131 also applies to the project in this section. we have some special items such as the protoshield. 8.0 printing.8 HAT I F I T D OESN ’ T W ORK ? 153 But you can also build many interesting projects that measure indirect acceleration. What If It Doesn’t Work? . It should also have a left button and a right button. It should work in free air. Still. and it should emit the current acceleration around the x.8 What If It Doesn’t Work? All advice from Section 5. Make sure that it sits correctly on top of the Arduino and that none of its connectors accidentally slipped past its socket.dimensionengineering. such as when you are driving a car. Sometimes the headers are out of shape.10.9 Exercises • Create your own computer mouse using the ADXL335 accelerometer. 2011) . Check if you have soldered the pin header correctly to the breakout board. Use a magnifying glass and study every single solder joint carefully.wowebook. Write some Processing code (or perhaps code in a programming language of your choice?) to control a mouse pointer on the screen. Janurary. so it might happen.htm Report erratum Download from Wow! eBook <www. Did you use enough solder? Did you use too much and connect two joints? 6.

We’ll use an ordinary Nunchuk controller and transfer the data it emits to our computer using an> . You don’t even need a Nintendo Wii to do any of this—you only need a Nunchuk controller.1 What You Need • An Arduino board such as the Uno. In this chapter. Even better: because of its good design and its easy-to-access connectors. You’ll learn how to wire it to the Arduino. you can integrate it into your own projects surprisingly easily. and two buttons. an analog joystick. rotate. Duemilanove.wowebook. and it is very cheap (less than $20 at the time of this writing). and scale a 3D cube on the screen using your Nunchuk. and how to move. how to write software that reads the controller’s current state. 7. or Diecimila • A USB cable to connect the Arduino to your computer • A Nintendo Nunchuk controller • Four wires Download from Wow! eBook <www. other times you can safely make it part of your own project. It’s a perfect candidate for tinkering: it comes with a three-axis accelerometer.Chapter 7 Tinkering with the Wii Nunchuk One of the most entertaining electronic activities is tinkering: taking an existing product and turning it into something different or using it for an unintended purpose. you’ll learn how to hijack a Nintendo Nunchuk controller. Sometimes you have to open the product and void its warranty.