diff options
Diffstat (limited to 'tennis.c')
-rw-r--r-- | tennis.c | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/tennis.c b/tennis.c new file mode 100644 index 0000000..7147073 --- /dev/null +++ b/tennis.c @@ -0,0 +1,228 @@ +#include <SDL2/SDL.h> +#include <SDL2/SDL_image.h> + +#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); +} |