Skip to content

Instantly share code, notes, and snippets.

@mitrnsplt
Created May 6, 2014 21:27
Show Gist options
  • Save mitrnsplt/642a8b86c229bf28ad66 to your computer and use it in GitHub Desktop.
Save mitrnsplt/642a8b86c229bf28ad66 to your computer and use it in GitHub Desktop.
A re-creation of an old video game where a player uses a "paddle" to smack balls against a brick wall until all the bricks are knocked out. Staff provided helper files and libraries.
//
// breakout.c
//
// Computer Science 50
// Problem Set 4
/**
* A version of breakout
*
* Some sections by Peter Downs
*
* Simulates classic "Jailbreak" arcade game
*/
//
// standard libraries
#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
// Stanford Portable Library
#include "gevents.h"
#include "gobjects.h"
#include "gwindow.h"
// height and width of game's window in pixels
#define HEIGHT 600
#define WIDTH 400
// number of rows of bricks
#define ROWS 5
// number of columns of bricks
#define COLS 10
// radius of ball in pixels
#define RADIUS 10
// lives
#define LIVES 3
// paddle
#define Pad_Width 60
#define Pad_Height 10
// prototypes
void initBricks(GWindow window);
GOval initBall(GWindow window);
GRect initPaddle(GWindow window);
GLabel initScoreboard(GWindow window);
void updateScoreboard(GWindow window, GLabel label, int points);
GObject detectCollision(GWindow window, GOval ball);
int main(void)
{
// seed pseudorandom number generator
srand48(time(NULL));
// instantiate window
GWindow window = newGWindow(WIDTH, HEIGHT);
// instantiate bricks
initBricks(window);
// instantiate ball, centered in middle of window
GOval ball = initBall(window);
// instantiate paddle, centered at bottom of window
GRect paddle = initPaddle(window);
// instantiate scoreboard, centered in middle of window, just above ball
GLabel label = initScoreboard(window);
// number of bricks initially
int bricks = COLS * ROWS;
// number of lives initially
int lives = LIVES;
// number of points initially
int points = 0;
waitForClick();
// define and initialize ball velocity
double xvelocity = drand48() + 1;
double yvelocity = drand48() + 1;
// keep playing until game over
while (lives > 0 && bricks > 0)
{
// program paddle moves to follow user's mouse
GEvent event = getNextEvent(MOUSE_EVENT);
if (event != NULL)
{
if (getEventType(event) == MOUSE_MOVED)
{
double x = getX(event) - getWidth(paddle)/2;
double y = HEIGHT * 0.9;
setLocation(paddle, x, y);
}
}
// move ball
move(ball, xvelocity, yvelocity);
// bounce off right or left edges of window
if (getX(ball) + getWidth(ball) >= WIDTH || getX(ball) <= 0)
{
xvelocity = -xvelocity;
}
// bounce off the top edge
else if (getY(ball) <= 0)
{
yvelocity = -yvelocity;
}
// linger before moving again
pause(5);
//if ball passes paddle and strikes the bottom, lose a life
if (getY(ball) + getWidth(ball) >= HEIGHT)
{
lives = lives - 1;
setLocation(ball, WIDTH/2 - RADIUS, HEIGHT/2 - RADIUS);
waitForClick();
}
//check for collision
GObject object = detectCollision(window, ball);
if (object != NULL)
{
// if ball hits paddle, bounce
if (object == paddle)
{
yvelocity = -yvelocity;
}
// if ball hits a brick, knock it out and bounce
else if (strcmp(getType(object), "GRect") == 0)
{
removeGWindow(window, object);
yvelocity = -yvelocity;
bricks = bricks - 1;
points = points + 1;
}
}
updateScoreboard(window, label, points);
}
//messages on completion of game
if (lives == 0)
{
GLabel lost = newGLabel("Too bad! You've no more lives!");
setFont(lost, "SansSerif-18");
double x = (getWidth(window) - getWidth(lost)) / 2;
double y = getHeight(window) * 4 / 5;
setLocation(lost, x, y);
add(window, lost);
}
else if (bricks == 0)
{
GLabel free = newGLabel("You're free!");
setFont(free, "SansSerif-18");
double x = (getWidth(window) - getWidth(free)) / 2;
double y = getHeight(window) / 5;
setLocation(free, x, y);
add(window, free);
}
// wait for click before exiting
waitForClick();
// game over
closeGWindow(window);
return 0;
}
/**
* Initializes window with a grid of bricks.
*/
void initBricks(GWindow window)
{
// make a grid of bricks that are proportional to the width of the window
int brickwidth = WIDTH/(COLS + 1);
int brickheight = brickwidth/3;
int brickseparation = brickwidth/COLS;
for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLS; j++)
{
// start by making blank space behind where the brick wall starts
double x = brickseparation + (j * (brickwidth + brickseparation));
double y = HEIGHT/10 + (i * (brickheight + brickseparation));
// make the bricks
GRect brick = newGRect(x, y, brickwidth, brickheight);
// color the bricks
setFilled(brick, true);
if (i % 2 == 0)
setColor(brick, "RED");
if (i % 2 == 1)
setColor(brick, "ORANGE");
// add the bricks to the window
add(window, brick);
}
}
}
/**
* Instantiates ball in center of window. Returns ball.
*/
GOval initBall(GWindow window)
{
// make a ball in the center of the window
int cx = WIDTH / 2 - RADIUS;
int cy = HEIGHT / 2 - RADIUS;
GOval ball = newGOval(cx, cy, RADIUS * 2, RADIUS * 2);
// color the ball black
setColor(ball, "BLACK");
setFilled(ball, true);
// add the ball to the window
add(window, ball);
return ball;
}
/**
* Instantiates paddle in bottom-middle of window.
*/
GRect initPaddle(GWindow window)
{
//create and initialize paddle
GRect paddle = newGRect((WIDTH - Pad_Width)/2, HEIGHT * 0.9, 60, 10);
setColor(paddle, "CYAN");
setFilled(paddle, true);
add(window, paddle);
return paddle;
}
/**
* Instantiates, configures, and returns label for scoreboard.
*/
GLabel initScoreboard(GWindow window)
{
// create the scoreboard
GLabel label = newGLabel(" ");
setFont(label, "SansSerif-18");
double x = (getWidth(window) - getWidth(label)) / 2;
double y = (getHeight(window) - getHeight(label)) / 2;
setLocation(label, x, y);
add(window, label);
return label;
}
void updateScoreboard(GWindow window, GLabel label, int points)
{
// update label
char s[12];
sprintf(s, "%i", points);
setLabel(label, s);
// center label in window
double x = (getWidth(window) - getWidth(label)) / 2;
double y = (getHeight(window) - getHeight(label)) / 2;
setLocation(label, x, y);
}
/**
* Detects whether ball has collided with some object in window
* by checking the four corners of its bounding box (which are
* outside the ball's GOval, and so the ball can't collide with
* itself). Returns object if so, else NULL.
*/
GObject detectCollision(GWindow window, GOval ball)
{
// ball's location
double x = getX(ball);
double y = getY(ball);
// for checking for collisions
GObject object;
// check for collision at ball's top-left corner
object = getGObjectAt(window, x, y);
if (object != NULL)
{
return object;
}
// check for collision at ball's top-right corner
object = getGObjectAt(window, x + 2 * RADIUS, y);
if (object != NULL)
{
return object;
}
// check for collision at ball's bottom-left corner
object = getGObjectAt(window, x, y + 2 * RADIUS);
if (object != NULL)
{
return object;
}
// check for collision at ball's bottom-right corner
object = getGObjectAt(window, x + 2 * RADIUS, y + 2 * RADIUS);
if (object != NULL)
{
return object;
}
// no collision
return NULL;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment