#include "SDL.h" #include "SDL_image.h" #include "SDL_ttf.h" #include #include #include #include #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; }