summaryrefslogtreecommitdiff
path: root/pong.c
diff options
context:
space:
mode:
Diffstat (limited to 'pong.c')
-rw-r--r--pong.c359
1 files changed, 359 insertions, 0 deletions
diff --git a/pong.c b/pong.c
new file mode 100644
index 0000000..0d77e97
--- /dev/null
+++ b/pong.c
@@ -0,0 +1,359 @@
+#include "SDL.h"
+#include "SDL_image.h"
+#include "SDL_ttf.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+
+#include "pong.h"
+#include "text.h"
+#include "color.h"
+#include "ball.h"
+#include "paddle.h"
+
+TTF_Font * DejaVu = NULL;
+
+int main(int argc, char *argv[]) {
+ SDL_Event Event;
+ SDL_Surface * Surface = NULL;
+ SDL_Surface * Temp = NULL;
+ Game.height = 480; /* Modify Window Height */
+ Game.width = 640; /* Modify Window Width */
+ Game.depth = 0;
+ Game.done = 0;
+ Game.play = 1;
+ Game.Score_Limit = 2;
+ Game.Speed = Game.height / 75; /* Modify Paddle Speeds */
+ Event.type = SDL_NOEVENT;
+
+ if ( argc ) {
+ if ( argv ) {}
+ }
+
+ srand(time(NULL));
+
+ if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
+ fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
+ exit(-1);
+ }
+ atexit(SDL_Quit);
+ if ( TTF_Init() < 0 ) {
+ fprintf(stderr, "Unable to init SDL_ttf: %s\n", TTF_GetError());
+ exit(-1);
+ }
+ atexit(TTF_Quit);
+
+ DejaVu = TTF_OpenFont(
+#ifdef SKYOS
+ "/boot/system/fonts/DejaVuSans.ttf",
+#else
+ "DejaVuSans.ttf",
+#endif
+ 18);
+ if ( !DejaVu ) {
+ fprintf(stderr, "TTF_OpenFont: %s\n", TTF_GetError());
+ exit(-1);
+ }
+
+ Surface = SDL_SetVideoMode(Game.width, Game.height, Game.depth, SDL_HWSURFACE);
+ if ( !Surface ) {
+ fprintf(stderr, "Unable to create main surface: %s\n", SDL_GetError());
+ exit(-1);
+ }
+
+ black = CreateColor(0, 0, 0);
+ white = CreateColor(255, 255, 255);
+
+ Temp = IMG_Load("icon.png");
+ if ( !Temp ) {
+ fprintf(stderr, "%s\n", SDL_GetError());
+ exit (-1);
+ }
+ SDL_SetColorKey(Temp, SDL_SRCCOLORKEY, black->color);
+ SDL_WM_SetIcon(Temp, NULL);
+ SDL_FreeSurface(Temp);
+ SDL_WM_SetCaption("SDL Pong", "SDL Pong");
+ SDL_ShowCursor(SDL_DISABLE);
+
+ Ball = CreateBall("20x20.png");
+ Left = CreatePaddle("paddle.png");
+ Right = CreatePaddle("paddle.png");
+
+ Start = CreateText(DejaVu, "Press Space to start.", &white->components);
+ Again = CreateText(DejaVu, "Play Again? [y/n]", &white->components);
+ Player = CreateText(DejaVu, "Player ", &white->components);
+ P1Score = CreateText(DejaVu, "0", &white->components);
+ P2Score = CreateText(DejaVu, "0", &white->components);
+ Wins = CreateText(DejaVu, " Wins!", &white->components);
+ One = CreateText(DejaVu, "1", &white->components);
+ Two = CreateText(DejaVu, "2", &white->components);
+
+ Start->Rect.x = (Game.width / 2) - (Start->Rect.w / 2);
+ Start->Rect.y = (Game.height / 2) + 200;
+ Again->Rect.x = (Game.width / 2) - (Again->Rect.w / 2);
+ Again->Rect.y = (Game.height / 2) - (Again->Rect.h / 2);
+ Player->Rect.x = (Game.width / 2) - (Wins->Rect.w / 2) - (Player->Rect.w / 2);
+ Player->Rect.y = (Game.height / 2) - 100;
+ One->Rect.x = Player->Rect.x + Player->Rect.w;
+ One->Rect.y = Player->Rect.y;
+ Two->Rect.x = Player->Rect.x + Player->Rect.w;
+ Two->Rect.y = Player->Rect.y;
+ Wins->Rect.x = Two->Rect.x + Two->Rect.w;
+ Wins->Rect.y = Player->Rect.y;
+ P1Score->Rect.w = P1Score->Surface->w;
+ P1Score->Rect.h = P1Score->Surface->h;
+ P1Score->Rect.x = 70;
+ P1Score->Rect.y = 1;
+ P2Score->Rect.w = P2Score->Surface->w;
+ P2Score->Rect.h = P2Score->Surface->h;
+ P2Score->Rect.x = Game.width - P2Score->Rect.w - 70;
+ P2Score->Rect.y = 1;
+
+ Left->Paddle.x = 25;
+ Left->Top.x = Left->Paddle.x;
+ Left->Bottom.x = Left->Paddle.x;
+ Right->Paddle.x = Game.width - Right->Paddle.w - 25;
+ Right->Top.x = Right->Paddle.x;
+ Right->Bottom.x = Right->Paddle.x;
+ /* Set Y values to prevent DrawRect from screwing us over
+ * Padding SDL_Rects with NULL y values with throw mess up the h value
+ */
+ Left->Paddle.y = 0;
+ Right->Paddle.y = 0;
+
+ while ( Game.play == 1 ) {
+ SDL_BlitSurface(Start->Surface, NULL, Surface, &Start->Rect);
+ SDL_UpdateRect(Surface, Start->Rect.x, Start->Rect.y, Start->Rect.w, Start->Rect.h);
+ UpdateScore(P1Score, Left->Score);
+ UpdateScore(P2Score, Right->Score);
+ Reset();
+
+ for (;;) {
+ if ( Event.type == SDL_QUIT ) {
+ goto cleanup;
+ }
+ if ( SDL_PollEvent(&Event) != 0 ) {
+ if ( Event.type == SDL_KEYDOWN ) {
+ if ( Event.key.keysym.sym == SDLK_SPACE ) {
+ DrawRect(&Start->Rect, black->color);
+ break;
+ } else if ( Event.key.keysym.sym == SDLK_ESCAPE ) {
+ goto cleanup;
+ }
+ }
+ }
+ SDL_Delay(10);
+ }
+
+ while ( Game.done == 0 ) {
+ if ( SDL_PollEvent(&Event) != 0 ) {
+ if ( Event.type == SDL_QUIT ) {
+ goto cleanup;
+ }
+ if ( Event.type == SDL_KEYDOWN ) {
+ if ( Event.key.keysym.sym == SDLK_ESCAPE ) {
+ goto cleanup;
+ }
+ if ( Event.key.keysym.sym == SDLK_p ) {
+ for (;;) {
+ if ( SDL_PollEvent(&Event) != 0 ) {
+ if ( Event.type == SDL_QUIT ) {
+ goto cleanup;
+ }
+ if ( Event.type == SDL_KEYDOWN ) {
+ if ( Event.key.keysym.sym == SDLK_ESCAPE ) {
+ goto cleanup;
+ }
+ if ( Event.key.keysym.sym == SDLK_p ) {
+ break;
+ }
+ }
+ }
+ SDL_Delay(10);
+ }
+ }
+ }
+ }
+ Game.keystate = SDL_GetKeyState(NULL);
+ MovePaddleUp(Right, SDLK_k);
+ MovePaddleDown(Right, SDLK_m);
+ MovePaddleUp(Left, SDLK_s);
+ MovePaddleDown(Left, SDLK_x);
+
+ if ( Ball->Rect.x <= 0 ) {
+ Right->Score++;
+ UpdateScore(P2Score, Right->Score);
+ if ( (Right->Score > Game.Score_Limit) && ( Right->Score > Left->Score + 1) ) {
+ Game.done = 1;
+ } else {
+ Reset();
+ }
+ } else if ( Ball->Rect.x >= (Game.width - Ball->Rect.w) ) {
+ Left->Score++;
+ UpdateScore(P1Score, Left->Score);
+ if ( (Left->Score > Game.Score_Limit) && (Left->Score > Right->Score + 1) ) {
+ Game.done = 1;
+ } else {
+ Reset();
+ }
+ }
+
+ DrawRect(&Ball->Rect, black->color);
+ Ball->absolute = abs(Ball->xv);
+ for (Ball->counter = 0; Ball->counter < Ball->absolute; Ball->counter++) {
+ if ( Collide(&Right->Paddle, &Ball->Rect) ) {
+ DrawRect(&Right->Paddle, black->color);
+ DrawPaddle(Right);
+ if ( Ball->Rect.y < Right->Paddle.y + (Right->Paddle.h / 4) ){
+ Ball->yv -= 1;
+ } else if ( Ball->Rect.y > Right->Paddle.y + Right->Paddle.h - (Right->Paddle.h / 4) ) {
+ Ball->yv += 1;
+ }
+ Ball->xv = -Ball->xv;
+ } else if ( Collide(&Left->Paddle, &Ball->Rect) ) {
+ DrawRect(&Left->Paddle, black->color);
+ DrawPaddle(Left);
+ if ( Ball->Rect.y < Left->Paddle.y + (Left->Paddle.h / 4) ){
+ Ball->yv -= 1;
+ } else if ( Ball->Rect.y > Left->Paddle.y + Left->Paddle.h - (Left->Paddle.h / 4) ) {
+ Ball->yv += 1;
+ }
+ Ball->xv = -Ball->xv;
+ }
+ if ( Collide(&P1Score->Rect, &Ball->Rect) ) {
+ UpdateScore(P1Score, Left->Score);
+ } else if ( Collide(&P2Score->Rect, &Ball->Rect) ) {
+ UpdateScore(P2Score, Right->Score);
+ }
+ Ball->Rect.x += Ball->xv;
+ }
+ Ball->absolute = abs(Ball->yv);
+ for (Ball->counter = 0; Ball->counter < Ball->absolute; Ball->counter++) {
+ if ( ( Collide(&Left->Top, &Ball->Rect)
+ || Collide(&Right->Top, &Ball->Rect) )
+ && Ball->yv > 0 ) {
+ Ball->yv = -Ball->yv;
+ } else if ( ( Collide(&Left->Bottom, &Ball->Rect)
+ || Collide(&Right->Bottom, &Ball->Rect) )
+ && Ball->yv < 0 ) {
+ Ball->yv = -Ball->yv;
+ }
+ if ( Ball->Rect.y <= 0 ) {
+ Ball->yv = -Ball->yv;
+ Ball->Rect.y = 0;
+ } else if ( Ball->Rect.y >= Game.height - Ball->Rect.h ) {
+ Ball->yv = -Ball->yv;
+ Ball->Rect.y = Game.height - Ball->Rect.h;
+ }
+ Ball->Rect.y += Ball->yv;
+ }
+ SDL_BlitSurface(Ball->Surface, NULL, Surface, &Ball->Rect);
+ SDL_UpdateRect(Surface, Ball->Rect.x, Ball->Rect.y, Ball->Rect.w, Ball->Rect.h);
+ SDL_Delay(10);
+
+ if ( Game.done == 1 ) {
+ DrawRect(&Ball->Rect, black->color);
+ DrawRect(&Left->Paddle, black->color);
+
+ DrawRect(&Right->Paddle, black->color);
+ SDL_BlitSurface(Again->Surface, NULL, Surface, &Again->Rect);
+ SDL_BlitSurface(Player->Surface, NULL, Surface, &Player->Rect);
+ if ( Left->Score > Right->Score ) {
+ SDL_BlitSurface(One->Surface, NULL, Surface, &One->Rect);
+ } else {
+ SDL_BlitSurface(Two->Surface, NULL, Surface, &Two->Rect);
+ }
+ SDL_BlitSurface(Wins->Surface, NULL, Surface, &Wins->Rect);
+ SDL_UpdateRect(Surface, Again->Rect.x, Again->Rect.y, Again->Rect.w, Again->Rect.h);
+ SDL_UpdateRect(Surface, Player->Rect.x, Player->Rect.y, Player->Rect.w + Two->Rect.w + Wins->Rect.w, Player->Rect.h);
+
+ for (;;) {
+ if ( SDL_PollEvent(&Event) != 0 ) {
+ if ( Event.type == SDL_QUIT ) {
+ goto cleanup;
+ }
+ if ( Event.type == SDL_KEYDOWN ) {
+ if ( (Event.key.keysym.sym == SDLK_n) || (Event.key.keysym.sym == SDLK_ESCAPE) ) {
+ goto cleanup;
+ } else if ( Event.key.keysym.sym == SDLK_y ) {
+ Game.done = 0;
+ Left->Score = 0;
+ Right->Score = 0;
+ DrawRect(&Again->Rect, black->color);
+ SDL_FillRect(Surface, &Player->Rect, black->color);
+ SDL_FillRect(Surface, &Two->Rect, black->color);
+ SDL_FillRect(Surface, &Wins->Rect, black->color);
+ SDL_UpdateRect(Surface, Player->Rect.x, Player->Rect.y, Player->Rect.w + Two->Rect.w + Wins->Rect.w, Player->Rect.h);
+ UpdateScore(P1Score, Left->Score);
+ UpdateScore(P2Score, Right->Score);
+ Reset();
+ break;
+ }
+ }
+ }
+ SDL_Delay(10);
+ }
+ }
+ }
+ }
+cleanup:
+ free(black);
+ free(white);
+ DeleteBall(Ball);
+ DeletePaddle(Right);
+ DeletePaddle(Left);
+ DeleteText(Start);
+ DeleteText(Again);
+ DeleteText(Player);
+ DeleteText(Wins);
+ DeleteText(P1Score);
+ DeleteText(P2Score);
+ DeleteText(One);
+ DeleteText(Two);
+ return 0;
+}
+
+void Reset() {
+ DrawRect(&Ball->Rect, black->color);
+ DrawRect(&Left->Paddle, black->color);
+ DrawRect(&Right->Paddle, black->color);
+ Left->Paddle.y = (Game.height / 2) - (Left->Paddle.h / 2);
+ Left->Top.y = Left->Paddle.y - 1;
+ Left->Bottom.y = Left->Paddle.y + Left->Paddle.h + 1;
+ Right->Paddle.y = (Game.height / 2) - (Right->Paddle.h / 2);
+ Right->Top.y = Right->Paddle.y - 1;
+ Right->Bottom.y = Right->Paddle.y + Right->Paddle.h + 1;
+ Ball->Rect.x = (Game.width / 2) - (Ball->Rect.w / 2);
+ Ball->Rect.y = 1;
+ Ball->xv = (rand() % 2) ? 2 : -2;
+ Ball->yv = (rand() % 2) ? 2 : -2;
+ DrawBall(Ball);
+ DrawPaddle(Left);
+ DrawPaddle(Right);
+ SDL_Delay(500);
+}
+
+void DrawRect(SDL_Rect * rect, Uint32 color) {
+ SDL_FillRect(SDL_GetVideoSurface(), rect, color);
+ SDL_UpdateRect(SDL_GetVideoSurface(), rect->x, rect->y, rect->w, rect->h);
+}
+
+void UpdateScore(Text_t * Text, Uint8 score) {
+ char buffer[4];
+ DrawRect(&Text->Rect, black->color);
+ sprintf(buffer, "%u", score);
+ UpdateText(Text, DejaVu, buffer, &white->components);
+ Text->Rect.w = Text->Surface->w;
+ Text->Rect.h = Text->Surface->h;
+ SDL_BlitSurface(Text->Surface, NULL, SDL_GetVideoSurface(), &Text->Rect);
+ SDL_UpdateRect(SDL_GetVideoSurface(), Text->Rect.x, Text->Rect.y, Text->Rect.w, Text->Rect.h);
+}
+
+int Collide(SDL_Rect * a, SDL_Rect * b) {
+ if ( b->x + b->w < a->x ) return 0;
+ if ( b->x > a->x + a->w ) return 0;
+ if ( b->y + b->h < a->y ) return 0;
+ if ( b->y > a->y + a->h ) return 0;
+ return 1;
+}