/********************************************************* * Pacman by Chatzidimitriou Athanasios 050064 * * m3nt4l@in.gr * * * * Instructions: * * -Use the arrows to move arround the stage * * -"q" Quits the game * * -"p" Pauses the game * * -z/x toggles speed (-/+) * * -Each time you hit a wall, you lose a life and return * * to the center * * -On beggining, press any key to start * * -Score depends on Speed(difficulty) * * * * � Feb 2008 * *********************************************************/ #include #include #include #include #include #include /*Global game Variables */ static float speed = 0.2; static int score = 0; /*For the renderBitmapString and a buffer string to print */ int font=(int)GLUT_BITMAP_8_BY_13; char str[30]; #include "pacman.h" #include "dots.h" /*Coordinates of the Dots to create the grid */ float coors[]={ -400.,-400.,-400.,-300.,-400.,-200.,-400.,-100.,-400.,-0.,-400.,100.,-400.,200.,-400.,300.,-400.,400., -300.,-400.,-300.,-300.,-300.,-200.,-300.,-100.,-300.,-0.,-300.,100.,-300.,200.,-300.,300.,-300.,400., -200.,-400.,-200.,-300.,-200.,-200.,-200.,-100.,-200.,-0.,-200.,100.,-200.,200.,-200.,300.,-200.,400., -100.,-400.,-100.,-300.,-100.,-200.,-100.,-100.,-100.,-0.,-100.,100.,-100.,200.,-100.,300.,-100.,400., 0.,-400., 0.,-300., 0.,-200., 0.,-100., 0.,-0., 0.,100., 0.,200., 0.,300., 0.,400., 100.,-400., 100.,-300., 100.,-200., 100.,-100., 100.,-0., 100.,100., 100.,200., 100.,300., 100.,400., 200.,-400., 200.,-300., 200.,-200., 200.,-100., 200.,-0., 200.,100., 200.,200., 200.,300., 200.,400., 300.,-400., 300.,-300., 300.,-200., 300.,-100., 300.,-0., 300.,100., 300.,200., 300.,300., 300.,400., 400.,-400., 400.,-300., 400.,-200., 400.,-100., 400.,-0., 400.,100., 400.,200., 400.,300., 400.,400.,}; /*Global game objects */ static pacman pman; static gridv grid(81,coors); /*Standard functions */ void init(); void display(); void idle(); void reshape(int,int); void keyboard(unsigned char , int, int); void keybspecial(int , int , int ); /*arrows are Special keys */ void renderBitmapString(float, float, void*,char*); /*prints a string */ int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize (400, 400); glutInitWindowPosition (100, 100); glutCreateWindow ("Pacman"); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutSpecialFunc(keybspecial); glutMainLoop(); return 0; } void init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_FLAT); } void display(void) { glClear(GL_COLOR_BUFFER_BIT); /*Score and Lifes Display */ glPushMatrix(); glColor3f(1.0,0.0f,0.0f); sprintf(str,"Lifes: %d",pman.getlif()-1); renderBitmapString(300,-450,(void *)font,str); sprintf(str,"Speed: %.2f",speed); renderBitmapString(-100,-450,(void *)font,str); sprintf(str,"Score: %d",score); renderBitmapString(-450,-450,(void *)font,str); glPopMatrix(); /*Draw dots and pacman*/ grid.draw(); pman.draw(); glutSwapBuffers(); } void idle(void) { /*emulate eating the dots */ for (int i = 0; i < grid.getsize(); i++){/*for every dot */ /*check if pacman touches it */ if (pman.touch(grid.getdot(i)->getx(),grid.getdot(i)->gety())) grid.getdot(i)->eat(); } pman.move(speed); if (grid.clear()) exit(0); /*stage clear */ glutPostRedisplay(); } void reshape(int w, int h) { glViewport (0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-500.0, 500.0, -500.0, 500.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void keyboard(unsigned char key, int x, int y) { glutIdleFunc(idle); switch (key) { case 'Q': case 'q': exit(0);break; case 'P': case 'p': glutIdleFunc(NULL);break; case 'Z': case 'z': if (speed > 0.06) speed-=0.05;break; case 'X': case 'x': if (speed < 2.) speed +=0.05;break; } } void keybspecial(int key, int x, int y) { glutIdleFunc(idle); switch(key) { case GLUT_KEY_UP : pman.setdir(UP) ;break; case GLUT_KEY_DOWN : pman.setdir(DOWN) ;break; case GLUT_KEY_LEFT : pman.setdir(LEFT) ;break; case GLUT_KEY_RIGHT : pman.setdir(RIGHT);break; } } /*Function to print a string (i got it ready from inet) */ void renderBitmapString(float x, float y, void *font,char *string) { glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(-500, 500, -500, 500); glScalef(1, -1, 1); glMatrixMode(GL_MODELVIEW); char *c; glRasterPos2f(x, y); for (c=string; *c != '\0'; c++) glutBitmapCharacter(font, *c); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef PACMAN_H #define PACMAN_H enum dir {UP,DOWN,LEFT,RIGHT}; /*Direction */ class pacman { public: pacman(); pacman(float x,float y); ~pacman(){delete[] posv;} /*drawing & positioning */ void draw(); /*draw pacman */ void chmouth(){mouth = !mouth;}/*open/close mouth */ bool touch(float x, float y);/*chech if is in touch wit point */ /*Moving */ void move(float d); /*move to direction for d distance */ /*general purpose*/ float* getpos()const{return posv;} float getp_x()const{return posv[0];} float getp_y()const{return posv[1];} bool getm() const{return mouth;} int getlif()const{return lifes;} dir getdir()const{return direction;} void setdir(dir d){direction = d;} void setpos(float *v){posv = v;} void setp_x(float x){posv[0] = x;} void setp_y(float y){posv[1] = y;} void setm (bool m){mouth = m;} private: void hit();/*hit on a wall, private method */ float *posv; /*position vector */ float dist; /*distance (to calculate mouth open/close */ bool mouth; dir direction; int lifes; }; pacman::pacman() { posv = new float[2]; posv[0] = 0.0; posv[1] = 0.0; mouth = true; direction = RIGHT; dist = 0.; lifes = 3; } pacman::pacman(float x,float y) { posv = new float[2]; posv[0] = x; posv[1] = y; mouth = true; direction = RIGHT; dist = 0.; lifes = 3; } void pacman::draw() { float angle; float r = 50.,x,y,c; float tmp; /*calculate mouth open, depends on speed */ if (dist > 500.*speed){chmouth();dist = 0.;} if (mouth) tmp = 3.14/6; /*draw from 3.14/6 to 2*3.14 - 3.14/6 */ else tmp = 0; /*full circle */ /*Setting the rotation angle */ switch (direction){ case UP: angle = 90.;break; case DOWN: angle = 270.;break; case LEFT: angle = 180.;break; case RIGHT: angle = 0.;break; } /*drawing the shape */ glPushMatrix(); glTranslatef(posv[0], posv[1], 0.0); glRotatef(angle, 0.0, 0.0, 1.0); glColor3f(1.0, 1.0, 0.0); glBegin(GL_POLYGON); if (mouth) glVertex3f(0.0,0.0,0.0); /*the center point for mouth */ for (c = tmp; c < (2*3.14 - tmp); c += 0.1){ x = r * cos(c); y = r * sin(c); glVertex3f(x,y,0.0); } glEnd(); glPopMatrix(); } /*checks if pacman touches a point (x,y) */ bool pacman::touch(float x, float y) {/*pacman radious is 50, so we calculate +- 50 from position */ bool tx = false, ty = false; if (x > posv[0] - 50. && x < posv[0] + 50.) tx = true; if (y > posv[1] - 50. && y < posv[1] + 50.) ty = true; return (tx && ty); } void pacman::move(float d) { /* Check if touched a border + if not, move*/ if (direction == RIGHT) if (touch(+500.,posv[1])) {hit();return;} else posv[0] += d; if (direction == LEFT) if (touch(-500.,posv[1])) {hit();return;} else posv[0] -= d; if (direction == UP) if (touch(posv[0],+500.)) {hit();return;} else posv[1] += d; if (direction == DOWN) if (touch(posv[0],-500.)) {hit();return;} else posv[1] -= d; dist += d; } /*on a hit, bring to center and freeze till a key pressed */ void pacman::hit() { posv[0] = 0.; posv[1] = 0.; --lifes; mouth = true; glutIdleFunc(NULL); /*on 0 lifes, exit */ if (lifes == 0) exit(0); } #endif //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef DOTS_H #define DOTS_H #include using namespace std; class dot { public: dot(float x, float y); /*coordinates of dot */ ~dot(){delete[] posv;} void draw() const; float* getpos() const{return posv;} float getx() const{return posv[0];} float gety() const{return posv[1];} bool geteaten()const{return eaten;} void eat(){if (!eaten){eaten = true;score+=(int)(40*speed);}} /*changes condition to eaten */ private: float *posv; /*position vector */ bool eaten;/*eaten flag */ }; dot::dot(float x, float y) { posv = new float[2]; posv[0] = x; posv[1] = y; eaten = false; } void dot::draw()const { if (eaten)return; /*nothing to draw.. */ glPushMatrix(); glTranslatef(posv[0], posv[1], 0.0); glColor3f(1.0, 1.0, 0.0); glRectf(-5.0, -5.0, 5.0, 5.0); glPopMatrix(); } /*-----------------------------------------------------------------*/ class gridv /*gridvector */ { public: gridv(int,float *); ~gridv(); void draw(); int getsize()const{return dots->size();} dot* getdot(int i)const{return dots->at(i);} bool clear()const; /*check if stage is clear */ private: vector *dots; /*vector with the dots */ }; /*Size of vector, and pairs of coordinates (x,y) */ gridv::gridv(int s,float *v) { dots = new vector; for (int i = 0; i < s; i++) { dots->push_back(new dot(*v, *(v+1))); v+=2; } } gridv::~gridv() { for (int i = 0; i < dots->size(); i++) delete dots->at(i); delete dots; } void gridv::draw() { for (int i = 0; i < dots->size(); i++) dots->at(i)->draw(); } bool gridv::clear()const { for (int i = 0; i < dots->size(); i++) if (!dots->at(i)->geteaten()) return false; return true; } #endif