Lucid Bounce

Views: 3745 Difficulty: 3 Status: Complete

Our take on the classic bouncing ball, paddle game.

A simple game for the Joy Gamer, Lucid Bounce puts the fun of the arcade in the palm of your hand, without hiding the cool stuff under the hood. This game uses our new LeoGamer to showcase what you can do with an LCD screen and joystick a few buttons and some Arduino code. While the controller itself will amaze you, this tutorial is about the code that goes into the machine. The objective is to write a bouncing ball and moving paddle game. In the process, you'll learn a few useful things about interfacing with an analog joystick, writing functions , and using a 3rd party library.

Joy Bouncing

The joystick controls the paddle.

Joy Bounce Video

Joy Bounce in action

Lucid Bounce Arduino Code

Here is code for the Joy Gamer to Play the paddle bounce game. First, make sure you have necessary libraries downloaded from the main Joy Gamer tutorial. The point of the game is just to keep the ball alive the longer you do it the more points you get. The whole program boils down to three functions and one struct. The struct is called point to encapsulate the data for the ball, the ball's direction and speed of travel, and the paddle.
struct point{ 
  float x;
  float y;
  float sizer;
  Color c;
The functions are start_game(), draw_game() and draw_stats(). The start_game function clears the screen and resets the ball's position. The draw_stats() function draws the score and the remaining lives to the top of the screen. The draw_game() function does most of the work reading in the joy stick data and translating that into a position for the paddle. Then update the ball's position using the ball speed vector.
/* LucidTronix JoyGamer Joy Bounce
 * For instructions, details and schematic, See:

#include <JoyGamer.h>
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#include <Color.h>
#include <I2C.h>
#include <MMA8453Q.h>
#include <SD.h>

Adafruit_ST7735  tft = Adafruit_ST7735(SS, 9, 8);
JoyGamer jg = JoyGamer(&tft);

struct point{ 
  float x;
  float y;
  float sizer;
  Color c;

int score = 0;
int lives = 5; // dont go over 5 without adjusting paddle color code
unsigned long last_press, last_level_up;
point paddle, ball, ball_speed;

void setup(){

void loop() {

// reset the ball and updates ball speed and padddle size;
void start_game()
  paddle.x = 64;
  paddle.y = 150;
  paddle.c = Color(255 - (lives*50), 50, 50);
  paddle.sizer = 40 - min(36, (score/50));
  ball.x = 64;
  ball.y = 64;
  ball.c = Color(random(0,245), random(0,245), random(0,245));
  ball.sizer =  max(2, 8 - score /50);
  long randx = random(60, 500) + score;
  long randy = random(150, 500) + score/3;
  ball_speed.x = (float)randx / 1000.0; 
  ball_speed.y = (float)randy / 300.0; ;

void draw_game(){
  tft.fillCircle(ball.x, ball.y, ball.sizer, jg.background.color_16());
  int dx = map(analogRead(jg.joy_x), 0, 1024, -3, 4);
  if(dx != 0) tft.fillRect(paddle.x-1, paddle.y-1, paddle.sizer+1, 6, jg.background.color_16());
  ball.x += ball_speed.x;
  ball.y += ball_speed.y;
  if((dx > 0 && paddle.x < 128-paddle.sizer) || (dx < 0 && paddle.x > 0)) paddle.x += dx;
  tft.fillCircle(ball.x, ball.y, ball.sizer, ball.c.color_16());
  tft.fillRect(paddle.x, paddle.y, paddle.sizer, 5, paddle.c.color_16());
  if(bounce_ball_y()) {
    ball_speed.y *= -1;
    // avoid double bounces by pushing the ball above the paddle when necessary
    tft.fillCircle(ball.x, ball.y, ball.sizer, jg.background.color_16());
    ball.y = min(paddle.y-1, ball.y);
  if(ball.x < ball.sizer || ball.x > 128 - ball.sizer) ball_speed.x *= -1;
  if(ball.y >  paddle.y + 6){
    if(lives <= 0) {
       jg.draw_string(3, 10, "Game Over.", Color(150, 20, 50).color_16(), 2);
       jg.draw_string(10, 60, "Death becomes you.", Color(0, 50, 250).color_16(), 1);
       jg.draw_string(10, 74, "Press Joystick", Color(0, 50, 250).color_16());
       jg.draw_string(10, 88, "to Start Over", Color(0, 50, 250).color_16());
       while(digitalRead(jg.joystick_btn_pin) == LOW){
       lives = 5;
       score = 0;
       last_level_up = millis();
    else {
      last_level_up = millis();
  if(millis() - last_level_up > 4000){
    score += 50;
    last_level_up = millis();
    ball_speed.x *= 1.1;
    ball_speed.y *= 1.1;
    paddle.sizer = 40 - min(36, (score/50));

boolean bounce_ball_y(){
  if (ball.y >= paddle.y && ball.x > paddle.x && ball.x < paddle.x+paddle.sizer) return true;
  if (ball.y < 12 + ball.sizer) return true;
  return false;

void draw_stats(){
  tft.fillRect(0, 0, 128, 12, Color(250, 250, 250).color_16());
  jg.draw_string(2, 2, "Score:", Color(0, 50, 250).color_16());
  String s = String(score);
  jg.draw_string(45, 2, s, Color(0, 50, 250).color_16());
  jg.draw_string(78, 2, "Lives:", Color(0, 50, 250).color_16());
  String s2 = String(lives);
  if ( lives <= 1 ) jg.draw_string(115, 2, s2,  Color(255, 10, 10).color_16());
  else if ( lives <= 3 ) jg.draw_string(115, 2, s2, Color(250, 200, 0).color_16());
  else jg.draw_string(115, 2, s2, Color(5, 250, 5).color_16());


Title Description # Cost Link Picture
Joy Gamer Joyous Arduino-Based Gaming machine! Full color LCD screen, Joystick with 3D printed knob and enclosure. 1 $79.95 Link Gamers
Handheld gaming machine, based on the Arduino Leonardo, equipped with joystick, SD card and more....
Mixing pixels from two face images together....
Display bitmap images and text files and folders with this TFT LCD screen and SD Card navigator....
Play pong on a little LCD screen with two big joysticks....
The Wearable Wayfinder is a totally programmable, beautiful little computer for your wrist packed wit...
3d view of a face using an SD card, accelerometer and a TFT LCD Screen...
Servo motor, JPEG camera, and Arduino Leonardo combine to make a panoramic camera....
Control the hue, value and saturation on this pocket-sized joystick drawing machine....