1 //Edited by Chris
2
3 /*
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include "menu.h"
23
24 int SCR_X = 800;
25 int SCR_Y = 600;
26
27
28 #define PADDLE_X 16
29 #define PADDLE_Y 64
30 #define BALL_X 16
31 #define BALL_Y 15
32 #define PADDLE_MIDDLE PADDLE_Y/2
33 #define VERSION "V 0.3"
34 #define TICK_INTERVAL 5
35 #define GAP 30
36 int MOVE_Y = SCR_Y/80;
37
38 int ai = 1;
39 SDL_Surface *screen, *background, *font;
40 SDL_Rect blank_screen;
41 SDL_Event event;
42 Uint32 black;
43 static Uint32 next_time;
44 char points[10];
45 char points_title[50] = "\'s Points: ";
46 char who_live[50];
47 char winner_title[50] = " Won!";
48 char winner[50];
49 bool full_screen = 0;
50
51 extern object adam, david, ball;
52 extern char file_path[];
53
54
time_left()55 Uint32 time_left()
56 {
57 Uint32 now;
58 now = SDL_GetTicks();
59 if(next_time <= now)
60 return 0;
61 else
62 return next_time - now;
63 }
64
65
66 void movement(Node*);
67
68 void (*commander) (Node*) = &movement;
69
70 // Image loading function - takes a filename and whether or not
71 // the image is transparent and converts it to an SDL_Surface
LoadImage(char * datafile,int transparent)72 SDL_Surface *LoadImage(char *datafile, int transparent)
73 {
74 SDL_Surface *image, *surface;
75 char datatemp[70];
76 sprintf(datatemp, "%s%s", file_path, datafile);
77 image = IMG_Load(datafile);
78 if( image == NULL)
79 {
80 image = IMG_Load(datatemp);
81 }
82
83 if ( image == NULL ) {
84 fprintf(stderr, "Couldn't load image %s: %s\n",
85 datatemp, IMG_GetError());
86 return(NULL);
87 }
88
89 if ( transparent ) {
90 /* Assuming 8-bit BMP image */
91 SDL_SetColorKey(image, (SDL_SRCCOLORKEY|SDL_RLEACCEL),
92 *(Uint16 *)image->pixels);
93 surface = SDL_DisplayFormat(image);
94 SDL_FreeSurface(image);
95 return (surface);
96 }
97
98 return(image);
99 }
100
clean_up()101 void clean_up()
102 {
103 SDL_FreeSurface(adam.image);
104 SDL_FreeSurface(david.image);
105 SDL_FreeSurface(ball.image);
106 SDL_FreeSurface(screen);
107
108 printf("Destroying surfaces\n");
109 SDL_Quit();
110 exit(0);
111 }
112
wait_until_keypressed()113 void wait_until_keypressed()
114 {
115 event.type = SDL_KEYUP;
116
117 while(event.type != SDL_KEYDOWN)
118 {
119 SDL_WaitEvent(&event);
120 if(event.type == SDL_QUIT)
121 clean_up();
122 }
123 }
124
update_timer()125 void update_timer()
126 {
127 next_time = SDL_GetTicks() + TICK_INTERVAL;
128 SDL_Delay(time_left());
129 next_time += TICK_INTERVAL;
130 }
131
132 // clears the screen and displays message in the center. when a key is pressed the
133 // screen is then cleared
134
important_message(char * message,int y)135 void important_message(char *message, int y)
136 {
137
138 blank_screen.x = blank_screen.y=0;
139 blank_screen.w = SCR_X;
140 blank_screen.h = SCR_Y;
141 SDL_FillRect(screen, &blank_screen, black);
142 SDL_UpdateRects(screen, 1, &blank_screen);
143
144 if(y == 0)
145 {
146 PutString(screen, SCR_X/2-TextWidth(message)/2, SCR_Y/2-font->h/2, message);
147 }
148 else
149 {
150 PutString(screen, SCR_X/2-TextWidth(message)/2, (y-font->h)/2, message);
151 }
152
153 SDL_UpdateRect(screen, 0,0,0,0);
154 wait_until_keypressed();
155 }
156
157
place_objects()158 void place_objects()
159 {
160 InitFont(font);
161 clear_surface(screen);
162 SDL_BlitSurface(ball.image, NULL, screen, &ball.rect);
163 SDL_BlitSurface(adam.image, NULL, screen, &adam.rect);
164 SDL_BlitSurface(david.image, NULL, screen, &david.rect);
165
166 SDL_UpdateRects(screen, 1, &david.rect);
167 SDL_UpdateRects(screen, 1, &adam.rect);
168 SDL_UpdateRects(screen, 1, &ball.rect);
169
170 strcpy(adam.who_live, adam.name);
171 strcat(adam.who_live, points_title);
172 sprintf(points, "%d", adam.points);
173 PutString(screen, 0, 0, adam.who_live);
174 PutString(screen, TextWidth(adam.who_live)+3, 0, points);
175
176 strcpy(david.who_live, david.name);
177 strcat(david.who_live, points_title);
178 sprintf(points, "%d", david.points);
179 PutString(screen, SCR_X-(TextWidth(david.who_live)+TextWidth("xxx")), 0,
180 david.who_live);
181 PutString(screen, SCR_X-TextWidth("abc"), 0, points);
182 SDL_UpdateRect(screen, 0,0,0,0);
183 blank_screen.w=TextWidth("abc");
184 blank_screen.h=GAP;
185 }
186
init_game()187 void init_game()
188 {
189
190 //Node* head = NULL;
191 char title[15];
192 printf("Initializing the display . . . \n");
193
194 if(SDL_Init(SDL_INIT_VIDEO) < 0)
195 {
196 fprintf(stderr, "Can't init: %s\n", SDL_GetError());
197 exit(1);
198 }
199
200 if(!full_screen)
201 screen = SDL_SetVideoMode(SCR_X, SCR_Y, 16, SDL_HWSURFACE);
202 else
203 screen = SDL_SetVideoMode(SCR_X, SCR_Y, 16, SDL_HWSURFACE |
204 SDL_FULLSCREEN);
205
206 sprintf(title,"Peng-Pong %s",VERSION);
207 SDL_WM_SetCaption(title, NULL);
208 font=LoadImage("24P_Copperplate_Blue.png", 0);
209 background=LoadImage("logo.jpg", 0);
210
211 if(font == NULL)
212 {
213 fprintf(stderr, "Can't load font. Get it stupid!");
214 SDL_Quit();
215 exit(1);
216 }
217
218 InitFont(font);
219
220 blank_screen.x = blank_screen.y=0;
221 blank_screen.w = SCR_X;
222 blank_screen.h = SCR_Y;
223 SDL_FillRect(screen, &blank_screen, black);
224 SDL_UpdateRects(screen, 1, &blank_screen);
225 blank_screen.x=SCR_X/2-(background->w/2);
226 blank_screen.y=SCR_Y/2-(background->h/2);
227 blank_screen.w=background->w;
228 blank_screen.h=background->h;
229
230 SDL_BlitSurface(background, NULL, screen, &blank_screen);
231 SDL_UpdateRects(screen, 1, &blank_screen);
232 SDL_UpdateRect(screen, 0,0,0,0);
233 wait_until_keypressed();
234 //clear_surface(screen);
235 //main_menu(head);
236 // gets the ball ready for action by starting it in the
237 // middle of the screen with a 5x5 pixel motion
238 ball.mx = int(MOVE_Y*.75);
239 ball.my = int(MOVE_Y*.75);
240 ball.x = SCR_X/2;
241 ball.y = SCR_Y/2;
242 ball.rect.x = ball.x;
243 ball.rect.y = ball.y;
244 ball.image = LoadImage("ball.tga", 0);
245 ball.rect.w = ball.image->w;
246 ball.rect.h = ball.image->h;
247
248 black = SDL_MapRGB(screen->format, 0, 0, 0);
249
250 adam.x = PADDLE_X;
251 adam.y = SCR_Y/2;
252 adam.rect.x = PADDLE_X;
253 adam.rect.y = SCR_Y/2;
254 adam.my = 0;
255 adam.mx = 0;
256 adam.image = LoadImage("paddle.tga", 0);
257 adam.rect.w = adam.image->w;
258 adam.rect.h = adam.image->h;
259 adam.points = david.points = number_points;
260
261 david.x = (SCR_X - 2*PADDLE_X);
262 david.y = SCR_Y/2;
263 david.rect.x = (SCR_X - 2*PADDLE_X);
264 david.rect.y = SCR_Y/2;
265 david.mx = 0;
266 david.my = 0;
267 david.image = LoadImage("paddle.tga", 0);
268 david.rect.w = adam.image->w;
269 david.rect.h = adam.image->h;
270
271 blank_screen.x = blank_screen.y = 0;
272 blank_screen.w = SCR_X;
273 blank_screen.h = SCR_Y;
274
275 read_config_file();
276 }
277
278 // check for collisions, dummy
collision_detect()279 void collision_detect()
280 {
281
282 // if the ball hits the top or the bottom of the screen,
283 // reverse it's direction vertically
284
285 if(((ball.rect.y + ball.my) <= (GAP)) ||
286 ((ball.rect.y + ball.my) >= (SCR_Y - SCR_Y/96)))
287 ball.my = -ball.my;
288
289
290 // if it hits the left paddle
291
292
293 if((ball.rect.x + ball.mx) <= (adam.rect.x + adam.image->w))
294 {
295
296 if((ball.rect.y + ball.my <= adam.rect.y + adam.image->h) &&
297 (ball.rect.y + ball.my >= adam.rect.y) &&
298 (ball.mx < 0))
299 {
300
301 adam.points++;
302 sprintf(points, "%d", adam.points);
303 blank_screen.x=TextWidth(adam.who_live);
304 blank_screen.y=0;
305 SDL_FillRect(screen, &blank_screen, black);
306 SDL_UpdateRects(screen, 1, &blank_screen);
307 PutString(screen, TextWidth(adam.who_live), 0, points);
308 SDL_UpdateRect(screen, 0,0, SCR_X, GAP);
309 ball.mx=-ball.mx;
310
311 }
312
313 // if the ball hits the top of the paddle
314 if((ball.rect.y + ball.rect.h) == (adam.rect.y + adam.my))
315 {
316 printf("TOP! %d\n", adam.rect.y);
317 ball.mx = -ball.mx;
318 ball.my = -ball.my;
319 }
320
321
322 // if the ball hits the bottom of the paddle
323 else if((ball.rect.y) == (adam.rect.y + adam.image->h + adam.my))
324 {
325 printf("BOTTOM! %d\n", adam.rect.y);
326 ball.mx = -ball.mx;
327 ball.my = -ball.my;
328 }
329
330 /*else
331 {
332 if(ball.rect.y <= adam.rect.y + adam.image->h/2)
333 ball.my = adam.rect.y - ball.rect.y;
334 else
335 ball.my = ball.rect.y - (adam.rect.y +
336 adam.image->h);
337 }*/
338
339 }
340
341 // if it hits the right paddle
342
343 if((ball.rect.x + ball.mx + ball.image->w) >= (david.rect.x))
344 {
345
346 if((ball.rect.y + ball.my <= david.rect.y + david.image->h) &&
347 (ball.rect.y + ball.my >= david.rect.y) &&
348 (ball.mx > 0))
349 {
350 david.points++;
351 sprintf(points, "%d", david.points);
352 blank_screen.x=SCR_X-TextWidth("abc");
353 blank_screen.y=0;
354 SDL_FillRect(screen, &blank_screen, black);
355 SDL_UpdateRects(screen, 1, &blank_screen);
356 PutString(screen, SCR_X-TextWidth("abc"), 0, points);
357 SDL_UpdateRect(screen, 0,0, SCR_X, GAP);
358 ball.mx = -ball.mx;
359 }
360
361
362 // if the ball hits the top of the paddle
363 if((ball.rect.y + ball.rect.h + ball.my) == (david.rect.y+david.my))
364 {
365 printf("TOP! %d\n", david.rect.y);
366 ball.mx = -ball.mx;
367 ball.my = -ball.my;
368 }
369
370 // if the ball hits the bottom of the paddle
371 if((ball.rect.y + ball.my) == (david.rect.y + david.image->h + david.my))
372 {
373 printf("BOTTOM! %d\n", david.rect.y);
374 ball.mx = -ball.mx;
375 ball.my = -ball.my;
376 }
377
378 }
379
380 // if the ball hits the left side of the screen, then adam loses a life
381 if((ball.rect.x + ball.mx) <= SCR_X/30)
382 {
383
384 strcpy(winner, david.name);
385 strcat(winner, winner_title);
386 important_message(winner, 0);
387 write_config_file();
388 init_game();
389 clear_surface(screen);
390 place_objects();
391
392 }
393
394 // if the ball hits the right side of the screen, david gains a point
395 if((ball.rect.x + ball.mx) >= (SCR_X - SCR_X/30))
396 {
397
398 strcpy(winner, adam.name);
399 strcat(winner, winner_title);
400 important_message(winner, 0);
401 write_config_file();
402 init_game();
403 clear_surface(screen);
404 place_objects();
405
406 }
407
408
409 if(ball.my <= 2 && ball.my >= 0)
410 ball.my = 2;
411 if(ball.mx <= 2 && ball.mx >=0)
412 ball.mx = 2;
413 if(ball.mx >= -2 && ball.mx <= 0)
414 ball.mx = -2;
415 if(ball.my >= -2 && ball.my <= 0)
416 ball.my = -2;
417 }
418
419
420
421 // hmmm - what does this do?
update_ball()422 void update_ball()
423 {
424 SDL_Rect buff_erect[2];
425
426
427 // don't execute the following if it's all gonna be off the screen (that would be bad)
428
429 if(!(((ball.rect.x + ball.mx) <= (adam.image->w + adam.rect.x) || (ball.rect.x+ball.mx) >=
430 (david.rect.x)) && (ball.rect.y <= GAP || ball.rect.y >= (SCR_Y - SCR_Y/96))))
431 {
432 // Set buff_erect[0] equal to ball.rect and write the old
433 // position with black onto the screen
434
435
436 buff_erect[0] = ball.rect;
437 SDL_FillRect(screen, &buff_erect[0], black);
438
439 // set the ball to its new position and sticks it into
440 // buff_erect[1]
441
442 ball.rect.x += ball.mx;
443 ball.rect.y += ball.my;
444 buff_erect[1] = ball.rect;
445
446 SDL_BlitSurface(ball.image, NULL, screen, &buff_erect[1]);
447 SDL_UpdateRects(screen, 2, buff_erect);
448
449 }
450 }
451
update_screen(object * user)452 void update_screen(object * user)
453 {
454 SDL_Rect rects[2];
455
456 // if the user's paddle hits the top of the screen
457
458 if((user->rect.y+user->my) <= GAP)
459 {
460 user->my=0;
461 rects[0] = user->rect;
462 SDL_FillRect(screen, &rects[0], black);
463 SDL_UpdateRects(screen, 1, &rects[0]);
464 user->rect.y = GAP+1;
465 }
466
467 // if the user's paddle hits the bottom of the screen
468
469 if((user->rect.y+user->image->h+user->my) >= (SCR_Y - MOVE_Y))
470
471 {
472 user->my=0;
473 rects[0] = user->rect;
474 SDL_FillRect(screen, &rects[0], black);
475 SDL_UpdateRects(screen, 1, &rects[0]);
476 user->rect.y = (SCR_Y - PADDLE_Y - MOVE_Y - 2);
477 }
478
479 // if you don't move, then you don't display it!
480
481 //if(user->my != 0 )
482 //{
483 int tempy = 0 ;
484 tempy = user->rect.y;
485 rects[0] = user->rect;
486 SDL_FillRect(screen, &rects[0], black);
487 user->rect.y+=user->my;
488 rects[1] = user->rect;
489 SDL_BlitSurface(user->image, NULL, screen, &rects[1]);
490 SDL_UpdateRects(screen, 2, rects);
491 //}
492 }
493
game_loop()494 void game_loop()
495 {
496 // perform game loop operations
497
498 collision_detect();
499 update_ball();
500 update_screen(&david);
501 update_screen(&adam);
502 update_timer();
503
504 }
505
movement(Node * head)506 void movement(Node *head)
507 {
508 SDL_ShowCursor(0);
509 int quit = 0;
510 clear_surface(screen);
511 place_objects();
512
513 while(!quit)
514 {
515
516 game_loop();
517 //ai_move(&adam);
518 if(ai)
519 if(ai == 1)
520 ai_move(&david);
521 if(ai == 2)
522 {
523 ai_move(&adam);
524 ai_move(&david);
525 }
526
527 while(SDL_PollEvent(&event))
528 {
529 switch(event.type)
530 {
531 // When the window is closed (X button), quit
532 case SDL_QUIT:
533 write_config_file();
534 quit = 1;
535
536 break;
537
538 case SDL_KEYDOWN:
539 switch(event.key.keysym.sym)
540 {
541
542 // When the escape button is pressed
543 case SDLK_ESCAPE:
544 start_me();
545 game_menu(head);
546 break;
547
548 case SDLK_f:
549 full_screen = true;
550 SDL_WM_ToggleFullScreen(screen);
551 break;
552
553 case SDLK_q:
554 adam.my=-(MOVE_Y);
555 break;
556 case SDLK_a:
557 adam.my=(MOVE_Y);
558 break;
559 case SDLK_o:
560 if(ai == 0)
561 {
562 david.my=-(MOVE_Y);
563 break;
564 }
565 case SDLK_l:
566 if(ai == 0)
567 {
568 david.my=(MOVE_Y);
569 break;
570 }
571 default:
572 break;
573
574 }
575
576 break;
577
578
579 case SDL_KEYUP:
580 switch(event.key.keysym.sym)
581 {
582
583 case SDLK_q:
584 if(adam.my < 0)
585 adam.my=0;
586 break;
587 case SDLK_a:
588 if(adam.my > 0)
589 adam.my=0;
590 break;
591 case SDLK_o:
592 if(ai == 0)
593 {
594 if(david.my < 0)
595 david.my=0;
596 break;
597 }
598 case SDLK_l:
599 if(ai == 0)
600 {
601 if(david.my > 0)
602 david.my=0;
603 break;
604 }
605 default:
606 break;
607 }
608 break;
609
610 default:
611 break;
612 }
613 }
614 }
615
616 }
617
618 /*void start_demo(Node *head)
619 {
620 start_me();
621 main_menu(head);
622 ai = 2;
623
624
625 }*/
626
main()627 int main()
628 {
629 Node *head = NULL;
630 strcpy(adam.name,"Player 1");
631 strcpy(david.name,"Player 2");
632 init_game();
633
634
635 movement(head);
636
637 printf("Thanks for playing Peng-Pong %s\n", VERSION);
638
639 clean_up();
640 return 0;
641 }
642