/* ============================================================================== WordUp Graphics Toolkit Version 5.0 Demonstration Program 59 This is a PACMAN clone which has two player mode. The right player uses the arrow keys, and the left player uses the W, A, S, and D keys. *** PROJECT *** This program requires the files WGT5_WC.LIB and WSCR_WC.LIB to be linked. *** DATA FILES *** PACSPR.SPR, PACTILE.SPR, PACMAN.WMP WATCOM C++ VERSION ============================================================================== */ #include #include #include #include #include #include #include #define LEFT 0 #define RIGHT 1 #define UP 2 #define DOWN 3 #define ESC 1 #define WIN 0 #define WIN2 1 short keys[2][4] = {{30, 32, 17, 31}, {75, 77, 72, 80}}; #define NUM_LOAD 100 #define DIESPEED 40 int frames; /* Number of frames counted */ short spx,spy; /* Speed of scrolling window */ short pacanim, pacdir[2]; /* Controls animation frame and the direction PACMAN is facing */ short ox[2],oy[2]; /* Stores PACMAN's coordinate from previous frame, in case you hit a wall */ wgtmap pacmap; /* our world map */ short dying[2]; /* Counts down after dying. Once it hits 0, PACMAN starts a new life. */ color palette[256]; /* Our palette of colours */ block pactile[NUM_LOAD + 1]; /* Tiles for the map */ block pacspr[NUM_LOAD + 1]; /* Our sprites */ scrollsprite wobject[100]; /* A few objects for you, ghosts, etc */ short tiletypes[256]; /* Tile types */ short pacspeed = 4,ghostspeed = 4; /* Moving speed of you and the ghosts */ short oldmode; /* Previous video mode */ short bonus; /* Tells how many points eating a ghost will give you 0 = 100, 1 = 200, 2 = 400, 3 = 800 */ short traptime[6]; /* Time left until ghost reappears */ short moved[6], movedir[6]; /* Controls movement of ghosts */ short bluetime; /* Time left with blue ghosts */ short i; short score[2]; /* Your score */ short level; /* Current level */ short bonusscore[5] = {100, 200, 400, 800}; /* Bonus points for each ghost */ short total_dots; /* Dots not eaten */ int timer; void checkpos (short); /* checks PACMAN for hitting walls */ void moveghost (short); /* checks ghosts for hitting walls */ short oldmode; void timerctr (void) { timer++; } void set_positions (void) /* Sets the initial positions of the ghosts and pacman */ { short i; wobject[0].on = 1; /* Set Pacman's position */ wobject[0].x = 192; wobject[0].y = 176; wobject[0].num = 1; wobject[1].on = 1; /* Set Pacman's position */ wobject[1].x = 208; wobject[1].y = 176; wobject[1].num = 1; for (i = 2; i < 6; i++) { wobject[i].on = 1; wobject[i].x = 176; /* Set up the ghosts */ wobject[i].y = 112; wobject[i].num = 19 + i; /* Make the ghosts different colors */ } for (i = 2; i < 6; i++) { moved[i] = 16; movedir[i] = 4; } pacanim = 1; } void count_dots(void) { unsigned short *mapptr; int size, i; mapptr = (unsigned short *)pacmap; total_dots = 0; for (i = 0; i < mapwidth[WIN] * mapheight[WIN]; i++) { if ((tiletypes[*mapptr] == 2) || (tiletypes[*mapptr] == 3)) total_dots++; mapptr++; } } void incscore(short player, short amt) /* Increases your score by amt and shows the change on the screen. */ { score[player] += amt; wgtprintf (10 + player * 160, 192, NULL, "%i", score[player]); } void check_dots_left (void) /* Checks how many dots are left. */ { if (total_dots == 0) { nosound (); wfreemap (pacmap); pacmap = wloadmap (WIN, "pacman.wmp", tiletypes, wobject); set_positions (); wshowwindow (WIN, 5, 5); wshowwindow (WIN2, 6, 5); count_dots (); ghostspeed *= 2; if (ghostspeed > 16) ghostspeed = 16; } } void checkpos (short player) /* Checks your position, and makes sure you don't go through a wall */ { short hit = 0; short nx; i = wgetworldblock (player, wobject[player].x, wobject[player].y); if (tiletypes[i] == 0) hit = 1; i = wgetworldblock (player, wobject[player].x+15, wobject[player].y); if (tiletypes[i] == 0) hit = 1; i = wgetworldblock (player, wobject[player].x, wobject[player].y + 15); if ((tiletypes[i] == 0) | (tiletypes[i] == 4)) hit = 1; i = wgetworldblock (player, wobject[player].x + 15, wobject[player].y + 15); if (tiletypes[i] == 0) hit = 1; i = wgetworldblock (player, wobject[player].x + 7, wobject[player].y + 7); if (tiletypes[i] == 2) { sound (500); wputworldblock (WIN, wobject[player].x + 7, wobject[player].y + 7, 12); incscore (player, 10); total_dots--; check_dots_left (); } if (tiletypes[i] == 3) { sound (800); wputworldblock (WIN, wobject[player].x + 7, wobject[player].y + 7, 12); bluetime += 150; total_dots--; check_dots_left (); } if (wobject[player].x < 4) { wobject[player].x = mapwidth[WIN] * 16 - 32; wshowwindow (player, (worldx[player] + 144) / 16, worldy[player] / 16); } if (wobject[player].x > mapwidth[WIN] * 16 - 17) { wobject[player].x = 16; wshowwindow (player, 0, worldy[player] / 16); } if (hit == 1) { wobject[player].x = ox[player]; wobject[player].y = oy[player]; moved[player] = 0; } } void moveghost (short numb) /* Checks the ghost's position, and makes sure it doesn't go through a wall */ { short gox, goy; /* Coordinate of ghost */ short hit = 0; short j; gox = wobject[numb].x; goy = wobject[numb].y; if (moved[numb] == 0) movedir[numb] = (rand () % 5) +1; /* Pick a random direction (1-5) 5 = still */ switch (movedir[numb]) { case 1: wobject[numb].x += ghostspeed; break; case 2: wobject[numb].x -= ghostspeed; break; case 3: wobject[numb].y += ghostspeed; break; case 4: wobject[numb].y -= ghostspeed; break; } moved[numb] += ghostspeed; if (moved[numb] >= 16) moved[numb] = 0; /* Make sure ghost doesn't move off the screen. */ if (wobject[numb].x < 0) wobject[numb].x = 0; else if (wobject[numb].x > (mapwidth[WIN] - 1) * 16) wobject[numb].x = (mapwidth[WIN] - 1) * 16; if (wobject[numb].y < 0) wobject[numb].y = 0; else if (wobject[numb].y > (mapheight[WIN] - 1) * 16) wobject[numb].y = (mapheight[WIN] - 1) * 16; j = wgetworldblock (WIN, wobject[numb].x, wobject[numb].y); if (tiletypes[j] == 0) hit = 1; j = wgetworldblock (WIN, wobject[numb].x + 15, wobject[numb].y); if (tiletypes[j] == 0) hit = 1; j = wgetworldblock(WIN, wobject[numb].x, wobject[numb].y + 15); if (tiletypes[j] == 0) hit = 1; if ((tiletypes[j] == 4) & (movedir[numb] == 3)) /* Can't move down through ghost's door */ hit = 1; j = wgetworldblock(WIN, wobject[numb].x + 14, wobject[numb].y + 15); if (tiletypes[j] == 0) hit = 1; if (hit == 1) /* A solid tile was run into */ { wobject[numb].x = gox; /* Set to the old position */ wobject[numb].y = goy; moved[numb] = 0; } if ((wobject[numb].x == gox) && (wobject[numb].y == goy)) moveghost (numb); /* Recursive call, makes sure ghost moves in a new direction if it ran into a wall the first time. */ } void do_player (short player) { spx = 0; spy = 0; ox[player] = wobject[player].x; oy[player] = wobject[player].y; if (dying[player] == 0) { switch(movedir[player]) { case 1: wobject[player].x += pacspeed; break; case 2: wobject[player].x -= pacspeed; break; case 3: wobject[player].y += pacspeed; break; case 4: wobject[player].y -= pacspeed; break; } if (movedir[player] != 0) { moved[player] += pacspeed; checkpos (player); } if (moved[player] >= 16) moved[player] = 0; if (moved[player] == 0) { if (kbdon[keys[player][RIGHT]]) { movedir[player] = 1; pacdir[player] = 0; } else if (kbdon[keys[player][LEFT]]) { movedir[player] = 2; pacdir[player] = 2; } else if (kbdon[keys[player][UP]]) { movedir[player] = 4; pacdir[player] = 1; } else if (kbdon[keys[player][DOWN]]) { movedir[player] = 3; pacdir[player] = 3; } } pacanim++; if (pacanim > 5) pacanim = 1; wobject[player].num = pacanim + (pacdir[player] * 5); /* Set the sprite image for pacman */ } else /* Dying loop */ { wobject[player].num = (DIESPEED - dying[player] + 31); if (wobject[player].num > 34) wobject[player].num = 34; dying[player]--; if (dying[player] == 0) { wobject[player].x = 192; wobject[player].y = 176; wobject[player].num = 1; } } } void main(void) { short j; oldmode = wgetmode (); if (!vgadetected ()) { printf ("VGA is required to run this program..."); exit (1); } printf ("WGT Example #59\n\n"); printf ("This is a PACMAN clone which has two player mode.\n"); printf ("The right player uses the arrow keys, and the left player uses\n"); printf ("the W, A, S, and D keys.\n"); printf ("\nPress any key to begin\n"); getch (); vga256 (); wtextcolor (1); wtexttransparent (TEXTFGBG); wtextbackground (254); /* Load the graphics */ wloadsprites (palette, "pactile.spr", pactile, 1, NUM_LOAD); wloadsprites (palette, "pacspr.spr", pacspr, 1, NUM_LOAD); wsetpalette (0, 255, palette); /* load our pacman map */ winitscroll (WIN, NORMAL, -1, 10, 12, pactile); winitscroll (WIN2, NORMAL, -1, 10, 12, pactile); pacmap = wloadmap (WIN, "pacman.wmp", tiletypes, wobject); wcopymap (WIN, WIN2); wcls (0); wbutt (0, 0, 319, 199); wshowwindow (WIN, 5, 5); wshowwindow (WIN2, 6, 5); count_dots (); installkbd (); set_positions (); frames = 0; timer = 0; winittimer (); wstarttimer (timerctr, TICKS(100)); /* Program runs at top speed */ do { do_player (0); do_player (1); if (bluetime > 0) bluetime--; for (i = 2; i < 6; i++) /* Ghost loop */ { if (traptime[i] == 0) { moveghost (i); if (bluetime > 0) wobject[i].num = 25; if ((bluetime == 1) || ((bluetime < 40) && (bluetime % 2 == 1))) wobject[i].num = 19 + i; for (j = 0; j < 2; j++) if ((soverlap (i, wobject, pacspr, j, wobject, pacspr) == 1) && (traptime[i] == 0)) { if (bluetime > 0) { wobject[i].num = 27 + bonus; incscore (j, bonusscore[bonus]); bonus++; traptime[i] = 100; } else if (dying[j] == 0) /* The ghost caught you */ dying[j] = DIESPEED; } } else traptime[i]--; if (traptime[i] == 1) { wobject[i].x = 192; wobject[i].y = 144; wobject[i].num = 19 + i; bonus = 0; } } /* Find out the scrolling speed based on where you are in the window. */ if (wobject[0].x - worldx[WIN] < windowmaxx[WIN] / 2 - 1) spx = -pacspeed; else if (wobject[0].x - worldx[WIN] > windowmaxx[WIN] / 2 + 1) spx = pacspeed; if (wobject[0].y - worldy[WIN] < windowmaxy[WIN] / 2 - 1) spy = -pacspeed; else if (wobject[0].y - worldy[WIN] > windowmaxy[WIN] / 2 + 1) spy = pacspeed; nosound (); wscrollwindow (WIN, spx, spy); wshowobjects (WIN, 0, 8, pacspr, wobject); wputblock (0, 0, scrollblock[WIN], NORMAL); spx = 0; spy = 0; /* Do the same for the second player */ if (wobject[1].x - worldx[WIN2] < windowmaxx[WIN2] / 2 - 1) spx = -pacspeed; else if (wobject[1].x - worldx[WIN2] > windowmaxx[WIN2] / 2 + 1) spx = pacspeed; if (wobject[1].y - worldy[WIN2] < windowmaxy[WIN2] / 2 - 1) spy = -pacspeed; else if (wobject[1].y - worldy[WIN2] > windowmaxy[WIN2] / 2 + 1) spy = pacspeed; wscrollwindow (WIN2, spx, spy); wshowobjects (WIN2, 0, 8, pacspr, wobject); wretrace (); wputblock (161, 0, scrollblock[WIN2], NORMAL); frames++; } while (!kbdon[ESC]); /* until ESC is pressed */ wstoptimer (); wdonetimer (); uninstallkbd (); wendscroll (WIN); wendscroll (WIN2); wfreesprites (pactile, 0, NUM_LOAD); wfreesprites (pacspr, 0, NUM_LOAD); wfreemap (pacmap); wsetmode (oldmode); printf ("Number of Frames: %i\n", frames); printf ("Time elapsed: %i microseconds\n", timer); printf ("Frame Rate: %f\n", (float)frames / (float)(timer / 100.0)); }