summaryrefslogtreecommitdiff
path: root/tennis.c
diff options
context:
space:
mode:
Diffstat (limited to 'tennis.c')
-rw-r--r--tennis.c228
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, &center_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);
+}