Atari Breakout

Avi Gupta
hackerLog
Published in
6 min readNov 18, 2018

--

“Everybody thinks they’re a historian.”
- Alan Alcorn, creater of Pong

Okay, so this is pretty much a version of Atari Breakout, a 1P game where you just hit bricks and earned points. Ah yes. The good old retro days, where one of the only forms of video games were arcades, with their maze of coin-op machines. Not that I would know, but that’s what I’ve heard.

Atari breakout. Courtesy of GIFER.

I made a version of this game where the ball moves slower and the paddle is automated.

My version of Atari Breakout with the automatic paddle

Here’s how we made the game. The details are explained in the comments and shown here.

First, we make the global variables.

// global constantsint wallAcross = 19;// the width of the array of the 2d bricks
int wallDown = 4;// the height of the array of the 2d bricks
int brickWidth = 50;// the width of each brick
int brickHeight = 20;// the height of each brick
// this makes a 19 by 4 array of bricks with dimensions [50*20]

In Processing, each thing that you see here — the bat, the paddle, the bricks — were all rendered with a class. To make the ball, you must make a class of type ball. (see inline comments for details.)

/*
this is the class that makes the ball
the ints define the xy position, the radius of the ball
and the change in x and y position
*/
class Ball {
int x, y, radius;
int xspeed, yspeed;
Ball(int initX, int initY, int initXS, int initYS, int radius) {
fill(255);
this.x = initX;
this.y = initY;
this.xspeed = initXS;
this.yspeed = initYS;
this.radius = radius;
}

We also must create conditions for the collision of the ball for different directions.

   void ballUpdate(Collision c) {    
switch(c) {
case UP:// collision upward
case DN:// collision downward
// cases of vertical collision
yspeed *= -1;
// inverts the direction of the change on the y axis
break;//breaks the process, doing it only once
case RT:// collision to the right
case LT://collison to the left
// cases of horizontal collision
xspeed *= -1;
// inverts the direction of the change on the x axis
break;
default://case where there is no collision
break;
}
}

Then, we must also render the graphics for the ball.

   void display() {    
this.x += xspeed;// changes the x
this.y += yspeed;// changes the y
ellipse(x, y, radius*2, radius*2);
/* radius * 2 because
last 2 inputs specify x diameter and y diameter respectively
not radius
*/
}
} // end class Ball

then we use an enum, or list, of all of the collision cases.

enum Collision {  
UP, DN, RT, LT, NO// NO = No collision
} // end enum Collision

Now we declare the class brick. It is similar to the class ball, but in this case, it has booleans for whether it is visible or not and whether it is permanent or not.

/* this is the class for brick
ints specify xy coordinates, width, height
boolean fixed, which states that a brick can't be destroyed
points, which we have not added yet
and boolean visible, which is set to "true" if not destroyed
and "false" if destroyed"
*/
class Brick {
int x, y, w, h, r, g, b;
boolean fixed;
int points;
boolean visible;
Brick(int x, int y, int w, int h, int r, int g, int b, boolean fixed, int points) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.r = r;
this.g = g;
this.b = b;
this.fixed = fixed;
this.points = points;
this.visible = true;
}

We also have to detect a collision with the brick so that it will become invisible.

  Collision detectCollision(Ball ball) {    
if (visible) {
Collision c = detectCollisionUtil(ball, this.x, this.y, this.w, this.h);
if (c != Collision.NO) {
this.visible = false;
}// states that if there is a collision, it we become invisible
return c;
}
return Collision.NO;
}// return if Collision.NO (no collision) is true

of course, we also have to render the brick.

void display() {
if (visible) {
fill(r, g, b);
rect(x, y, w, h);
} else {
// fill(0);
// rect(1000, 1000, w, h);
}
}

Okay, now the last thing: The paddle!

/*
This is the class for paddle
ints declare the xy position of the paddle
also declares the width and height of paddle
*/
class Paddle {
int px, py, pw, ph;
Paddle(int px, int py, int pw, int ph) {
this.px = px;
this.py = py;
this.pw = pw;
this.ph = ph;
}

Again, all things must be rendered. We make the paddle so that the x is the ball.width — pw/2 where pw is the width of the paddle (x width).

void display(Ball ball) {
fill(255);
//paddle is centered with ball along x-axis
rect(ball.x - pw/2, py, pw, ph);

}

And of course, the paddle is also going to be hitting the ball. We covered that, too.

Collision detectCollision(Ball ball) {
if ((ball.y > py - ball.radius) &&
(ball.y < py + ph + ball.radius)) {
return Collision.DN;
}// says if ball is touching paddle
// then ball will bounce upward
return Collision.NO;// returns if there is no collision
}

Okay, now all of the classes are initialized. Now we must define the conditions of the types of collisions.

Collision detectCollisionUtil(Ball ball, int x, int y, int w, int h) {
if ((ball.x > x - ball.radius) &&
(ball.x < x + w + ball.radius) &&
(ball.y > y - ball.radius) &&
(ball.y < y + h + ball.radius)) {
if (ball.x > x + w) {
return Collision.LT;
} else if (ball.x < x) {
return Collision.RT;
} else if (ball.y < y) {
return Collision.DN;
} else if (ball.y > y + h) {
return Collision.UP;
}
}
return Collision.NO;
}

The ball also collides with the wall. We got that, too.

Collision detectWall(Ball ball) {
if (ball.x < 0) {
return Collision.LT;
} else if ((ball.x + (ball.radius*2))> width) {
return Collision.RT;
} else if (ball.y < 0) {
return Collision.UP;
}
return Collision.NO;
}

Now we declare the objects.

/*
declares an array of bricks,
a paddle,
and a ball
*/
Brick[][] wall;
Paddle paddle;
Ball ball;

Now we make the basic setup, which initializes the background, size, and even object positions and characteristics. Here we start with the bricks and the game background details.

void setup() {// generates start of game
frameRate(1000);// the framerate of the game
size(1000, 400);// the width and height of the game screen respectively
background(0);// greyscale input, so the background will be blac, or rgb (0, 0, 0)
wall = new Brick[wallAcross][wallDown];// see global variables
int xOffset = (width - (brickWidth * wallAcross))/2;// sets x spacing for the bricks
int yOffset = 20;// sets y spacing for the bricks
for (int across = 0; across < wallAcross; across++) {
for (int down = 0; down < wallDown; down++) {
int xBrick = xOffset + (brickWidth*across) ;
int yBrick = yOffset + ((brickHeight + 5)*down);
wall[across][down] =
new Brick(xBrick, yBrick,
brickWidth, brickHeight,
(int)random(100, 150), (int)random(150, 200), (int)random(200, 255),
false, 10);// makes bricks of random colors
}
}

Then, we make the paddle and the ball.

// makes a 2D array of bricks with the dimensions specified in the global variables
paddle = new Paddle((width - 50)/2, height-50, 50, 5);
ball = new Ball(width/2, height/2, -3, 3, 5);
// makes the paddle and the ball.
}

Then comes the drawing, where we can see everything.

void draw() { 
background(0);
for (int across = 0; across < wallAcross; across++) {
for (int down = 0; down < wallDown; down++) {
Brick b = wall[across][down];
Collision c = b.detectCollision(ball);
ball.ballUpdate(c);
wall[across][down].display();
}// renders the bricks
}
paddle.display(ball);
Collision c2 = paddle.detectCollision(ball);
ball.ballUpdate(c2);
Collision c3 = detectWall(ball);
ball.ballUpdate(c3);
ball.display();
}// renders the paddle and the ball

Pretty cool, right?

Give it a go, play with the settings, and see how you like it.

The full game is available on GitHub over here.

--

--

Avi Gupta
hackerLog

Named after the first 2 games I got on my xBox, Forza and Minecraft. Also, i have a blog. Real name is Avi.