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