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