#include #include #include "./constants.h" #include "./structs.h" #include "./game_time.h" #include "./sound.h" #include "./color.h" extern App app; game_object ball; game_object paddle1; game_object paddle2; int player1_score; int player2_score; float speed_up_factor; float delta_time; float serve_timer; float collision_timer; float winner_timer; void init_pong(); void init_ball(); void init_paddles(); void update(); void update_ball(float dt); void do_ball_collision(game_object* paddle); void update_paddles(float dt); void do_serve(void); void do_goal(int* score_to_update); void do_winner(void); void render(); void draw_center_line(); void draw_score(); void init_pong() { app.input = 0; player1_score = 0; player2_score = 0; init_ball(); init_paddles(); init_sounds(); app.update = update; app.render = render; } void init_ball() { const game_object BALL_TEMPLATE = { { BALL_INIT_X, BALL_INIT_Y, BALL_RADIUS, BALL_RADIUS }, 0, 0, 0 }; ball = BALL_TEMPLATE; speed_up_factor = -1.05; } void init_paddles() { const game_object PADDLE_TEMPLATE = { { 0, PADDLE_Y, PADDLE_WIDTH, PADDLE_HEIGHT }, 0, 0, 0 }; paddle1 = paddle2 = PADDLE_TEMPLATE; paddle1.rect.x = PADDLE1_X; paddle2.rect.x = PADDLE2_X; } void do_ball_collision(game_object* paddle) { if(ball.timer >= 1) { ball.dx *= speed_up_factor; ball.dy = (WINDOW_HEIGHT * 0.015) * -((paddle->rect.y + paddle->rect.h / 2) - ball.rect.y); play_sound(0, -1); ball.timer = 0; } } void update_ball(float dt) { // serve ball if not moving if( ball.dx == 0 ) { do_serve(); } // check for collision with paddles if(SDL_HasIntersection(&ball.rect, &paddle1.rect)) { do_ball_collision(&paddle1); } if(SDL_HasIntersection(&ball.rect, &paddle2.rect)) { do_ball_collision(&paddle2); } // check for collision with top and bottom of screen if(ball.rect.y + ball.rect.h >= WINDOW_HEIGHT || ball.rect.y <= 0) { ball.dy *= -1; } // check for exit off right or left of screen if(ball.rect.x > WINDOW_WIDTH) { do_goal(&player1_score); } if(ball.rect.x + ball.rect.w < 0) { do_goal(&player2_score); } // update ball's position ball.rect.x += ball.dx * dt; ball.rect.y += ball.dy * dt; } void update_paddles(float dt) { // reset paddles' movement vectors, adjust according to input paddle1.dy = 0; paddle2.dy = 0; if(app.input & PADDLE_1_UP && paddle1.rect.y >= 0) { paddle1.dy = -PADDLE_SPEED; } if(app.input & PADDLE_1_DOWN && paddle1.rect.y + paddle1.rect.h <= WINDOW_HEIGHT) { paddle1.dy = PADDLE_SPEED; } if(app.input & PADDLE_2_UP && paddle2.rect.y >= 0) { paddle2.dy = -PADDLE_SPEED; } if(app.input & PADDLE_2_DOWN && paddle2.rect.y + paddle2.rect.h <= WINDOW_HEIGHT) { paddle2.dy = PADDLE_SPEED; } // update paddles' positions paddle1.rect.y += paddle1.dy * dt; paddle2.rect.y += paddle2.dy * dt; ball.timer += dt; } void do_goal(int* score_to_update) { ++*score_to_update; init_ball(); init_paddles(); if(*score_to_update >= 5) { do_winner(); } } void do_winner() { init_pong(); if(player1_score > player2_score) { SDL_Log("PLAYER 1 WINS!!!"); } else { SDL_Log("PLAYER 2 WINS!!!"); } } void do_serve(void) { if(ball.timer >= 3) { if (SDL_GetTicks() % 2 == 0) { ball.dx = BALL_INIT_SPEED; } else { ball.dx = -BALL_INIT_SPEED; } } } void update() { delay(); delta_time = get_delta_time(); update_ball(delta_time); update_paddles(delta_time); } void draw_center_line(void) { for(int i = -CENTER_LINE_HEIGHT / 2; i < WINDOW_HEIGHT; i += CENTER_LINE_HEIGHT * 2) { SDL_Rect center_line_rect = { WINDOW_WIDTH / 2 - CENTER_LINE_WIDTH / 2, i, CENTER_LINE_WIDTH, CENTER_LINE_HEIGHT }; SDL_RenderFillRect(app.renderer, ¢er_line_rect); } } void draw_score(void) { for(int i = 0; i != player1_score; ++i) { SDL_Rect score_tally_rect = { PLAYER1_SCORE_TALLY_X + i * WINDOW_WIDTH / 16, SCORE_TALLY_Y, SCORE_TALLY_WIDTH, SCORE_TALLY_HEIGHT }; SDL_RenderFillRect(app.renderer, &score_tally_rect); } for(int i = 0; i != player2_score; ++i) { SDL_Rect score_tally_rect = { PLAYER2_SCORE_TALLY_X - i * WINDOW_WIDTH / 16, SCORE_TALLY_Y, SCORE_TALLY_WIDTH, SCORE_TALLY_HEIGHT }; SDL_RenderFillRect(app.renderer, &score_tally_rect); } } void draw_message(void) { SDL_Texture* font = IMG_LoadTexture(app.renderer, "./gfx/90.png"); SDL_RenderCopy(app.renderer, font, NULL, NULL); } void render(void) { // fill screen SDL_SetRenderDrawColor(app.renderer, COLOR_BG.r, COLOR_BG.g, COLOR_BG.b, COLOR_BG.a); SDL_RenderClear(app.renderer); // draw ball, paddles SDL_SetRenderDrawColor(app.renderer, COLOR_FG.r, COLOR_FG.g, COLOR_FG.b, COLOR_FG.a); SDL_RenderFillRect(app.renderer, &ball.rect); SDL_RenderFillRect(app.renderer, &paddle1.rect); SDL_RenderFillRect(app.renderer, &paddle2.rect); // draw center line, dividing the play field draw_center_line(); // draw score tally draw_score(); // draw serve, goal, or winner message // draw_message(); // present rendered scene SDL_RenderPresent(app.renderer); }