1 
2 // Food* types. Remember that the vector will need to be purged at the start
3 // of each level.
4 
5 #include <iostream>
6 #include <cstdio>
7 //#include <mcheck.h>
8 //#include <vector>
9 #include "Player.h"
10 #include "Defines.h"
11 #include "Level.h"
12 //#include "Ghost1.h" included from Food.h
13 #include "Ghost2.h"
14 #include "Ghost3.h"
15 #include "Food.h"
16 #include "Bonus.h"
17 #include "SDL_ttf.h"
18 #include "SDL_mixer.h"
19 #include "AnimationFactory.h"
20 
21 #ifndef WIN32
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #endif
25 
26 #define pilltime 200
27 
28 SDL_Surface* screen = NULL;
29 
30 // Now for some global sprites - better done as classes but Oh Well!
31 SDL_Surface* hedge = NULL;
32 SDL_Surface* hedge2 = NULL;
33 SDL_Surface* hedge3 = NULL;
34 SDL_Surface* hedge4 = NULL;
35 SDL_Surface* pill = NULL;
36 SDL_Surface* powerpill = NULL;
37 SDL_Surface* grass = NULL;
38 SDL_Surface* grass2 = NULL;
39 SDL_Surface* grass3 = NULL;
40 SDL_Surface* grass4 = NULL;
41 SDL_Surface* bg = NULL;
42 SDL_Surface* bg2 = NULL;
43 SDL_Surface* gate = NULL;
44 SDL_Surface* story = NULL;
45 SDL_Surface* oneway = NULL;
46 SDL_Surface* howto = NULL;
47 SDL_Surface* border = NULL;
48 SDL_Surface* cross = NULL;
49 SDL_Surface* red_door = NULL;
50 SDL_Surface* red_key = NULL;
51 SDL_Surface* gradient = NULL;
52 SDL_Surface* banner = NULL;
53 SDL_Surface* words = NULL;
54 
55 SDL_Surface* current_hedge = NULL;
56 SDL_Surface* current_grass = NULL;
57 
58 TTF_Font* font = NULL;
59 TTF_Font* subgamefont = NULL;
60 TTF_Font* bigfont = NULL;
61 Mix_Chunk* eatpill = NULL;
62 Mix_Music* bgm1 = NULL;
63 Mix_Chunk* eatmagic = NULL;
64 Mix_Chunk* eatfood = NULL;
65 Mix_Chunk* scream = NULL;
66 Mix_Chunk* chomp = NULL;
67 Mix_Chunk* yeah = NULL;
68 Mix_Chunk* uhoh = NULL;
69 
70 static AnimationFactory* af = new AnimationFactory();
71 Player* hannah;
72 
73 
74 Ghost* red = NULL;
75 Ghost* pink = NULL;
76 Ghost* hay = NULL;
77 Ghost* blue = NULL;
78 
79 vector<Ghost*> ghosties;
80 
81 //THIS IS TEMPORARY - IT NEEDS TO BE IN A VECTOR
82 //Food* carrot = NULL;
83 //Food* apple = NULL;
84 
85 int nextxpos = 50 + (SIZET*7);
86 int nextypos = 50 + (SIZET*7);
87 int ypos = nextypos;
88 int xpos = nextxpos;
89 int direction = 5; // 1, 2, 3, 4, 5 (u,d,l,r,stat)
90 int nextdir = 5;
91 int speed = 6;
92 
93 unsigned int level = 1;
94 int lives = 3;
95 int score = 0;
96 int numlives = 3; // number of lives to start each game with
97 
98 int subgamestate = 1;
99 int pillsleft = 0;
100 
101 enum effecttype {NONE,FREEZE,INVERT,SLOW,INVIS};
102 effecttype effect = NONE;
103 int bonustimer = 0;
104 
105 Uint32 lastticks;
106 Uint32 delta_tick;
107 Uint32 tick;
108 
109 
110 // Array for the map
111 //gridcell map[SIZEX][SIZEY];
112 Level lev;
113 
114 vector<Food*> levelfood;
115 
116 using namespace std;
117 
118 //class Level{
119 //	gridcell map[SIZEX][SIZEY];
120 //};
121 //
122 typedef struct {
123 	int score;
124 	char name[40];
125 
126 } scoreentry;
127 
128 vector<Level> maps;
129 vector<Sprite> food;
130 vector<scoreentry> hiscore;
131 //vector<Bonus*> bonuses;
132 Bonus* the_bonus; // Limit to one bonus at a time
133 
loadHiScores()134 void loadHiScores(){
135 	#ifndef WIN32
136 	char *scoredir;
137 	scoredir = getenv("USER");
138 
139 	string p(scoredir);
140 	p = p + "/.hannah/hiscore.dat";
141 	p = "/home/" + p;
142 	ifstream br;
143 	if(scoredir!=NULL){
144 		br.open(p.c_str());
145 		string hdir(scoredir);
146 		hdir = "/home/" + hdir;
147 		hdir = hdir + "/.hannah/";
148 		if(!br){
149 			mode_t file_mode;
150 			file_mode = (mode_t)0755;
151 			mkdir(hdir.c_str(), file_mode);
152 			hdir = hdir + "hiscore.dat";
153 			ofstream os(hdir.c_str());
154 			cout << "Creating Hiscore table - " << hdir.c_str() << "\n";
155 			os << "25600 sab\n12800 zjc\n6400 hjw\n3200 sab\n1600 zjc\n800 hjw\n400 sab\n200 zjc\n100 hjw\n50 sab\n";
156 			os.close();
157 			br.open(hdir.c_str());
158 		}
159 	} else {
160 		br.open(".hiscore.dat");
161 	}
162 	#else
163 	ifstream br("hiscore.dat");
164 	#endif
165 
166 	// If hiscore doesn't exist, create it (above)
167 
168 	char buffer[40];
169 	int i = 0;
170 	for(i=0; i<10; i++){
171 		br.getline(buffer,40);
172 		char nname[40];
173 		char nscore[40];
174 		sscanf(buffer,"%s %s",nscore,nname);
175 
176 		scoreentry tmp;
177 		tmp.score = atoi(nscore);
178 		strcpy(tmp.name,nname);
179 
180 		//printf("<><>%s %d\n",tmp.name,tmp.score);
181 		hiscore.push_back(tmp);
182 	}
183 	br.close();
184 };
185 
checkHiScores(int score)186 int checkHiScores(int score){ // return the entry location of the new score
187 	int i =0;
188 	int entryAt = 0;
189 	for(i=0;i<10;i++){
190 		if(score >= ((scoreentry)hiscore[i]).score){
191 			entryAt = i;
192 			int j = 10;
193 			while(j > entryAt){
194 				hiscore[j] = hiscore[j-1];
195 				j--;
196 			}
197 			scoreentry news;
198 			news.score = score;
199 			strcpy(news.name,"god");
200 			hiscore[entryAt] = news;
201 			return entryAt;
202 		}
203 	}
204 	return -1;
205 };
206 
setTimer(int time,effecttype e)207 void setTimer(int time, effecttype e){
208 	effect = e;
209 	bonustimer = time;
210 	if(e==INVIS){
211 		hannah->setAnimation("invis");
212 	} else if(hannah->isAnimation("invis")){
213 		hannah->setAnimation("default");
214 	}
215 };
216 
timer()217 void timer(){
218 	if(bonustimer>0){
219 		bonustimer--;
220 	} else {
221 		effect = NONE;
222 		if(hannah->isAnimation("invis"))
223 			hannah->setAnimation("default");
224 	}
225 };
226 
checknext()227 bool checknext(){
228 	// get pacman's actual x y grid position
229 	int ax = (xpos / SIZET) - 1;
230 	int ay = (ypos / SIZET) - 1;
231 
232 //	int x; int y;
233 			switch(direction){
234 				case 1: if((lev.map[ax][ay-1].type=='#' || lev.map[ax][ay-1].type=='~' || lev.map[ax][ay-1].type=='$')){
235 											 return true;
236 										} else { return false;} break;
237 				case 2:  if((lev.map[ax][ay+1].type=='#' || lev.map[ax][ay+1].type=='-' || lev.map[ax][ay+1].type=='~' || lev.map[ax][ay+1].type=='$')){
238 											 return true;
239 										} else { return false;} break;
240 				case 3:	if((lev.map[ax-1][ay].type=='#' || lev.map[ax-1][ay].type=='$')){
241 										return true;
242 									} else { return false; } break;
243 				case 4: if((lev.map[ax+1][ay].type=='#' || lev.map[ax+1][ay].type=='$')){
244 										return true;
245 									} else { return false; } break;
246 			};
247 	return false;
248 };
249 
250 
251 
checkcollisions()252 bool checkcollisions(){
253 	// get pacman's actual x y grid position
254 	int ax = (xpos / SIZET) - 1;
255 	int ay = (ypos / SIZET) - 1;
256 
257 //	int x; int y;
258 			switch(nextdir){
259 				case 1: if((lev.map[ax][ay-1].type=='#' || lev.map[ax][ay-1].type=='~' || lev.map[ax][ay-1].type=='$')){
260 											 return true;
261 										} else { return false;} break;
262 				case 2:  if((lev.map[ax][ay+1].type=='#' || lev.map[ax][ay+1].type=='-' || lev.map[ax][ay+1].type=='~' || lev.map[ax][ay+1].type=='$')){
263 											 return true;
264 										} else { return false;} break;
265 				case 3:	if((lev.map[ax-1][ay].type=='#' || lev.map[ax-1][ay].type=='$')){
266 										return true;
267 									} else { return false; } break;
268 				case 4: if((lev.map[ax+1][ay].type=='#' || lev.map[ax+1][ay].type=='$')){
269 										return true;
270 									} else { return false; } break;
271 			};
272 
273 	return false;
274 };
275 
blit(SDL_Surface * image,int x,int y)276 void blit(SDL_Surface* image, int x, int y){
277 	SDL_Rect dest;
278 	dest.x = x;
279 	dest.y = y;
280 
281 	SDL_BlitSurface(image, NULL, screen, &dest);
282 };
283 
createBonus()284 void createBonus(){
285 	// random number between 1 and 300
286 	//printf("Ticks: %d \n",SDL_GetTicks());
287 	if(the_bonus==NULL && effect==NONE){
288 		if(SDL_GetTicks() % 200 == 0){
289 		//printf("Spawning bonus...\n");
290 		int r = (rand() % 3) + 1;
291 		//if(r==1) cout << "Creating freeze\n";
292 		//if(r==2) cout << "Creating invis\n";
293 		//if(r==3) cout << "Creating invert\n";
294 	//	int rx = (rand() % SIZEX);
295 	//	int ry = (rand() % SIZEY);
296 	//	if(r < 50){
297 	//		//printf("creating bonus\n");
298 	//		while(lev.map[rx][ry].type!='.'){
299 	//			rx = (rand() % SIZEX);
300 	//			ry = (rand() % SIZEY);
301 	//			//printf("Testing (%d,%d) = %c\n",rx,ry,lev.map[rx][ry].type);
302 	//		}
303 
304 			//Bonus* b;
305 			switch(r){
306 			case 1: the_bonus = new Bonus("freeze",7,7,1,af,'f'); break;
307 			case 2: the_bonus = new Bonus("invis",7,7,1,af,'i'); break;
308 			case 3: the_bonus = new Bonus("invert",7,7,1,af,'s'); break;
309 			};
310 			the_bonus->setLevel(lev,7,7);
311 			//bonuses.push_back(b);
312 	//	}
313 		}
314 	}
315 };
316 
moveBonus()317 void moveBonus(){
318 	if(the_bonus!=NULL){
319 		//for(i=0; i<bonuses.size(); i++){
320 			the_bonus->move(xpos,ypos);
321 			blit(the_bonus->frame(), the_bonus->x(), the_bonus->y());
322 			the_bonus->decLife();
323 			if(the_bonus->lifeforce == 0){
324 				//vector<Bonus*>::iterator itRemove = bonuses.begin() + i;
325 				//bonuses.erase(itRemove);
326 				delete the_bonus;
327 			//	cout << the_bonus << "\n";
328 				the_bonus = NULL;
329 			//	cout << the_bonus << "\n";
330 			}
331 		//}
332 	}
333 };
334 
check_bonus_pacman()335 void check_bonus_pacman(){
336 	if(the_bonus!=NULL){
337 			if((the_bonus->x() < xpos+30) && (the_bonus->x()+30 > xpos) && (the_bonus->y()+30 > ypos) && (the_bonus->y() < ypos+30)){
338 				// Pacman gets pill
339 				//vector<Bonus*>::iterator itRemove = bonuses.begin() + i;
340 				//bonuses.erase(itRemove);
341 				switch(the_bonus->type){
342 					case 'f':	setTimer(200,FREEZE); Mix_PlayChannel(-1,yeah,0); break;
343 					case 's':	setTimer(200,INVERT); Mix_PlayChannel(-1,uhoh,0); break;
344 					case 'i':	setTimer(200,INVIS); Mix_PlayChannel(-1,yeah,0); break;
345 				};
346 				delete the_bonus;
347 				the_bonus = NULL;
348 			}
349 	}
350 };
351 /*
352 void freeBonus(){
353 	int i;
354 	for(i=0; i<bonuses.size(); i++){
355 		Bonus* tmp = (Bonus*)bonuses[i];
356 		delete tmp;
357 	}
358 	bonuses.clear();
359 };
360 */
361 
drawMap()362 void drawMap(){
363 	int x; int y;
364 	x = 0;
365 	y = 0;
366 	int mapx = 0;
367 	int mapy = 0;
368 	for(mapy = 0; mapy < SIZEY; mapy++){
369 	for(mapx = 0; mapx < SIZEX; mapx++){
370 		switch(lev.map[mapx][mapy].type){
371 			case '#': blit(current_hedge,(mapx*SIZET)+50,(mapy*SIZET)+50); break;
372 			case '.': blit(current_grass,(mapx*SIZET)+50,(mapy*SIZET)+50);
373 				  blit(pill, (mapx*SIZET)+50,(mapy*SIZET)+50);
374 				break;
375 			case '_': blit(current_grass,(mapx*SIZET)+50,(mapy*SIZET)+50); break;
376 			case 'p': blit(current_grass,(mapx*SIZET)+50,(mapy*SIZET)+50);
377 					blit(powerpill,(mapx*SIZET)+50,(mapy*SIZET)+50); break;
378 			case '-':	blit(current_grass,(mapx*SIZET)+50,(mapy*SIZET)+50);
379 								blit(gate,(mapx*SIZET)+50,(mapy*SIZET)+50); break;
380 			case '~':	blit(current_grass,(mapx*SIZET)+50,(mapy*SIZET)+50);
381 								blit(oneway,(mapx*SIZET)+50,(mapy*SIZET)+50); break;
382 			case 'x':	blit(current_grass,(mapx*SIZET)+50,(mapy*SIZET)+50);
383 								blit(cross,(mapx*SIZET)+50,(mapy*SIZET)+50); break;
384 			case '$':	blit(current_grass,(mapx*SIZET)+50,(mapy*SIZET)+50);
385 								blit(red_door,(mapx*SIZET)+50,(mapy*SIZET)+50); break;
386 			case 'r':	blit(current_grass,(mapx*SIZET)+50,(mapy*SIZET)+50);
387 								blit(red_key,(mapx*SIZET)+50,(mapy*SIZET)+50); break;
388 
389 
390 		};
391 	}
392 	}
393 	blit(hannah->frame(),xpos,ypos);
394 };
395 
mapout()396 void mapout(){
397 };
398 
level_init_food(Level levl)399 void level_init_food(Level levl){
400 	// While there are more foods in lev.foods create add to vector of food
401 	//printf("Init food...\n");
402 	lev.foods.clear();
403 	unsigned int i = 0;
404 	//printf("Level's food buffer is %d\n",levl.foods.size());
405 	for(i=0; i<levl.foods.size(); i++){
406 		foodinfo tmpfi = (foodinfo)levl.foods[i];
407 		//printf("Size levfood: %d \n",levl.foods.size());
408 		Food *tmpfood = new Food("carrot",tmpfi.sx,tmpfi.sy,tmpfi.speed,af);
409 		tmpfood->setLevel(levl, tmpfi.sx, tmpfi.sy);
410 		//printf("Creating new food at: %d %d %d \n",tmpfi.sx,tmpfi.sy,tmpfi.speed);
411 		levelfood.push_back(tmpfood);
412 		pillsleft++;
413 	}
414 };
415 
level_move_food()416 void level_move_food(){
417 	unsigned	int i = 0;
418 	for(i=0; i<levelfood.size(); i++){
419 		Food *tmpfood = (Food*)levelfood[i];
420 		tmpfood->move(xpos,ypos);
421 	}
422 };
423 
level_free_food()424 void level_free_food(){
425 	//printf("Free food...\n");
426 	unsigned int i = 0;
427 
428 	for(i=0; i<levelfood.size(); i++){
429 		Food* tmp = (Food*)levelfood[i];
430 		delete tmp;
431 	}
432 	levelfood.clear();
433 	//printf("Bool lev empty: %d\n",levelfood.empty());
434 };
435 
level_draw_food()436 void level_draw_food(){
437 	unsigned int i = 0;
438 	for(i=0; i<levelfood.size(); i++){
439 		Food* tmp = (Food*)levelfood[i];
440 		if(tmp->alive == true){
441 			blit(tmp->frame(),tmp->x(),tmp->y());
442 		}
443 	}
444 };
445 
446 
447 
check_baddies_pacman()448 Ghost* check_baddies_pacman(){
449 	// Check pacman for collision with ghosts
450 	// Is it possible to enumerate through ghosts?
451 	// Encapsulate ghosts in vector to make iteration easier
452 	// Return true if collision
453 
454 	//printf("Check baddies pacman\n");
455 	if(effect!=INVIS){
456 		Ghost* tmp = NULL;
457 		unsigned int i=0;
458 		for(i=0; i<ghosties.size(); i++){
459 			tmp = (Ghost*)ghosties[i];
460 
461 			if((tmp->x() < xpos+30) && (tmp->x()+30 > xpos) && (tmp->y()+30 > ypos) && (tmp->y() < ypos+30)){
462 				//printf("You hit a ghost!\n");
463 
464 				return tmp;
465 			}
466 		}
467 	}
468 	return NULL;
469 };
470 
drawbaddies()471 void drawbaddies(){
472 	blit(red->frame(),red->x(),red->y());
473 	blit(pink->frame(),pink->x(),pink->y());
474 	//blit(apple->frame(),apple->x(),apple->y());
475 	blit(blue->frame(),blue->x(),blue->y());
476 	//blit(carrot->frame(),carrot->x(),carrot->y());
477 	level_draw_food();
478 };
479 
readMap(string filename)480 void readMap(string filename){
481 	Level levl;
482 	string fname(filename);
483 	string dirname(DATA_INSTALL_DIR);
484 
485 	dirname = dirname + "/" + fname;
486 	levl.pillsleft = 0;
487 	ifstream br(dirname.c_str());
488 	char buffer[SIZEX+1];
489 	// open file, read a line
490 	if(!br.is_open()){
491 		printf("Could not open map file %s!\n",dirname.c_str());
492 	} else {
493 		int x = 0;
494 		int y = 0;
495 
496 		// map needs to be read BEFORE passing to ghosts, or they
497 		// just get NULL and therefore have no way to hit a wall.
498 
499 		for(y=0; y<SIZEY; y++){
500 			br.getline(buffer,SIZEX+1);
501 			for(x=0; x<SIZEX; x++){
502 				levl.map[x][y].type = buffer[x];
503 				if(levl.map[x][y].type == '.') levl.pillsleft++;
504 				levl.map[x][y].t = (y*SIZET) + 50;
505 				levl.map[x][y].b = (y*SIZET) + 50 + 49;
506 				levl.map[x][y].l = (x*SIZET) + 50;
507 				levl.map[x][y].r = (x*SIZET) + 50 + 49;
508 			}
509 		}
510 
511 		char tempx[5]; char tempy[5]; char spd[5];
512 		int tempxi; int tempyi; // bit of geordi there :D
513 		int tempspdi;
514 
515 		// Kill old ghosts and free mem
516 		// before creating new ones
517 
518 		br.getline(buffer, SIZEX+1); // SIZEX+1 just to use all allocated space
519 		//printf("Buffer: %s\n", buffer);
520 		string pinkline(buffer);
521 		sscanf(pinkline.c_str(),"%*s %s %s",tempx,tempy);
522 		tempxi = atoi(tempx);
523 		tempyi = atoi(tempy);
524 		//printf("X: %d Y: %d\n",tempxi,tempyi);
525 		levl.px = tempxi;
526 		levl.py = tempyi;
527 		//pink = new Ghost2("pink",lev, tempxi, tempyi);
528 		//printf("Pink created at %d %d\n", tempxi, tempyi);
529 		//printf("Actual -> %d %d", pink->x(),pink->y());
530 
531 		br.getline(buffer, SIZEX+1);
532 		//printf("Buffer: %s\n", buffer);
533 		string blueline(buffer);
534 		sscanf(blueline.c_str(),"%*s %s %s",tempx,tempy);
535 		tempxi = atoi(tempx);
536 		tempyi = atoi(tempy);
537 		//blue = new Ghost3("blue",lev, tempxi, tempyi);
538 
539 		//printf("X: %d Y: %d\n",tempxi,tempyi);
540 		levl.bx = tempxi;
541 		levl.by = tempyi;
542 
543 		br.getline(buffer, SIZEX+1);
544 		//printf("Buffer: %s\n", buffer);
545 		string redline(buffer);
546 		sscanf(redline.c_str(),"%*s %s %s",tempx,tempy);
547 		tempxi = atoi(tempx);
548 		tempyi = atoi(tempy);
549 		//red = new Ghost1("red", lev, tempxi, tempyi);
550 
551 		//printf("X: %d Y: %d\n",tempxi,tempyi);
552 		levl.rx = tempxi;
553 		levl.ry = tempyi;
554 
555 		// Read file til end. Each line is a food item
556 		//br.getline(buffer, SIZEX+1);
557 		//printf("Food Buffer: %s\n",buffer);
558 		while (br.getline(buffer, SIZEX+1)){
559 			//printf("Food Buffer: %s\n",buffer);
560 			string foodline(buffer);
561 			sscanf(foodline.c_str(),"%*s %s %s %s",tempx,tempy,spd);
562 			tempxi = atoi(tempx);
563 			tempyi = atoi(tempy);
564 			tempspdi = atoi(spd);
565 			foodinfo fd;
566 			fd.sx = tempxi;
567 			fd.sy = tempyi;
568 			//printf("fd.sx %d fd.sy %d\n",fd.sx,fd.sy);
569 			fd.speed = tempspdi;
570 			levl.foods.push_back(fd);
571 			//printf("Size foods %d\n",levl.foods.size());
572 			//br.getline(buffer, SIZEX+1);
573 		}
574 
575 		// kill any old ghosts before creating new ones
576 		br.close();
577 		}
578 		maps.push_back(levl);
579 		//printf("Loaded level\n");
580 };
581 
init(bool fullscreen)582 SDL_Surface* init(bool fullscreen){
583 	SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
584 
585 	if(fullscreen == true){
586 	//printf("Init screen\n");
587 	screen = SDL_SetVideoMode(800, 600, 24,
588 		SDL_HWSURFACE|SDL_ANYFORMAT|SDL_DOUBLEBUF|SDL_FULLSCREEN);
589 	} else {
590 	screen = SDL_SetVideoMode(800, 600, 24,
591 		SDL_HWSURFACE|SDL_ANYFORMAT|SDL_DOUBLEBUF);
592 
593 	}
594 	if( !screen ) {
595 		fprintf(stderr,
596 			"Couldn't create a surface: %s\n", SDL_GetError());
597 		return NULL;
598 
599 	} else {
600 		if(TTF_Init()==-1) {
601 			printf("TTF_Init: %s\n", TTF_GetError());
602     	return NULL;
603 		}
604 
605 		if(Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 2, 1024)==-1) {
606 			printf("Mix_OpenAudio: %s\n", Mix_GetError());
607 			return NULL;
608 		}
609 
610 		SDL_WM_SetCaption("Help Hannah's Horse!!", "Help Hannah's Horse!!");
611 
612 		return screen;
613 	}
614 };
615 
616 
617 
move()618 void move(){
619 
620 	int ax = (xpos / SIZET) - 1;
621 	int ay = (ypos / SIZET) - 1;
622 
623 	if(!checkcollisions() && xpos==nextxpos && ypos==nextypos){
624 		direction = nextdir;
625 			switch(nextdir){
626 					case 1: nextypos = lev.map[ax][ay-1].t; direction=nextdir; break;
627 					case 2: nextypos = lev.map[ax][ay+1].t; direction=nextdir; break;
628 					case 3: nextxpos = lev.map[ax-1][ay].l; direction=nextdir; break;
629 					case 4: nextxpos = lev.map[ax+1][ay].l; direction=nextdir; break;
630 			};
631 	} else if(checkcollisions() && xpos==nextxpos && ypos==nextypos){
632 		if(nextdir==direction){
633 			direction = 5;
634 			nextdir = 5;
635 		} else if(nextdir!=direction && checknext()){
636 			direction = 5;
637 			nextdir=5;
638 		} else {
639 			switch(direction){
640 				case 1: nextypos = lev.map[ax][ay-1].t; break;
641 				case 2: nextypos = lev.map[ax][ay+1].t; break;
642 				case 3: nextxpos = lev.map[ax-1][ay].l; break;
643 				case 4: nextxpos = lev.map[ax+1][ay].l; break;
644       };
645 			direction = direction;
646 		}
647 	}
648 
649 	if(nextxpos!=xpos){
650 		switch(direction){
651 			case 3: xpos = xpos - speed; break;
652 			case 4: xpos = xpos + speed; break;
653 		};
654 	} else if(nextypos!=ypos){
655 		switch(direction){
656 			case 1: ypos = ypos - speed; break;
657 			case 2: ypos = ypos + speed; break;
658 		};
659 	}
660 
661 };
662 
drawBigTextAt(char * text,int x,int y)663 void drawBigTextAt(char* text, int x, int y){
664 	SDL_Surface* textsurface;
665 	SDL_Color color = {0,0,0};
666 	char tt[40];
667 	sprintf(tt, text);
668 	textsurface = TTF_RenderText_Blended(bigfont,tt,color);
669 	blit(textsurface,x,y);
670 	SDL_FreeSurface(textsurface);
671 };
672 
drawTextAt(char * text,int x,int y)673 void drawTextAt(char* text, int x, int y){
674 	SDL_Surface* textsurface;
675 	SDL_Color color = {0,0,0};
676 	char tt[40];
677 	sprintf(tt, text);
678 	textsurface = TTF_RenderText_Blended(subgamefont,tt,color);
679 	blit(textsurface,x,y);
680 	SDL_FreeSurface(textsurface);
681 };
682 
saveHiScores()683 void saveHiScores(){
684 	//printf("Saving Hi Score\n");
685 	//remove(SCORE_DIR "/hiscore.dat");
686 	//ofstream br(SCORE_DIR "/hiscore.dat");
687 	ofstream br;
688 	#ifdef WIN32
689 		remove("hiscore.dat");
690 		br.open("hiscore.dat");
691 	#else
692 		char* scoredir;
693 		scoredir = getenv("USER");
694 		string s(scoredir);
695 		s = "/home/" + s;
696 		s = s + "/.hannah/hiscore.dat";
697 		remove(s.c_str());
698 		cout << "Saving score " << s.c_str() << "\n";
699 		br.open(s.c_str());
700 	#endif
701 
702 	int i;
703 	for(i=0; i<10; i++){
704 		//printf("Saving entry %d\n",i);
705 		char buf[40];
706 		scoreentry tmp;
707 		tmp = (scoreentry)hiscore[i];
708 		sprintf(buf,"%d %s",tmp.score,tmp.name);
709 		//printf("%s\n",buf);
710 		br << buf << "\n";
711 	}
712 	br.flush();
713 	br.close();
714 	//printf("Finished saving scores\n");
715 };
716 
setHiScore(int entryAt)717 void setHiScore(int entryAt){
718 
719 	// One array for each initial
720 	char first[][26] = {{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'},
721 	{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'},
722 	{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}};
723 	int counter = 0;
724 	int c1 = 0;
725 	int c2 = 0;
726 	int c3 = 0;
727 	int current = 0;
728 	bool done = false;
729 	char tt[9] = "aaa     ";
730 	int indx = 250;
731 	int indy = 350;
732 
733 	SDL_Flip(screen);
734 	SDL_Event e;
735 	while(!done){
736 		while(SDL_PollEvent (&e)){
737 			switch(e.key.state){
738 				case SDL_PRESSED:
739 					switch(e.key.keysym.sym){
740 						case SDLK_RETURN: done = true; strcpy(hiscore[entryAt].name,tt); break;
741 						case SDLK_RIGHT:
742 							// Make the current initial equal to where the counter had gotten
743 							//switch(current){
744 							//	case 0: c1 = counter; break;
745 							//	case 1: c2 = counter; break;
746 							//	case 2: c3 = counter; break;
747 						//	};
748 							current++;
749 							if(current == 3) current = 0;
750 							// Make the new initial equal to where the counter left off last time
751 							switch(current){
752 								case 0: counter = c1; break;
753 								case 1: counter = c2; break;
754 								case 2: counter = c3; break;
755 							};
756 						break;
757 						case SDLK_LEFT:
758 					//		switch(current){
759 				//				case 0: c1 = counter; break;
760 			//					case 1: c2 = counter; break;
761 		//						case 2: c3 = counter; break;
762 	//						};
763 							current--;
764 							if(current == -1) current = 2;
765 							switch(current){
766 								case 0: counter = c1; break;
767 								case 1: counter = c2; break;
768 								case 2: counter = c3; break;
769 							};
770 						break;
771 						case SDLK_UP:
772 							counter++;
773 							if(counter>25) counter = 0;
774 							switch(current){
775 								case 0: c1 = counter; break;
776 								case 1: c2 = counter; break;
777 								case 2: c3 = counter; break;
778 							};
779 							//counter++;
780 
781 							//printf("[%c][%c][%c]\n",first[0][c1],first[1][c2],first[2][c3]);
782 						break;
783 						case SDLK_DOWN:
784 							counter--;
785 							if(counter<0) counter = 25;
786 							switch(current){
787 								case 0: c1 = counter; break;
788 								case 1: c2 = counter; break;
789 								case 2: c3 = counter; break;
790 							};
791 							//printf("[%c]\n",first[current][c1]);
792 						break;
793 						default: break;
794 					};
795 					switch(current){
796 						case 0: indx = 250; break;
797 						case 1: indx = 325; break;
798 						case 2: indx = 400; break;
799 					};
800 					sprintf(tt,"%c%c%c",first[0][c1],first[1][c2],first[2][c3]);
801 		//			printf("[%c][%c][%c]\n",first[0][c1],first[1][c2],first[2][c3]);
802 
803 				break;
804 			};
805 
806 		}
807 
808 		blit(border,190,100);
809 		drawTextAt("Enter your initials",210,150);
810 		drawBigTextAt(tt,250,250);
811 		blit(powerpill,indx,indy);
812 		SDL_Flip(screen);
813 	}
814 };
815 
816 /*
817 void getHiScore(){
818 	SDL_Flip(screen);
819 	bool done = false;
820 	SDL_Event e;
821 	char name[40];
822 	int i = 0;
823 	for(i=0; i<40; i++){ name[i]=' ';}
824 	i = 0;
825 	while(!done){
826 		while(SDL_PollEvent(&e)){
827 			switch(e.key.state){
828 				case SDL_PRESSED:
829 					if(e.key.keysym.sym == SDLK_RETURN){
830 						done = true;
831 					} else if(e.key.keysym.sym == SDLK_SPACE){
832 						name[i] = ' ';
833 						i++;
834 						drawTextAt(name, 200,250);
835 						SDL_Flip(screen);
836 					} else{
837 						char *ch;
838 						ch = SDL_GetKeyName(e.key.keysym.sym);
839 						printf(">%s<\n",ch);
840 						name[i] = ch[0];
841 						i++;
842 						drawTextAt(name, 200,250);
843 						SDL_Flip(screen);
844 					}
845 				break;
846 			};
847 		}
848 	}
849 };*/
850 
drawHiScore()851 void drawHiScore(){
852 	// Read hi score in from file
853 	//ifstream br("hiscore.dat");
854 	int i = 0;
855 	int yy = 120;
856 //	char buffer[40];
857 
858 	for(i=0; i<10; i++){
859 	//	br.getline(buffer,40);
860 	//	drawTextAt(buffer,200,yy);
861 	//	yy = yy + 35;
862 		scoreentry tmp = (scoreentry)hiscore[i];
863 		char buf[30];
864 		sprintf(buf,"%d",tmp.score);
865 		drawTextAt(buf,200,yy);
866 		drawTextAt(tmp.name,400,yy);
867 		yy = yy + 35;
868 	}
869 
870 	drawTextAt("Press SPACE",430,480);
871 };
872 
drawCredits()873 void drawCredits(){
874 	drawTextAt("Help Hannah's Horse",200,120);
875 	drawTextAt("(c)2006 Steve Branley",200,170);
876 	drawTextAt("Graphics - Steve Branley",200,220);
877 	drawTextAt("Programming - Steve Branley",200,270);
878 	drawTextAt("Inspiration - Hannah Williams",200,320);
879 	drawTextAt("Encouragement - Zoe Cunningham",200,370);
880 	drawTextAt("This game is released under",200,420);
881 	drawTextAt("the terms of the GPL v2",200,470);
882 };
883 
drawsubgamestate(int subgamestate)884 void drawsubgamestate(int subgamestate){
885 	// 1 = "Level 1 - Get Ready!", 2 = "Get Ready!", 3 = "Game Over!"
886 	// Display "Level 1" / "Game Over!" / "Get Ready!"
887 	SDL_Surface* textsurface;
888 	SDL_Color color = {0,0,0};
889 	char tt[100];
890 	switch(subgamestate){
891 		case 1: sprintf(tt, "Level %d - Get Ready!", level); break;
892 		case 2: sprintf(tt, "Get Ready!"); break;
893 		case 3: sprintf(tt, "Game Over!"); break;
894 	};
895 	//SDL_FreeSurface(textsurface);
896 	textsurface = TTF_RenderText_Blended(subgamefont,tt,color);
897 	switch(subgamestate){
898 		case 1:	blit(textsurface,170,232); break;
899 		case 2:	blit(textsurface,220,232); break;
900 		case 3:	blit(textsurface,220,232); break;
901 	};
902 	SDL_FreeSurface(textsurface);
903 
904 };
905 
initHannah(int x,int y)906 void initHannah(int x, int y){
907 	nextxpos = 50 + (SIZET*x);
908 	nextypos = 50 + (SIZET*y);
909 	ypos = nextypos;
910 	xpos = nextxpos;
911 	direction = 5; // 1, 2, 3, 4, 5 (u,d,l,r,stat)
912 	nextdir = 5;
913 	//speed = 6;
914 };
915 
drawscore()916 void drawscore(){
917 	SDL_Surface* textsurface;
918 	SDL_Color color = {0,0,0};
919 	char tt[40];
920 	sprintf(tt, "%d", score);
921 	textsurface = TTF_RenderText_Blended(font,tt,color);
922 	blit(textsurface,610,260);
923 	SDL_FreeSurface(textsurface);
924 
925 	sprintf(tt, "Level %d", level);
926 	textsurface = TTF_RenderText_Blended(font,tt,color);
927 	blit(textsurface,610,350);
928 	SDL_FreeSurface(textsurface);
929 
930 	sprintf(tt, "Lives %d", lives);
931 	textsurface = TTF_RenderText_Blended(font,tt,color);
932 	blit(textsurface,610,440);
933 
934 	SDL_FreeSurface(textsurface);
935 };
936 
initLevel(int levelnum)937 void initLevel(int levelnum){
938 	if(levelnum < 4){
939 		current_grass = grass;
940 		current_hedge = hedge;
941 	} else if(levelnum < 7){
942 		current_grass = grass2;
943 		current_hedge = hedge2;
944 	} else if(levelnum < 10){
945 		current_grass = grass3;
946 		current_hedge = hedge3;
947 	} else if(levelnum < 13){
948 		current_grass = grass4;
949 		current_hedge = hedge4;
950 	} else {
951 		current_grass = grass;
952 		current_hedge = hedge;
953 	}
954 	//printf("init level\n");
955 	// Remove any existing ghosts
956 	// before creating new ones for new level
957 	ghosties.clear();
958 	if(the_bonus!=NULL){
959 		delete the_bonus;
960 		the_bonus = NULL;
961 	}
962 
963 	subgamestate = 1;
964 	setTimer(0,NONE);
965 //	if(red != NULL) delete(red);
966 //	if(blue !=NULL) delete(blue);
967 //	if(pink !=NULL) delete(pink);
968 	//if(carrot !=NULL) free(carrot);
969 	lev = (Level)maps.at(levelnum-1);
970 	// Number of food is correct here.
971 	//printf("Just before INIT; Level food size: %d \n",lev.foods.size());
972 //	red = new Ghost1("red", lev, lev.rx, lev.ry, 5);
973 	red->setLevel(lev, lev.rx, lev.ry);
974 	red->x(lev.rx);
975 	red->y(lev.ry);
976 	red->setAnimation("default");
977 	red->timer(0);
978 	//red->x(lev.rx); red->y(lev.ry);
979 //	pink = new Ghost2("pink", lev, lev.px, lev.py, 5);
980 	pink->setLevel(lev, lev.px, lev.py);
981 	pink->x(lev.px);
982 	pink->y(lev.py);
983 	pink->setAnimation("default");
984 	pink->timer(0);
985 //	blue = new Ghost3("blue", lev, lev.bx, lev.by, 5);
986 	blue->setLevel(lev, lev.bx, lev.by);
987 	blue->x(lev.bx);
988 	blue->y(lev.by);
989 	blue->setAnimation("default");
990 	blue->timer(0);
991 
992 	//if(levelfood.size()!=0){
993 	//	level_free_food();
994 	//}
995 
996 	//printf("rx %d px %d bx %d\n",lev.rx,lev.px,lev.bx);
997 	pillsleft = lev.pillsleft;
998 	level_init_food(lev);
999 
1000 	ghosties.push_back(red);
1001 	ghosties.push_back(pink);
1002 	ghosties.push_back(blue);
1003 
1004 	initHannah(7,7);
1005 
1006 	//blit(bg2,550,50);
1007 	//drawMap();
1008 	//drawscore();
1009 	//drawsubgamestate(subgamestate);
1010 	//SDL_Flip(screen);
1011 
1012 	//SDL_Delay(2000);
1013 };
1014 
check_food_pacman()1015 bool check_food_pacman(){
1016 	// Check pacman for collision with ghosts
1017 	// Is it possible to enumerate through ghosts?
1018 	// Encapsulate ghosts in vector to make iteration easier
1019 	// Return true if collision
1020 
1021 	unsigned int i=0;
1022 	for(i=0; i<levelfood.size(); i++){
1023 		Food* tmp = (Food*)levelfood[i];
1024 		if((tmp->x() < xpos+30) && (tmp->x()+30 > xpos) && (tmp->y()+30 > ypos) && (tmp->y() < ypos+30) && tmp->alive==true){
1025 			//printf("You hit a carrot!\n");
1026 			Mix_PlayChannel(-1,eatfood,0);
1027 			tmp->alive = false;
1028 			score = score + 50;
1029 			pillsleft--;
1030 			if(pillsleft==0){
1031 				// set subgamestate to "Well Done!"
1032 				// set level to level +1
1033 				level++;
1034 				subgamestate = 1;
1035 				// Free the foods from the last level
1036 				// Only needed once for checkpillscollision and check_foods_pacman
1037 				//level_free_food();
1038 				initLevel(level);
1039 				initHannah(7,7);
1040 			}
1041 			return true;
1042 		}
1043 	}
1044 	return false;
1045 };
1046 
reInitLevel()1047 void reInitLevel(){
1048 	// put ghosts and pacman back to start
1049 	// after dying
1050 	red->x(lev.rx);
1051 	red->y(lev.ry);
1052 	red->setRespawn(0);
1053 	blue->x(lev.bx);
1054 	blue->y(lev.by);
1055 	blue->setRespawn(0);
1056 	pink->x(lev.px);
1057 	pink->y(lev.py);
1058 	pink->setRespawn(0);
1059 
1060 	red->setAnimation("default");
1061 	pink->setAnimation("default");
1062 	blue->setAnimation("default");
1063 	red->timer(0);
1064 	blue->timer(0);
1065 	pink->timer(0);
1066 
1067 	// Write "Get Ready!"
1068 	blit(bg2,550,0);
1069 	// Put Hannah back in the middle
1070 	initHannah(7,7);
1071 
1072 	setTimer(0,NONE);
1073 
1074 	drawMap();
1075 	move();
1076 	red->move(xpos,ypos);
1077 	blue->move(xpos,ypos);
1078 	pink->move(xpos,ypos);
1079 	drawbaddies();
1080 
1081 	drawsubgamestate(2);
1082 	hannah->respawn();
1083 
1084 	blit(hannah->frame(),xpos,ypos);
1085 	if(the_bonus!=NULL){
1086 		delete the_bonus;
1087 		the_bonus = NULL;
1088 	}
1089 
1090 	SDL_Flip(screen);
1091 	//SDL_Delay(2000);
1092 };
1093 
openRedDoor()1094 void openRedDoor(){
1095 	int ax = 0;
1096 	int ay = 0;
1097 	for(ax=0; ax<SIZEX; ax++){
1098 		for(ay=0; ay<SIZEY; ay++){
1099 			if(lev.map[ax][ay].type=='$')
1100 				lev.map[ax][ay].type='_';
1101 		}
1102 	}
1103 };
1104 
1105 
endGame()1106 void endGame(){
1107 	int bx = 150;
1108 	int by = -500;
1109 	int wx = 150;
1110 	int wy = 650;
1111 	bool bend = false;
1112 	bool wend = false;
1113 	bool end = false;
1114 	SDL_Event e;
1115 	// While banner and text are not in the right places
1116 	while(!bend || !wend){
1117 		if(by<100){
1118 			by = by + 5;
1119 		} else {
1120 			bend = true;
1121 		}
1122 		if(wy>100){
1123 			wy = wy - 5;
1124 		} else {
1125 			wend = true;
1126 		}
1127 		blit(gradient,0,0);
1128 		blit(banner,bx,by);
1129 		blit(words,wx,wy);
1130 		SDL_Flip(screen);
1131 	}
1132 	while(!end){
1133 		while(SDL_PollEvent(&e)){
1134 			if(e.key.state == SDL_PRESSED) end = true;
1135 		}
1136 	}
1137 	subgamestate = 3;
1138 };
1139 
1140 
checkpillcollision()1141 void checkpillcollision(){
1142 	//printf("Checking pill collision\n");
1143 	int ax = (xpos / SIZET) - 1;
1144 	int ay = (ypos / SIZET) - 1;
1145 
1146 	if(lev.map[ax][ay].type=='.'){
1147 		lev.map[ax][ay].type='_';
1148 		score = score + 10;
1149 		Mix_PlayChannel(-1,eatpill,0);
1150 		pillsleft--;
1151 		// check for end of level
1152 		if(pillsleft==0){
1153 			// set subgamestate to "Well Done!"
1154 			// set level to level +1
1155 			level++;
1156 			level_free_food();
1157 			if(level>maps.size()){
1158 				// Game is over, get highscore
1159 				endGame();
1160 			} else {
1161 
1162 				subgamestate = 1;
1163 				// Free the foods from the last level
1164 				//level_free_food();
1165 				//freeBonus();
1166 				initLevel(level);
1167 				initHannah(7,7);
1168 			}
1169 		}
1170 	} else if(lev.map[ax][ay].type=='p'){
1171 		lev.map[ax][ay].type='_';
1172 		score = score + 100;
1173 		Mix_PlayChannel(-1,eatmagic,0);
1174 		red->timer(pilltime);
1175 		blue->timer(pilltime);
1176 		pink->timer(pilltime);
1177 	//	red->effect = 'f';
1178 	//	blue->effect = 'f';
1179 	//	pink->effect = 'f';
1180 		red->setAnimation("flash");
1181 		blue->setAnimation("flash");
1182 		pink->setAnimation("flash");
1183 	} else if(lev.map[ax][ay].type=='r'){
1184 		lev.map[ax][ay].type='_';
1185 		openRedDoor();
1186 	}
1187 
1188 };
1189 
loadSprites()1190 int loadSprites(){
1191 	#ifdef WIN32
1192 	hedge = IMG_Load("images\\hedge.png");
1193 	hedge2 = IMG_Load("images\\hedge2.png");
1194 	hedge3 = IMG_Load("images\\hedge3.png");
1195 	hedge4 = IMG_Load("images\\hedge4.png");
1196 
1197 	pill = IMG_Load("images\\pill.png");
1198 	powerpill = IMG_Load("images\\powerpill.png");
1199 	grass = IMG_Load("images\\grass.png");
1200 	grass2 = IMG_Load("images\\grass2.png");
1201 	grass3 = IMG_Load("images\\grass3.png");
1202 	grass4 = IMG_Load("images\\grass4.png");
1203 
1204 	bg = IMG_Load("images\\bg_left.png");
1205 	bg2 = IMG_Load("images\\bg_right2_1.png");
1206 	story = IMG_Load("images\\story.png");
1207 	gate = IMG_Load("images\\gate.png");
1208 	oneway = IMG_Load("images\\oneway.png");
1209 	howto = IMG_Load("images\\howtoplay.png");
1210 	border = IMG_Load("images\\border.png");
1211 	cross = IMG_Load("images\\cross.png");
1212 	red_door = IMG_Load("images\\red_door.png");
1213 	red_key = IMG_Load("images\\red_key.png");
1214 
1215 	#else
1216 	hedge = IMG_Load(DATA_INSTALL_DIR "/images/hedge.png");
1217 	if(!hedge) return 0;
1218 	hedge = SDL_DisplayFormat(hedge);
1219 
1220 	hedge2 = SDL_DisplayFormat(IMG_Load(DATA_INSTALL_DIR "/images/hedge2.png"));
1221 	hedge3 = SDL_DisplayFormat(IMG_Load(DATA_INSTALL_DIR "/images/hedge3.png"));
1222 	hedge4 = SDL_DisplayFormat(IMG_Load(DATA_INSTALL_DIR "/images/hedge4.png"));
1223 
1224 	pill = SDL_DisplayFormatAlpha(IMG_Load(DATA_INSTALL_DIR "/images/pill.png"));
1225 	powerpill = SDL_DisplayFormatAlpha(IMG_Load(DATA_INSTALL_DIR "/images/powerpill.png"));
1226 	grass = SDL_DisplayFormat(IMG_Load(DATA_INSTALL_DIR "/images/grass.png"));
1227 	grass2 = SDL_DisplayFormat(IMG_Load(DATA_INSTALL_DIR "/images/grass2.png"));
1228 	grass3 = SDL_DisplayFormat(IMG_Load(DATA_INSTALL_DIR "/images/grass3.png"));
1229 	grass4 = SDL_DisplayFormat(IMG_Load(DATA_INSTALL_DIR "/images/grass4.png"));
1230 
1231 	bg = IMG_Load(DATA_INSTALL_DIR "/images/bg_left.png");
1232 	bg2 = SDL_DisplayFormat(IMG_Load(DATA_INSTALL_DIR "/images/bg_right2_1.png"));
1233 	story = IMG_Load(DATA_INSTALL_DIR "/images/story.png");
1234 	gate = SDL_DisplayFormatAlpha(IMG_Load(DATA_INSTALL_DIR "/images/gate.png"));
1235 	oneway = SDL_DisplayFormatAlpha(IMG_Load(DATA_INSTALL_DIR "/images/oneway.png"));
1236 	howto = IMG_Load(DATA_INSTALL_DIR "/images/howtoplay.png");
1237 	border = IMG_Load(DATA_INSTALL_DIR "/images/border.png");
1238 	cross = SDL_DisplayFormatAlpha(IMG_Load(DATA_INSTALL_DIR "/images/cross.png"));
1239 	red_door = SDL_DisplayFormatAlpha(IMG_Load(DATA_INSTALL_DIR "/images/red_door.png"));
1240 	red_key = SDL_DisplayFormatAlpha(IMG_Load(DATA_INSTALL_DIR "/images/red_key.png"));
1241 	gradient = IMG_Load(DATA_INSTALL_DIR "/images/gradient.png");
1242 	banner = IMG_Load(DATA_INSTALL_DIR "/images/end_banner.png");
1243 	words = IMG_Load(DATA_INSTALL_DIR "/images/congrats.png");
1244 
1245 	//printf("%s /images/red_key.png\n",DATA_INSTALL_DIR);
1246 	#endif
1247 
1248 	if(grass!=NULL && pill!=NULL
1249 	&& powerpill!=NULL && hedge!=NULL
1250 	&& bg!=NULL){
1251 		SDL_SetColorKey(pill, SDL_SRCCOLORKEY,
1252 			SDL_MapRGB(pill->format, 0x00, 0xFF, 0xFF));
1253 
1254 		SDL_SetColorKey(story, SDL_SRCCOLORKEY,
1255 			SDL_MapRGB(story->format,0x00,0xFF,0xFF));
1256 
1257 		SDL_SetColorKey(powerpill, SDL_SRCCOLORKEY,
1258 			SDL_MapRGB(powerpill->format,0x00,0xFF,0xFF));
1259 
1260 		SDL_SetColorKey(gate, SDL_SRCCOLORKEY,
1261 			SDL_MapRGB(gate->format,0x00,0xFF,0xFF));
1262 
1263 
1264 		return 1;
1265 	} else {
1266 		return 0;
1267 	}
1268 
1269 };
1270 
loadsounds()1271 void loadsounds(){
1272 	#ifdef WIN32
1273 	eatpill = Mix_LoadWAV("sounds\\DripC.wav");
1274 	eatmagic = Mix_LoadWAV("sound\\/gulp.wav");
1275 	eatfood = Mix_LoadWAV("sounds\\crunch.wav");
1276 	scream = Mix_LoadWAV("sounds\\scream.wav");
1277 	chomp = Mix_LoadWAV("sounds\\chomp.wav");
1278 	uhoh = Mix_LoadWAV("sounds\\uh-oh.wav");
1279 	yeah = Mix_LoadWAV("sounds\\yeah.wav");
1280 
1281 	#else
1282 	eatpill = Mix_LoadWAV(DATA_INSTALL_DIR "/sounds/DripC.wav");
1283 	eatmagic = Mix_LoadWAV(DATA_INSTALL_DIR "/sounds/gulp.wav");
1284 	eatfood = Mix_LoadWAV(DATA_INSTALL_DIR "/sounds/crunch.wav");
1285 	scream = Mix_LoadWAV(DATA_INSTALL_DIR "/sounds/scream.wav");
1286 	chomp = Mix_LoadWAV(DATA_INSTALL_DIR "/sounds/chomp.wav");
1287 	uhoh = Mix_LoadWAV(DATA_INSTALL_DIR "/sounds/uh-oh.wav");
1288 	yeah = Mix_LoadWAV(DATA_INSTALL_DIR "/sounds/yeah.wav");
1289 	#endif
1290 
1291 	printf("Loaded sounds\n");
1292 };
1293 
cleanUp()1294 void cleanUp(){
1295 
1296 	printf("Cleaning up...\n");
1297 
1298 	SDL_FreeSurface(hedge);
1299 	SDL_FreeSurface(hedge2);
1300 	SDL_FreeSurface(hedge3);
1301 	SDL_FreeSurface(hedge4);
1302 	SDL_FreeSurface(pill);
1303 	SDL_FreeSurface(powerpill);
1304 	SDL_FreeSurface(grass);
1305 	SDL_FreeSurface(grass2);
1306 	SDL_FreeSurface(grass3);
1307 	SDL_FreeSurface(grass4);
1308 	SDL_FreeSurface(bg);
1309 	SDL_FreeSurface(bg2);
1310 	SDL_FreeSurface(gate);
1311 	SDL_FreeSurface(oneway);
1312 	SDL_FreeSurface(howto);
1313 	SDL_FreeSurface(story);
1314 	SDL_FreeSurface(border);
1315 	SDL_FreeSurface(cross);
1316 	SDL_FreeSurface(red_key);
1317 	SDL_FreeSurface(red_door);
1318 	SDL_FreeSurface(gradient);
1319 	SDL_FreeSurface(banner);
1320 	SDL_FreeSurface(words);
1321 
1322 	TTF_CloseFont(font);
1323 	TTF_CloseFont(subgamefont);
1324 	TTF_CloseFont(bigfont);
1325 
1326 	Mix_HaltChannel(-1);
1327 	Mix_FreeChunk(eatpill);
1328 	Mix_FreeMusic(bgm1);
1329 	Mix_FreeChunk(eatmagic);
1330 	Mix_FreeChunk(eatfood);
1331 	Mix_FreeChunk(scream);
1332 	Mix_FreeChunk(chomp);
1333 	Mix_FreeChunk(yeah);
1334 	Mix_FreeChunk(uhoh);
1335 
1336 	if(the_bonus!=NULL){ delete the_bonus; the_bonus = NULL;}
1337 
1338 	delete(hannah);
1339 	delete(red);
1340 	delete(pink);
1341 	delete(blue);
1342 	//level_free_food();
1343 	//
1344 	delete(af);
1345 
1346 	Mix_CloseAudio();
1347 	TTF_Quit();
1348 	SDL_Quit();
1349 };
1350 
initGame()1351 void initGame(){
1352 
1353 	font=TTF_OpenFont(DATA_INSTALL_DIR "/font.ttf", 36);
1354 	bigfont=TTF_OpenFont(DATA_INSTALL_DIR "/subgamefont.ttf",108);
1355 	bgm1 = Mix_LoadMUS(DATA_INSTALL_DIR "/bgm1.ogg");
1356 
1357 	if(!bgm1) printf("Mix_LoadMUS(\"bgm1.mp3\"): %s\n", Mix_GetError());
1358 
1359 	subgamefont=TTF_OpenFont(DATA_INSTALL_DIR "/subgamefont.ttf", 24);
1360 	if(!font || !subgamefont) printf("Unable to load font! %s \n", TTF_GetError());
1361 
1362 	#ifdef WIN32
1363 	readMap("maps\\map1.dat");
1364 	readMap("maps\\map2.dat");
1365 	readMap("maps\\map3.dat");
1366 	readMap("maps\\map4.dat");
1367 	readMap("maps\\map5.dat");
1368 	readMap("maps\\map6.dat");
1369 	readMap("maps\\map7.dat");
1370 	readMap("maps\\map8.dat");
1371 	readMap("maps\\map9.dat");
1372 	readMap("maps\\map10.dat");
1373 	readMap("maps\\map11.dat");
1374 	readMap("maps\\map12.dat");
1375 	readMap("maps\\map13.dat");
1376 	readMap("maps\\map14.dat");
1377 	readMap("maps\\map15.dat");
1378 
1379 	#else
1380 	readMap("/maps/map1.dat");
1381 	readMap("/maps/map2.dat");
1382 	readMap("/maps/map3.dat");
1383 	readMap("/maps/map4.dat");
1384 	readMap("/maps/map5.dat");
1385 	readMap("/maps/map6.dat");
1386 	readMap("/maps/map7.dat");
1387 	readMap("/maps/map8.dat");
1388 	readMap("/maps/map9.dat");
1389 	readMap("/maps/map10.dat");
1390 	readMap("/maps/map11.dat");
1391 	readMap("/maps/map12.dat");
1392 	readMap("/maps/map13.dat");
1393 	readMap("/maps/map14.dat");
1394 	readMap("/maps/map15.dat");
1395 
1396 	printf("Loaded maps\n");
1397 
1398 	#endif
1399 
1400 	// Load extra anims for sprites
1401 	//hannah->loadAnimation("die", false);
1402 	af->loadAnimation("hannah","die",false,"hannah-die");
1403 	af->loadAnimation("hannah","default",true,"hannah-default");
1404 	af->loadAnimation("hannah","invis",true,"hannah-invis");
1405 
1406 
1407 	af->loadAnimation("red","default",true,"red-default");
1408 	af->loadAnimation("pink","default",true,"pink-default");
1409 	af->loadAnimation("blue","default",true,"blue-default");
1410 
1411 	//red->loadAnimation("flash",true);
1412 	//pink->loadAnimation("flash",true);
1413 	//blue->loadAnimation("flash",true);
1414 	af->loadAnimation("red","flash",true,"red-flash");
1415 	af->loadAnimation("pink","flash",true,"pink-flash");
1416 	af->loadAnimation("blue","flash",true,"blue-flash");
1417 
1418 	af->loadAnimation("carrot","default",true,"carrot-default");
1419 
1420 	af->loadAnimation("freeze","default",true,"freeze-default");
1421 	af->loadAnimation("invis","default",true,"invis-default");
1422 	af->loadAnimation("invert","default",true,"invert-default");
1423 
1424 	red = new Ghost1("red",0,0,5,af);
1425 	pink = new Ghost2("pink",0,0,5,af);
1426 	blue = new Ghost3("blue",0,0,5,af);
1427 
1428 	hannah = new Player("hannah",af);
1429 
1430 	//af->list();
1431 };
1432 
1433 
1434 
main(int argc,char ** argv)1435 int main(int argc, char **argv){
1436 
1437 	//printf("Started main method\n");
1438 
1439 	//Level lev;
1440 
1441 	//mtrace();
1442 	level = 1;
1443 
1444 	//printf("%d arguments passed\n",argc);
1445 	bool fullscreen = false;
1446 	bool music = true;
1447 
1448 	if(argc > 1){
1449 	//	level = atoi(argv[1]);
1450 		//printf("%d Arguments given\n",argc);
1451 		int a;
1452 		for(a=0; a<argc; a++){
1453 			//printf("Args: %s\n",argv[a]);
1454 			if(strcmp(argv[a],"-fullscreen") == 0){
1455 				//printf("FULLSCREEN\n");
1456 				fullscreen = true;
1457 			} else if(strcmp(argv[a],"-nomusic") == 0){
1458 				// Turn off music
1459 				music = false;
1460 			} else if(strcmp(argv[a],"-map") == 0){
1461 				level = atoi(argv[a+1]);
1462 				//printf("Level: %d\n",level);
1463 			} else if(strcmp(argv[a],"-lives") == 0){
1464 				//numlives = atoi(argv[a+1]);
1465 				if(a+1 >= argc){
1466 					printf("The -lives parameter requires a number!\n");
1467 					exit(1);
1468 				} else {
1469 					numlives = strtol(argv[a+1],NULL,10);
1470 					if(numlives == 0){
1471 						printf("The -lives parameter requires a number!\n");
1472 						exit(1);
1473 					} else {
1474 						printf("Lives: %d\n",numlives);
1475 						lives = numlives;
1476 					}
1477 				}
1478 			}
1479 		}
1480 	}
1481 
1482 	screen = init(fullscreen);
1483 
1484 	int ok = loadSprites();
1485 	if(ok == 0){
1486 		cout << "\n\nThis game needs to be installed - run \"make install\" as root.\nI will fix this in later version to allow play from current directory.\n\n";
1487 	}
1488 	score = 0;
1489 
1490 	//TTF_Init();
1491 	if(ok!=0) initGame();
1492 	srand(time(0));
1493 
1494 	if(screen!=NULL && ok>0){
1495 		// Screen was assigned and sprites loaded so carry on
1496 
1497 		SDL_Event e;
1498 		int exit = 0;
1499 
1500 		blit(bg,0,0);
1501 		blit(bg2,550,0);
1502 
1503 		subgamestate = 1; // used for displaying "Get Ready" etc at start of level
1504 
1505 		loadsounds();
1506 		loadHiScores();
1507 		if(music == true)
1508 		Mix_PlayMusic(bgm1, -1);
1509 
1510 		//printf("Successfully loaded ghosts\n");
1511 
1512 		int gamestate = 0; // 0 = intro, 1 = game, 2 = hiscore, 3 = howtoplay
1513 
1514 	//	initLevel(level);
1515 
1516 		while(!exit){
1517 			// test keys
1518 
1519 			// Some speed control
1520 			tick = SDL_GetTicks();
1521 			delta_tick = tick - lastticks;
1522 			lastticks = tick;
1523 
1524 			//limit to 40 revolutions per second (40*25ms = 1 second)
1525 			if(delta_tick < 32){
1526 				SDL_Delay(32 - delta_tick);
1527 				tick = SDL_GetTicks();
1528 				delta_tick = delta_tick + tick - lastticks;
1529 				lastticks = tick;
1530 			}
1531 
1532 
1533 //			int ax = (xpos / SIZET) - 1;
1534 //			int ay = (ypos / SIZET) - 1;
1535 
1536 				while(SDL_PollEvent(&e)){
1537 					switch(e.type){
1538 						case SDL_QUIT: exit = 1; break;
1539 					}
1540 					switch(e.key.state){
1541 						case SDL_PRESSED:
1542 							if(e.key.keysym.sym==SDLK_RIGHT){	if(effect==INVERT) nextdir = 3; else nextdir = 4;		}
1543 							if(e.key.keysym.sym==SDLK_LEFT){		if(effect==INVERT) nextdir = 4; else nextdir = 3;		}
1544 							if(e.key.keysym.sym==SDLK_UP){		nextdir = 1;		}
1545 							if(e.key.keysym.sym==SDLK_DOWN){		nextdir = 2;		}
1546 							if(e.key.keysym.sym==SDLK_h){
1547 								if(gamestate==0){
1548 									gamestate=3;
1549 								}
1550 							}
1551 							if(e.key.keysym.sym==SDLK_s){
1552 								if(gamestate==0){
1553 									gamestate=4; // show hiscore
1554 								}
1555 							}
1556 							if(e.key.keysym.sym==SDLK_p){
1557 								if(gamestate==1 && subgamestate==0){
1558 									subgamestate=4;
1559 								} else if(gamestate==1 && subgamestate==4){
1560 									subgamestate=0;
1561 								}
1562 							}
1563 							if(e.key.keysym.sym==SDLK_c){
1564 								if(gamestate==0) gamestate = 5;
1565 							}
1566 							if(e.key.keysym.sym==SDLK_m){
1567 								if(Mix_PlayingMusic()){
1568 									Mix_HaltMusic();
1569 								} else {
1570 									Mix_PlayMusic(bgm1,-1);
1571 								}
1572 							}
1573 
1574 							if(e.key.keysym.sym==SDLK_ESCAPE){
1575 								if(gamestate==0){
1576 									// Quit game
1577 									//level_free_food();
1578 									saveHiScores();
1579 									exit=1;
1580 								} else {
1581 									// Game is running - return to main screen
1582 									// Reset the whole game (maybe need a method for this?)
1583 									level_free_food();
1584 									//freeBonus();
1585 									gamestate=0;
1586 									level = 1;
1587 								}
1588 							}
1589 							if(e.key.keysym.sym==SDLK_SPACE){
1590 								if(gamestate==0){
1591 									lives = numlives;
1592 									score = 0;
1593 									hannah->setAnimation("default");
1594 									gamestate = 1;
1595 									blit(bg,0,0);
1596 									initLevel(level);
1597 								} else if(gamestate==3 || gamestate==4 || gamestate==5){
1598 									gamestate=0;
1599 									level = 1;
1600 								}
1601 
1602 							}
1603 							break;
1604 					}
1605 				}
1606 
1607 
1608 				// game logic
1609 				if(gamestate==0){
1610 					//blit(bg,0,0);
1611 					blit(story,0,0);
1612 					SDL_Flip(screen);
1613 
1614 				} else if(gamestate==1){
1615 					// Draw bg and map, all bits need this
1616 					blit(bg2,550,0);
1617 					drawMap();
1618 					drawscore();
1619 					// Game is running
1620 					if(subgamestate==0){
1621 						timer();
1622 						checkpillcollision();
1623 						move();
1624 						drawbaddies();
1625 						createBonus();
1626 
1627 						// BUG: if move not called (i.e. effect=='s') then timer never decreases.
1628 						if(effect==FREEZE){
1629 						//	if(red->effect != 's')
1630 						//	red->move(xpos,ypos);
1631 						//	else red->decTimer();
1632 						} else red->move(xpos,ypos);
1633 						if(effect==FREEZE){
1634 						//	if(pink->effect != 's')
1635 						//	pink->move(xpos,ypos);
1636 						//	else pink->decTimer();
1637 						} else pink->move(xpos,ypos);
1638 						if(effect==FREEZE){
1639 						//	if(blue->effect != 's')
1640 						//	blue->move(xpos,ypos);
1641 						//	else blue->decTimer();
1642 						} else blue->move(xpos,ypos);
1643 						level_move_food();
1644 						moveBonus();
1645 						//SDL_Delay(20);
1646 						//SDL_Flip(screen);
1647 						check_bonus_pacman();
1648 						Ghost* tmpghost = check_baddies_pacman();
1649 						if(tmpghost!=NULL && tmpghost->timer()==0 && hannah->isAnimation("default")){
1650 							//printf("Red timer: %d\n",red->timer());
1651 
1652 							Mix_PlayChannel(-1,scream,0);
1653 							hannah->setAnimation("die");
1654 
1655 
1656 							//hannah->setAnimation("die");
1657 							//if(hannah->animationFinished()){
1658 
1659 							//}
1660 						//} else if(){
1661 
1662 						} else if(tmpghost!=NULL && tmpghost->timer()>0){
1663 							//printf("Red timer: %d\n",tmpghost->timer());
1664 							// Powerpill is active, eat ghost
1665 							tmpghost->timer(0);
1666 							tmpghost->setAnimation("default");
1667 							tmpghost->setRespawn(50);
1668 							tmpghost->x(tmpghost->startx);
1669 							tmpghost->y(tmpghost->starty);
1670 							Mix_PlayChannel(-1,chomp,0);
1671 							score = score + 400;
1672 							//SDL_Delay(300);
1673 							//red->x(lev.rx);
1674 							//red->y(lev.ry);
1675 						}
1676 
1677 						unsigned int gn = 0;
1678 						for(gn=0; gn<ghosties.size(); gn++){
1679 							tmpghost = (Ghost*)ghosties[gn];
1680 							if(tmpghost->timer() == 0 && tmpghost->isAnimation("flash")){
1681 								tmpghost->setAnimation("default");
1682 							}
1683 						}
1684 
1685 						if(hannah->isAnimation("die") && hannah->animationFinished()){
1686 
1687 							lives--;
1688 							if(lives == 0){
1689 								level_free_food();
1690 								//freeBonus();
1691 								subgamestate = 3;
1692 							} else {
1693 								reInitLevel();
1694 								subgamestate = 2;
1695 							}
1696 							//hannah->respawn();
1697 						}
1698 
1699 						check_food_pacman();
1700 					//	SDL_Flip(screen);
1701 						SDL_UpdateRect(screen,50,50,450,450);
1702 						SDL_UpdateRect(screen,610,260,150,150);
1703 					// Game is saying "Level N - Get ready"
1704 					} else if(subgamestate==1){
1705 						drawbaddies();
1706 						drawscore();
1707 						drawsubgamestate(1);
1708 						SDL_Flip(screen);
1709 						SDL_Delay(2000);
1710 						subgamestate = 0;
1711 					// Game is saying "Get Ready!" after dying
1712 					} else if (subgamestate==2){
1713 						drawbaddies();
1714 						drawscore();
1715 						drawsubgamestate(2);
1716 						//SDL_Delay(2000);
1717 						SDL_Flip(screen);
1718 						SDL_Delay(2000);
1719 						subgamestate = 0;
1720 					// Game is saying "Game Over"
1721 					} else if (subgamestate==3){
1722 						drawscore();
1723 						drawsubgamestate(subgamestate);
1724 						gamestate = 0;
1725 						//SDL_Delay(2000);
1726 						SDL_Flip(screen);
1727 						SDL_Delay(2000);
1728 
1729 						// check for hiscore
1730 						int pos = checkHiScores(score);
1731 						if(pos > -1){
1732 							blit(border,190,100);
1733 							setHiScore(pos);
1734 							SDL_Flip(screen);
1735 							gamestate = 0;
1736 						}
1737 
1738 						lives = numlives;
1739 						score = 0;
1740 						level = 1;
1741 					} else if(subgamestate==4){
1742 						//pause
1743 						drawbaddies();
1744 						drawscore();
1745 						SDL_Flip(screen);
1746 					}
1747 				} else if(gamestate==2){
1748 					// Show hi scores
1749 				} else if(gamestate==3){
1750 					blit(howto,190,100);
1751 					SDL_Flip(screen);
1752 				} else if(gamestate==4){
1753 					blit(border,190,100);
1754 					//getHiScore();
1755 					drawHiScore();
1756 					SDL_Flip(screen);
1757 					//gamestate = 0;
1758 				} else if(gamestate==5){
1759 					blit(border,190,100);
1760 					drawCredits();
1761 					SDL_Flip(screen);
1762 				} else if(gamestate==6){
1763 					endGame();
1764 					gamestate = 0;
1765 				}
1766 				//SDL_Flip(screen);
1767 			}
1768 
1769 			// End of loop reached - cleanup
1770 		cleanUp();
1771 	} else {
1772 		// Quit - do any cleanup
1773 		SDL_Quit();
1774 	}
1775 };
1776 
1777