summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Manuel Tomás <jtomas1815@gmail.com>2018-09-12 15:15:42 -0300
committerJuan Manuel Tomás <jtomas1815@gmail.com>2018-09-12 15:15:42 -0300
commita9dcbe95c2d70c2457d750169b839e08462ab6b7 (patch)
treebf00eafa40e1688a1dc45c87141a9c677761f8b2
downloadpong-master.tar.gz
pong-master.zip
initial commitHEADmaster
-rw-r--r--pong.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/pong.c b/pong.c
new file mode 100644
index 0000000..0c8219e
--- /dev/null
+++ b/pong.c
@@ -0,0 +1,192 @@
+#define SDL_DISABLE_IMMINTRIN_H
+#include <limits.h>
+#include <stdlib.h>
+#include <time.h>
+#include <SDL2/SDL.h>
+
+#define WINDOW_W 800
+#define WINDOW_H 600
+#define MARGIN 20
+#define PLAYER_W 10
+#define PLAYER_H 100
+#define PLAYER_V 5
+#define BALL_SIZE 10
+
+typedef struct {
+ float x, y;
+ char dir;
+ int score;
+ int stuck;
+} Player;
+
+typedef struct {
+ float x, y;
+ float vx, vy;
+} Ball;
+
+void initBall(Ball *b) {
+ b->x = WINDOW_W / 2;
+ b->y = WINDOW_H / 2;
+ b->vx = 2 * (rand() % 2 ? 1 : -1);
+ b->vy = 2 * (rand() % 2 ? 1 : -1);
+}
+
+int abs(int n) {
+ return (n >= 0 ? n : -n);
+}
+
+void limit(float *n, float min, float max) {
+ if (abs(*n) > max) *n = *n > 0 ? max : -max;
+ else if (abs(*n) < min) *n = *n > 0 ? min : -min;
+}
+
+float randfloat(float from, float to) {
+ return from + (to - from) * ((float)rand()/INT_MAX);
+}
+
+void collision(Ball *b, Player *p) {
+ if (b->x + BALL_SIZE >= p->x &&
+ b->x <= p->x + PLAYER_W &&
+ b->y + BALL_SIZE >= p->y &&
+ b->y <= p->y + PLAYER_H) {
+ if (!p->stuck) {
+ b->vx = -b->vx;
+ b->vx *= randfloat(0.5, 1.5);
+ limit(&b->vx, 4, 8);
+ b->vy += randfloat(0.2, 0.8) * p->dir;
+ limit(&b->vy, 2, 8);
+ p->stuck = 1;
+ }
+ }
+ else {
+ p->stuck = 0;
+ }
+}
+
+void move(Player *p, float n) {
+ if (n > 0) p->dir = 1;
+ else if (n < 0) p->dir = -1;
+ p->y += n;
+ if (p->y > WINDOW_H - PLAYER_H) {
+ p->y = WINDOW_H - PLAYER_H;
+ p->dir = 0;
+ }
+ else if (p->y < 0) {
+ p->y = 0;
+ p->dir = 0;
+ }
+}
+
+void input(Player *p) {
+ const Uint8 *state = SDL_GetKeyboardState(0);
+ if (state[SDL_SCANCODE_UP])
+ move(p, -PLAYER_V);
+ else if (state[SDL_SCANCODE_DOWN])
+ move(p, PLAYER_V);
+ else
+ p->dir = 0;
+}
+
+void ai(Ball *b, Player *p) {
+ if (abs(b->x - p->x) < 300) {
+ if (b->y - p->y > PLAYER_H - 10 - BALL_SIZE)
+ move(p, PLAYER_V);
+ else if (b->y - p->y < 10)
+ move(p, -PLAYER_V);
+ }
+ else {
+ if (p->y >= WINDOW_H * 5 / 6 - PLAYER_H) {
+ p->dir = -1;
+ }
+ else if (p->y <= WINDOW_H / 6) {
+ p->dir = 1;
+ }
+ move(p, p->dir * PLAYER_V);
+ }
+}
+
+void update(Ball *b, Player *p1, Player *p2) {
+ b->x += b->vx;
+ b->y += b->vy;
+ if (b->y < 0 || b->y + BALL_SIZE > WINDOW_H)
+ b->vy = -b->vy;
+ if (b->x < 0) {
+ p2->score++;
+ initBall(b);
+ }
+ if (b->x + BALL_SIZE > WINDOW_W) {
+ p1->score++;
+ initBall(b);
+ }
+ if (p1->score > 5 || p2->score > 5) {
+ p1->score = 0;
+ p2->score = 0;
+ }
+ collision(b, p1);
+ collision(b, p2);
+ input(p1);
+ ai(b, p2);
+}
+
+void render(SDL_Renderer *r, Ball *b, Player *p1, Player *p2) {
+ SDL_SetRenderDrawColor(r, 0, 0, 0, 255);
+ SDL_RenderClear(r);
+ SDL_SetRenderDrawColor(r, 40, 40, 40, 255);
+ SDL_Rect canvas = {0, 0, WINDOW_W, WINDOW_H};
+ SDL_RenderFillRect(r, &canvas);
+ SDL_SetRenderDrawColor(r, 255, 255, 255, 255);
+ SDL_Rect net[10];
+ for (int i = 0; i < 10; i++) {
+ net[i].x = WINDOW_W / 2;
+ net[i].y = i * (WINDOW_H / 10) + 10;
+ net[i].w = 10;
+ net[i].h = WINDOW_H / 10 - 20;
+ }
+ SDL_RenderFillRects(r, net, 10);
+
+ SDL_SetRenderDrawColor(r, 255, 255, 255, 255);
+ SDL_Rect ball_r = {b->x, b->y, BALL_SIZE, BALL_SIZE};
+ SDL_RenderFillRect(r, &ball_r);
+
+ int p1factor = 255 - p1->score * 50;
+ SDL_SetRenderDrawColor(r, 255, p1factor, p1factor, 255);
+ SDL_Rect p1_r = {p1->x, p1->y, PLAYER_W, PLAYER_H};
+ SDL_RenderFillRect(r, &p1_r);
+
+ int p2factor = 255 - p2->score * 50;
+ SDL_SetRenderDrawColor(r, 255, p2factor, p2factor, 255);
+ SDL_Rect p2_r = {p2->x, p2->y, PLAYER_W, PLAYER_H};
+ SDL_RenderFillRect(r, &p2_r);
+
+ SDL_RenderPresent(r);
+ SDL_Delay(10);
+}
+
+int main() {
+ srand(time(0));
+ SDL_Init(SDL_INIT_VIDEO);
+ SDL_Window *w;
+ SDL_Renderer *r;
+ SDL_CreateWindowAndRenderer(WINDOW_W, WINDOW_H, SDL_WINDOW_RESIZABLE, &w, &r);
+ SDL_RenderSetLogicalSize(r, WINDOW_W, WINDOW_H);
+ Player p1, p2;
+ Ball b;
+ p1.x = MARGIN;
+ p1.y = WINDOW_H / 2;
+ p2.x = WINDOW_W - MARGIN - PLAYER_W;
+ p2.y = WINDOW_H / 2;
+ p1.score = p2.score = 0;
+ p1.stuck = p2.stuck = 0;
+ p1.dir = p2.dir = 0;
+ initBall(&b);
+ SDL_Event e;
+ while (e.type != SDL_QUIT) {
+ SDL_PollEvent(&e);
+ update(&b, &p1, &p2);
+ render(r, &b, &p1, &p2);
+ }
+ SDL_DestroyRenderer(r);
+ SDL_DestroyWindow(w);
+ SDL_Quit();
+ return 0;
+}