As the title says the detectCollision function is working properly but the ball is not bouncing off the paddle. I stuck on a printf in the "if(object == paddle)" func and it shows that it is detecting the collion, but the ball's velocity is not being reversed as instructed. I am at a loss, especially since it bounces off the brick no problem.
//
// 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 10
// lives
#define LIVES 3
// paddle
#define PADDLE_WIDTH 70
#define PADDLE_HEIGHT 20
#define PADDLE_X 160
#define PADDLE_Y 550
// 1st brick location
#define BRICK_X (SPACE / 2)
#define BRICK_Y 100
// height and width of brick
#define BRICK_W ((WIDTH - (SPACE * (COLS))) / COLS)
#define BRICK_H ((HEIGHT / 10) / ROWS)
// space size
#define SPACE 5
// number of rows of bricks
#define ROWS 5
// number of columns of bricks
#define COLS 10
// ball height and width
#define BALL_W 50
#define BALL_H 50
// Ball Initial Velocity
#define BALL_V_X 2.3
#define BALL_V_Y 2.7
// 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;
// Ball initial velocity
double velocity_x = BALL_V_X;
double velocity_y = BALL_V_Y;
// keep playing until game over
while (lives > 0 && bricks > 0)
{
// Listen of mouse move
GActionEvent move_paddle = getNextEvent(MOUSE_EVENT);
if(move_paddle != NULL)
{
if(getEventType(move_paddle) == MOUSE_MOVED)
{
// Move Paddle
double x = getX(move_paddle) - (PADDLE_WIDTH / 2);
double y = PADDLE_Y;
setLocation(paddle, x, y);
}
}
// Move Ball
move(ball, velocity_x, velocity_y);
// detect collision
GObject object = detectCollision(window, ball);
if (object != NULL)
{
if (object == paddle)
{
velocity_y = -velocity_y;
printf("you hit paddle\n");
}
else if (strcmp(getType(object), "GRect") == 0)
{
velocity_y = -velocity_y;
printf("you hit brick\n");
}
else if (strcmp(getType(object), "GLabel") == 0)
{
//TODO ignore?
}
}
// bounce off sides
if(getX(ball) >= (WIDTH - BALL_W))
{
velocity_x = -velocity_x;
}
if(getX(ball) <= 0)
{
velocity_x = -velocity_x;
}
// TODO when ball hits ground, undo comments
if(getY(ball) >= (HEIGHT - BALL_H))
{
velocity_y = -velocity_y;
printf("you hit the ground\n");
}
pause (20);
}
// 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 j = 0; j < ROWS; j++)
{
for(int i = 0; i < COLS; i++)
{
GRect brick = newGRect(BRICK_X + (BRICK_W * i) + (SPACE * i), (BRICK_Y + (BRICK_H * j) + (SPACE * j)), BRICK_W, BRICK_H);
if (j == 0)
{
setColor(brick, "Red");
}
if (j == 1)
{
setColor(brick, "Orange");
}
if (j == 2)
{
setColor(brick, "Yellow");
}
if (j == 3)
{
setColor(brick, "Green");
}
if (j == 4)
{
setColor(brick, "Cyan");
}
setFilled(brick, true);
add(window, brick);
}
}
}
/**
* Instantiates ball in center of window. Returns ball.
*/
GOval initBall(GWindow window)
{
GOval ball = newGOval((((WIDTH - BALL_W)) / 2), (((HEIGHT - BALL_H)) / 2), BALL_W, BALL_H);
add(window, ball);
return ball;
}
/**
* Instantiates paddle in bottom-middle of window.
*/
GRect initPaddle(GWindow window)
{
GRect paddle = newGRect(PADDLE_X, PADDLE_Y, PADDLE_WIDTH, PADDLE_HEIGHT);
setColor(paddle, "BLUE");
setFilled(paddle, true);
add(window, paddle);
return paddle;
}
/**
* Instantiates, configures, and returns label for scoreboard.
*/
GLabel initScoreboard(GWindow window)
{
// TODO
return NULL;
}
/**
* 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;
}
// Remove brick when hit
//void removeGWindow(GWindow gw, GObject gobj)
//{
//TODO
//}