//Edited by Chris /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "menu.h" int SCR_X = 800; int SCR_Y = 600; #define PADDLE_X 16 #define PADDLE_Y 64 #define BALL_X 16 #define BALL_Y 15 #define PADDLE_MIDDLE PADDLE_Y/2 #define VERSION "V 0.3" #define TICK_INTERVAL 5 #define GAP 30 int MOVE_Y = SCR_Y/80; int ai = 1; SDL_Surface *screen, *background, *font; SDL_Rect blank_screen; SDL_Event event; Uint32 black; static Uint32 next_time; char points[10]; char points_title[50] = "\'s Points: "; char who_live[50]; char winner_title[50] = " Won!"; char winner[50]; bool full_screen = 0; extern object adam, david, ball; extern char file_path[]; Uint32 time_left() { Uint32 now; now = SDL_GetTicks(); if(next_time <= now) return 0; else return next_time - now; } void movement(Node*); void (*commander) (Node*) = &movement; // Image loading function - takes a filename and whether or not // the image is transparent and converts it to an SDL_Surface SDL_Surface *LoadImage(char *datafile, int transparent) { SDL_Surface *image, *surface; char datatemp[70]; sprintf(datatemp, "%s%s", file_path, datafile); image = IMG_Load(datafile); if( image == NULL) { image = IMG_Load(datatemp); } if ( image == NULL ) { fprintf(stderr, "Couldn't load image %s: %s\n", datatemp, IMG_GetError()); return(NULL); } if ( transparent ) { /* Assuming 8-bit BMP image */ SDL_SetColorKey(image, (SDL_SRCCOLORKEY|SDL_RLEACCEL), *(Uint16 *)image->pixels); surface = SDL_DisplayFormat(image); SDL_FreeSurface(image); return (surface); } return(image); } void clean_up() { SDL_FreeSurface(adam.image); SDL_FreeSurface(david.image); SDL_FreeSurface(ball.image); SDL_FreeSurface(screen); printf("Destroying surfaces\n"); SDL_Quit(); exit(0); } void wait_until_keypressed() { event.type = SDL_KEYUP; while(event.type != SDL_KEYDOWN) { SDL_WaitEvent(&event); if(event.type == SDL_QUIT) clean_up(); } } void update_timer() { next_time = SDL_GetTicks() + TICK_INTERVAL; SDL_Delay(time_left()); next_time += TICK_INTERVAL; } // clears the screen and displays message in the center. when a key is pressed the // screen is then cleared void important_message(char *message, int y) { blank_screen.x = blank_screen.y=0; blank_screen.w = SCR_X; blank_screen.h = SCR_Y; SDL_FillRect(screen, &blank_screen, black); SDL_UpdateRects(screen, 1, &blank_screen); if(y == 0) { PutString(screen, SCR_X/2-TextWidth(message)/2, SCR_Y/2-font->h/2, message); } else { PutString(screen, SCR_X/2-TextWidth(message)/2, (y-font->h)/2, message); } SDL_UpdateRect(screen, 0,0,0,0); wait_until_keypressed(); } void place_objects() { InitFont(font); clear_surface(screen); SDL_BlitSurface(ball.image, NULL, screen, &ball.rect); SDL_BlitSurface(adam.image, NULL, screen, &adam.rect); SDL_BlitSurface(david.image, NULL, screen, &david.rect); SDL_UpdateRects(screen, 1, &david.rect); SDL_UpdateRects(screen, 1, &adam.rect); SDL_UpdateRects(screen, 1, &ball.rect); strcpy(adam.who_live, adam.name); strcat(adam.who_live, points_title); sprintf(points, "%d", adam.points); PutString(screen, 0, 0, adam.who_live); PutString(screen, TextWidth(adam.who_live)+3, 0, points); strcpy(david.who_live, david.name); strcat(david.who_live, points_title); sprintf(points, "%d", david.points); PutString(screen, SCR_X-(TextWidth(david.who_live)+TextWidth("xxx")), 0, david.who_live); PutString(screen, SCR_X-TextWidth("abc"), 0, points); SDL_UpdateRect(screen, 0,0,0,0); blank_screen.w=TextWidth("abc"); blank_screen.h=GAP; } void init_game() { //Node* head = NULL; char title[15]; printf("Initializing the display . . . \n"); if(SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Can't init: %s\n", SDL_GetError()); exit(1); } if(!full_screen) screen = SDL_SetVideoMode(SCR_X, SCR_Y, 16, SDL_HWSURFACE); else screen = SDL_SetVideoMode(SCR_X, SCR_Y, 16, SDL_HWSURFACE | SDL_FULLSCREEN); sprintf(title,"Peng-Pong %s",VERSION); SDL_WM_SetCaption(title, NULL); font=LoadImage("24P_Copperplate_Blue.png", 0); background=LoadImage("logo.jpg", 0); if(font == NULL) { fprintf(stderr, "Can't load font. Get it stupid!"); SDL_Quit(); exit(1); } InitFont(font); blank_screen.x = blank_screen.y=0; blank_screen.w = SCR_X; blank_screen.h = SCR_Y; SDL_FillRect(screen, &blank_screen, black); SDL_UpdateRects(screen, 1, &blank_screen); blank_screen.x=SCR_X/2-(background->w/2); blank_screen.y=SCR_Y/2-(background->h/2); blank_screen.w=background->w; blank_screen.h=background->h; SDL_BlitSurface(background, NULL, screen, &blank_screen); SDL_UpdateRects(screen, 1, &blank_screen); SDL_UpdateRect(screen, 0,0,0,0); wait_until_keypressed(); //clear_surface(screen); //main_menu(head); // gets the ball ready for action by starting it in the // middle of the screen with a 5x5 pixel motion ball.mx = int(MOVE_Y*.75); ball.my = int(MOVE_Y*.75); ball.x = SCR_X/2; ball.y = SCR_Y/2; ball.rect.x = ball.x; ball.rect.y = ball.y; ball.image = LoadImage("ball.tga", 0); ball.rect.w = ball.image->w; ball.rect.h = ball.image->h; black = SDL_MapRGB(screen->format, 0, 0, 0); adam.x = PADDLE_X; adam.y = SCR_Y/2; adam.rect.x = PADDLE_X; adam.rect.y = SCR_Y/2; adam.my = 0; adam.mx = 0; adam.image = LoadImage("paddle.tga", 0); adam.rect.w = adam.image->w; adam.rect.h = adam.image->h; adam.points = david.points = number_points; david.x = (SCR_X - 2*PADDLE_X); david.y = SCR_Y/2; david.rect.x = (SCR_X - 2*PADDLE_X); david.rect.y = SCR_Y/2; david.mx = 0; david.my = 0; david.image = LoadImage("paddle.tga", 0); david.rect.w = adam.image->w; david.rect.h = adam.image->h; blank_screen.x = blank_screen.y = 0; blank_screen.w = SCR_X; blank_screen.h = SCR_Y; read_config_file(); } // check for collisions, dummy void collision_detect() { // if the ball hits the top or the bottom of the screen, // reverse it's direction vertically if(((ball.rect.y + ball.my) <= (GAP)) || ((ball.rect.y + ball.my) >= (SCR_Y - SCR_Y/96))) ball.my = -ball.my; // if it hits the left paddle if((ball.rect.x + ball.mx) <= (adam.rect.x + adam.image->w)) { if((ball.rect.y + ball.my <= adam.rect.y + adam.image->h) && (ball.rect.y + ball.my >= adam.rect.y) && (ball.mx < 0)) { adam.points++; sprintf(points, "%d", adam.points); blank_screen.x=TextWidth(adam.who_live); blank_screen.y=0; SDL_FillRect(screen, &blank_screen, black); SDL_UpdateRects(screen, 1, &blank_screen); PutString(screen, TextWidth(adam.who_live), 0, points); SDL_UpdateRect(screen, 0,0, SCR_X, GAP); ball.mx=-ball.mx; } // if the ball hits the top of the paddle if((ball.rect.y + ball.rect.h) == (adam.rect.y + adam.my)) { printf("TOP! %d\n", adam.rect.y); ball.mx = -ball.mx; ball.my = -ball.my; } // if the ball hits the bottom of the paddle else if((ball.rect.y) == (adam.rect.y + adam.image->h + adam.my)) { printf("BOTTOM! %d\n", adam.rect.y); ball.mx = -ball.mx; ball.my = -ball.my; } /*else { if(ball.rect.y <= adam.rect.y + adam.image->h/2) ball.my = adam.rect.y - ball.rect.y; else ball.my = ball.rect.y - (adam.rect.y + adam.image->h); }*/ } // if it hits the right paddle if((ball.rect.x + ball.mx + ball.image->w) >= (david.rect.x)) { if((ball.rect.y + ball.my <= david.rect.y + david.image->h) && (ball.rect.y + ball.my >= david.rect.y) && (ball.mx > 0)) { david.points++; sprintf(points, "%d", david.points); blank_screen.x=SCR_X-TextWidth("abc"); blank_screen.y=0; SDL_FillRect(screen, &blank_screen, black); SDL_UpdateRects(screen, 1, &blank_screen); PutString(screen, SCR_X-TextWidth("abc"), 0, points); SDL_UpdateRect(screen, 0,0, SCR_X, GAP); ball.mx = -ball.mx; } // if the ball hits the top of the paddle if((ball.rect.y + ball.rect.h + ball.my) == (david.rect.y+david.my)) { printf("TOP! %d\n", david.rect.y); ball.mx = -ball.mx; ball.my = -ball.my; } // if the ball hits the bottom of the paddle if((ball.rect.y + ball.my) == (david.rect.y + david.image->h + david.my)) { printf("BOTTOM! %d\n", david.rect.y); ball.mx = -ball.mx; ball.my = -ball.my; } } // if the ball hits the left side of the screen, then adam loses a life if((ball.rect.x + ball.mx) <= SCR_X/30) { strcpy(winner, david.name); strcat(winner, winner_title); important_message(winner, 0); write_config_file(); init_game(); clear_surface(screen); place_objects(); } // if the ball hits the right side of the screen, david gains a point if((ball.rect.x + ball.mx) >= (SCR_X - SCR_X/30)) { strcpy(winner, adam.name); strcat(winner, winner_title); important_message(winner, 0); write_config_file(); init_game(); clear_surface(screen); place_objects(); } if(ball.my <= 2 && ball.my >= 0) ball.my = 2; if(ball.mx <= 2 && ball.mx >=0) ball.mx = 2; if(ball.mx >= -2 && ball.mx <= 0) ball.mx = -2; if(ball.my >= -2 && ball.my <= 0) ball.my = -2; } // hmmm - what does this do? void update_ball() { SDL_Rect buff_erect[2]; // don't execute the following if it's all gonna be off the screen (that would be bad) if(!(((ball.rect.x + ball.mx) <= (adam.image->w + adam.rect.x) || (ball.rect.x+ball.mx) >= (david.rect.x)) && (ball.rect.y <= GAP || ball.rect.y >= (SCR_Y - SCR_Y/96)))) { // Set buff_erect[0] equal to ball.rect and write the old // position with black onto the screen buff_erect[0] = ball.rect; SDL_FillRect(screen, &buff_erect[0], black); // set the ball to its new position and sticks it into // buff_erect[1] ball.rect.x += ball.mx; ball.rect.y += ball.my; buff_erect[1] = ball.rect; SDL_BlitSurface(ball.image, NULL, screen, &buff_erect[1]); SDL_UpdateRects(screen, 2, buff_erect); } } void update_screen(object * user) { SDL_Rect rects[2]; // if the user's paddle hits the top of the screen if((user->rect.y+user->my) <= GAP) { user->my=0; rects[0] = user->rect; SDL_FillRect(screen, &rects[0], black); SDL_UpdateRects(screen, 1, &rects[0]); user->rect.y = GAP+1; } // if the user's paddle hits the bottom of the screen if((user->rect.y+user->image->h+user->my) >= (SCR_Y - MOVE_Y)) { user->my=0; rects[0] = user->rect; SDL_FillRect(screen, &rects[0], black); SDL_UpdateRects(screen, 1, &rects[0]); user->rect.y = (SCR_Y - PADDLE_Y - MOVE_Y - 2); } // if you don't move, then you don't display it! //if(user->my != 0 ) //{ int tempy = 0 ; tempy = user->rect.y; rects[0] = user->rect; SDL_FillRect(screen, &rects[0], black); user->rect.y+=user->my; rects[1] = user->rect; SDL_BlitSurface(user->image, NULL, screen, &rects[1]); SDL_UpdateRects(screen, 2, rects); //} } void game_loop() { // perform game loop operations collision_detect(); update_ball(); update_screen(&david); update_screen(&adam); update_timer(); } void movement(Node *head) { SDL_ShowCursor(0); int quit = 0; clear_surface(screen); place_objects(); while(!quit) { game_loop(); //ai_move(&adam); if(ai) if(ai == 1) ai_move(&david); if(ai == 2) { ai_move(&adam); ai_move(&david); } while(SDL_PollEvent(&event)) { switch(event.type) { // When the window is closed (X button), quit case SDL_QUIT: write_config_file(); quit = 1; break; case SDL_KEYDOWN: switch(event.key.keysym.sym) { // When the escape button is pressed case SDLK_ESCAPE: start_me(); game_menu(head); break; case SDLK_f: full_screen = true; SDL_WM_ToggleFullScreen(screen); break; case SDLK_q: adam.my=-(MOVE_Y); break; case SDLK_a: adam.my=(MOVE_Y); break; case SDLK_o: if(ai == 0) { david.my=-(MOVE_Y); break; } case SDLK_l: if(ai == 0) { david.my=(MOVE_Y); break; } default: break; } break; case SDL_KEYUP: switch(event.key.keysym.sym) { case SDLK_q: if(adam.my < 0) adam.my=0; break; case SDLK_a: if(adam.my > 0) adam.my=0; break; case SDLK_o: if(ai == 0) { if(david.my < 0) david.my=0; break; } case SDLK_l: if(ai == 0) { if(david.my > 0) david.my=0; break; } default: break; } break; default: break; } } } } /*void start_demo(Node *head) { start_me(); main_menu(head); ai = 2; }*/ int main() { Node *head = NULL; strcpy(adam.name,"Player 1"); strcpy(david.name,"Player 2"); init_game(); movement(head); printf("Thanks for playing Peng-Pong %s\n", VERSION); clean_up(); return 0; }