Created
May 6, 2014 21:27
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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