// This version of pong includes the paddle #include #include #include #include #include // constants #define XDIM 600 // x dimension of table #define YDIM 400 // y dimension of table #define BALL_RADIUS 20 // ball radius #define TABLE_COLOR COLOR(0,50,0) // color of table #define BALL_COLOR RED // color of ball #define PADDLE_COLOR WHITE // color of paddle #define PADDLE_EXTENT_X 5 // how far does paddle extend in x direction // from paddle center in pixels #define PADDLE_EXTENT_Y 50 // how far does paddle extend in y direction // from paddle center in pixels #define PADDLE_VELOCITY 5 // how far does paddle move per time step // function prototypes void initialize_screen(); void initialize_ball(double &ball_loc_x, double &ball_loc_y, double &ball_direction, double &ball_velocity); void initialize_paddle(double &paddle_loc_x, double &paddle_loc_y); int update_ball_loc(double &ball_loc_x, double &ball_loc_y, double &ball_direction, double ball_velocity, double paddle_loc_x, double paddle_loc_y); void update_paddle_loc(double &paddle_loc_x, double &paddle_loc_y); void update_ball_on_screen(int ball_screen_x, int ball_screen_y); void update_paddle_on_screen(int paddle_screen_x, int paddle_screen_y); int random_in_range(int lower, int upper); /************************************ main ***********************************/ int main () { double ball_loc_x; // ball x coordinate in screen units double ball_loc_y; // ball y coordinate in screen units double ball_direction; // ball angle in radians double ball_velocity; // ball velocity in screen units double paddle_loc_x; // paddle x coordinate in screen units double paddle_loc_y; // paddle y coordinate in screen units int game_over; initialize_screen(); while (1) // loop for each game { initialize_ball(ball_loc_x, ball_loc_y, ball_direction, ball_velocity); initialize_paddle(paddle_loc_x, paddle_loc_y); do // loop for each time step within the game { update_ball_on_screen(int(ball_loc_x), int(ball_loc_y)); update_paddle_on_screen(int(paddle_loc_x), int(paddle_loc_y)); update_paddle_loc(paddle_loc_x, paddle_loc_y); game_over = update_ball_loc(ball_loc_x, ball_loc_y, ball_direction, ball_velocity, paddle_loc_x, paddle_loc_y); delay(25); // sleep for x milliseconds } while (!game_over); // wait a bit and start again delay(500); } } /************************************ initialize_screen **********************/ void initialize_screen() { // open window initwindow(XDIM, YDIM); // draw table : filled rectangle the size of the screen setfillstyle(SOLID_FILL, TABLE_COLOR); bar(0,0,XDIM-1,YDIM-1); } /************************************ initialize_ball ************************/ void initialize_ball(double &ball_loc_x, double &ball_loc_y, double &ball_direction, double &ball_velocity) { // initialize ball location, direction, and velocity ball_loc_x = XDIM / 2; ball_loc_y = (double) random_in_range(BALL_RADIUS, YDIM - BALL_RADIUS); ball_direction = (double) random_in_range(-60,60) * 3.14159 / 180.; ball_velocity = (double) random_in_range(5, 15); } /************************************ initialize_paddle **********************/ void initialize_paddle(double &paddle_loc_x, double &paddle_loc_y) { paddle_loc_x = double(XDIM - PADDLE_EXTENT_X - BALL_RADIUS); paddle_loc_y = double(YDIM / 2); } /************************************ update_ball_loc ************************/ int update_ball_loc(double &ball_loc_x, double &ball_loc_y, double &ball_direction, double ball_velocity, double paddle_loc_x, double paddle_loc_y) { double new_x, new_y; int game_over = 0; // determine new ball location if it follows current trajectory new_x = ball_loc_x + cos(ball_direction) * ball_velocity; new_y = ball_loc_y + sin(ball_direction) * ball_velocity; // check if ball hit left wall; if so, mirror direction around y axis if (new_x < BALL_RADIUS) ball_direction = 3.14159 - ball_direction; // check if ball hit paddle; if so, mirror direction around y axis else if (new_x + BALL_RADIUS >= paddle_loc_x - PADDLE_EXTENT_X && new_x + BALL_RADIUS <= paddle_loc_x + PADDLE_EXTENT_X && new_y + BALL_RADIUS >= paddle_loc_y - PADDLE_EXTENT_Y && new_y - BALL_RADIUS <= paddle_loc_y + PADDLE_EXTENT_Y) ball_direction = 3.14159 - ball_direction; // check if ball has gone off right side else if (new_x >= XDIM) game_over = 1; // otherwise advance ball in x direction else ball_loc_x = new_x; // check whether ball has hit upper or lower wall; if so, mirror direction // on x-axis if ((new_y >= YDIM - BALL_RADIUS) || (new_y < BALL_RADIUS)) ball_direction = -ball_direction; // otherwise advance ball in y direction else ball_loc_y = new_y; return game_over; } /************************************ update_ball_on_screen ******************/ void update_ball_on_screen(int new_ball_screen_x, int new_ball_screen_y) { static int old_ball_screen_x = -1; // previous displayed x posn. of ball static int old_ball_screen_y = -1; // previous displayed y posn. of ball // test if ball has moved on screen if (old_ball_screen_x != new_ball_screen_x || old_ball_screen_y != new_ball_screen_y) { // erase ball in old location setfillstyle(SOLID_FILL, TABLE_COLOR); setcolor(TABLE_COLOR); fillellipse(old_ball_screen_x, old_ball_screen_y, BALL_RADIUS, BALL_RADIUS); // draw ball in new location setfillstyle(SOLID_FILL, BALL_COLOR); setcolor(BALL_COLOR); fillellipse(new_ball_screen_x, new_ball_screen_y, BALL_RADIUS, BALL_RADIUS); // update stored ball position old_ball_screen_x = new_ball_screen_x; old_ball_screen_y = new_ball_screen_y; } } /************************************ update_paddle_on_screen ****************/ void update_paddle_on_screen(int new_paddle_screen_x, int new_paddle_screen_y) { static int old_paddle_screen_x = -1; // previous displayed x posn. of paddle static int old_paddle_screen_y = -1; // previous displayed y posn. of paddle // test if paddle has moved on screen if (old_paddle_screen_x != new_paddle_screen_x || old_paddle_screen_y != new_paddle_screen_y) { // erase paddle in old location setfillstyle(SOLID_FILL, TABLE_COLOR); bar(old_paddle_screen_x - PADDLE_EXTENT_X, old_paddle_screen_y - PADDLE_EXTENT_Y, old_paddle_screen_x + PADDLE_EXTENT_X, old_paddle_screen_y + PADDLE_EXTENT_Y); // draw paddle in new location setfillstyle(SOLID_FILL, PADDLE_COLOR); bar(new_paddle_screen_x - PADDLE_EXTENT_X, new_paddle_screen_y - PADDLE_EXTENT_Y, new_paddle_screen_x + PADDLE_EXTENT_X, new_paddle_screen_y + PADDLE_EXTENT_Y); // update stored paddle position old_paddle_screen_x = new_paddle_screen_x; old_paddle_screen_y = new_paddle_screen_y; } } /************************************ update_paddle_loc **********************/ void update_paddle_loc(double &paddle_loc_x, double &paddle_loc_y) { static double paddle_vel_y = 0.; // process mouse clicks to change paddle velocity if (ismouseclick(WM_LBUTTONDOWN)) { // left button is depressed clearmouseclick(WM_LBUTTONDOWN); paddle_vel_y = -PADDLE_VELOCITY; } if (ismouseclick(WM_LBUTTONUP)) { // left button is released clearmouseclick(WM_LBUTTONUP); paddle_vel_y = 0; } if (ismouseclick(WM_RBUTTONDOWN)) { // right button is depressed clearmouseclick(WM_RBUTTONDOWN); paddle_vel_y = PADDLE_VELOCITY; } if (ismouseclick(WM_RBUTTONUP)) { // right button is released clearmouseclick(WM_RBUTTONUP); paddle_vel_y = 0; } // update paddle location based on its velocity paddle_loc_y += paddle_vel_y; // make sure paddle can't run off screen if (paddle_loc_y < PADDLE_EXTENT_Y) paddle_loc_y = PADDLE_EXTENT_Y; if (paddle_loc_y > YDIM - PADDLE_EXTENT_Y - 1) paddle_loc_y = YDIM - PADDLE_EXTENT_Y - 1; } /************************************ random_in_range ************************/ // Generate a random number in the integer range [lower, upper] int random_in_range(int lower, int upper) { static int first_time = 1; if (first_time) { srand(time(0)); first_time = 0; } return (lower + rand()%(upper-lower+1)); }