I've looked through every Breakout question and can't seem to fix my issue. Whenever I manage to get the Scoreboard visible/counting the ball will always collide then freeze on it. Right now I can't seem to have it visible anymore. In this current code the ball bounces around fine and resets with a click.
Any hints towards my issues - which appear to revolve around the GLabel label = initScoreboard(window), would be great thanks.
//
// breakout.c
//
// Computer Science 50
// Problem Set 3
//
// standard libraries
#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
// Stanford Portable Library
#include <spl/gevents.h>
#include <spl/gobjects.h>
#include <spl/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 12.5
// lives
#define LIVES 3
//Paddle dimensions
#define padWIDTH 30
#define padHEIGHT 3
//BallWidth constants
#define ballWidth 25
#define ballHeight 25
// 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);
GLabel scoreboard;
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;
// Velocity initial speed
double velocityX = drand48()*2;
double velocityY = drand48()+2;
updateScoreboard(window, label, points);
//Ball paused until click
waitForClick();
while(true)
{
//Create/Wait for Mouse Event
GEvent event = getNextEvent(MOUSE_EVENT);
if(event != NULL)
{
//Detect mouse event 'movement' & move paddle with it.
if(getEventType(event) == MOUSE_MOVED)
{
double x = getX(event) - getWidth(paddle)/2;
setLocation(paddle, x, 500);
}
}
//Call move function at pre-set random velocities
move(ball, velocityX, velocityY);
//Bounce off right side
if (getX(ball) + getWidth(ball) >= getWidth(window))
{
velocityX = -velocityX;
}
//Bounce off left side
if (getX(ball) <= 0)
{
velocityX = -velocityX;
}
//Bounce off roof
if (getY(ball) - (getHeight(ball)/2) <= 0)
{
velocityY = -velocityY;
}
//Stop if hit the bottom & change counters, wait for click to reset
if (getY(ball) + (getHeight(ball)/2) >= getHeight(window))
{
lives -= 1;
velocityY = 0; velocityX = 0;
setLocation(ball,(WIDTH/2)-(ballWidth/2), (HEIGHT/2));
while(velocityY == 0)
{
GMouseEvent click = waitForEvent(MOUSE_EVENT);
if(getEventType(click) == MOUSE_CLICKED)
{
velocityX = drand48()*2;
velocityY = drand48()+2;
move(ball, velocityX, velocityY);
}
}
}
pause(10);
//Detec collisions with object = ball
GObject object = detectCollision(window, ball); //check which side of the ball collides with which side of the GRect
//bounce the ball off accordingly
if(object != NULL)
{
//reverse velocity when colliding with ball
if(object == paddle)
{
velocityY = -velocityY;
}
//revere velocity when colliding with brick, change counters & rm brick
else if(strcmp(getType(object), "GRect")==0)
{
velocityY = -velocityY;
bricks -= 1;
points += 1;
removeGWindow(window, object);
updateScoreboard(window, label, points);
}
//Do nothing if colliding with scoreboard label
else if (strcmp(getType(object), "GLabel") == 0)
{
return 0;
}
}
}
// wait for click before exiting
waitForClick();
// game over
closeGWindow(window);
return 0;
}
/**
* Initializes window with a grid of bricks.
*/
void initBricks(GWindow window)
{
for(int i = 0; i < ROWS; i++)
{
int brickPosHeight = 100;
brickPosHeight += 10*i;
for(int j = 0; j < COLS; j++)
{
int brickPosWidth = 10;
brickPosWidth += 39*j;
GRect brick = newGRect(brickPosWidth, brickPosHeight, 29, 5);
setFilled(brick, true);
if((j >= 0) && (j <= 2))
{
setColor(brick, "GREEN");
add(window, brick);
}
if((j > 2) && (j <= 6))
{
setColor(brick, "BLUE");
add(window, brick);
}
if((j > 6) && (j <= 10))
{
setColor(brick, "RED");
add(window, brick);
}
}
}
}
/**
* Instantiates ball in center of window. Returns ball.
*/
GOval initBall(GWindow window)
{
GOval ball = newGOval(((WIDTH/2)-(ballWidth/2)), (HEIGHT/2), ballWidth, ballHeight);
setFilled(ball, true);
setColor(ball, "PINK");
add(window, ball);
return ball;
}
/**
* Instantiates paddle in bottom-middle of window.
*/
GRect initPaddle(GWindow window)
{
GRect paddle = newGRect((WIDTH/2)-(padWIDTH/2), 500, padWIDTH, padHEIGHT);
setFilled(paddle, true);
setColor(paddle, "BLUE");
add(window, paddle);
return paddle;
}
/**
* Instantiates, configures, and returns label for scoreboard.
*/
GLabel initScoreboard(GWindow window)
{
double labelX =getWidth(window);
double labelY =getHeight(window);
GLabel label = newGLabel("0");
setFont(label, "Verdana-50");
setColor(label, "GREEN");
setLocation(label, labelX, labelY);
add(window, label);
return label;
}
/**
* Updates scoreboard's label, keeping it centered in window.
*/
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;
}