/*
==============================================================================
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 <dos.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <wgt5.h>
#include <wgtscrol.h>
#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));
}