VAZPAC Game Design Notes (updated March 20, 2005) For WIN32 game, Visual C++ compiler, GDI graphics and DirectDraw versions (and DirectSound) VazPac and VazPacDelux GDI version (VazPac.exe) should run on Windows ME/XP due to a bug in Win98/98SE GDI graphics using transparent Blit I've done a DirectDraw version (VazPacDelux.exe) which should run on Win 98/98SE/ME/XP ======================================================================= GAME STATES for VazPac GAME_STATE_DEMO_INIT = 0 (Demo initialization) GAME_STATE_DEMO_RUN = 1 (Demo running) GAME_STATE_GAME_INIT = 2 (Game initialization) GAME_STATE_GAME_RUN = 3 (Game running) GAME_STATE_GAME_RESET = 4 (Game reset -- new level etc) GAME_STATE_GAME_PAUSE = 5 (Game paused -- no movement) GAME_STATE_INTM_INIT = 6 (Intermission init) GAME_STATE_INTM_RUN = 7 (Intermission running) ======================================================================= CONSTANTS for VazPac VAZ_SPEED = 3 (Vaz character 3 pixels per move constant) BULLET_SPEED = 9 (for ghostbuster gun) MAZE_WIDTH = 25 (Maze horizontal width 25 blocks) MAZE_HEIGHT = 19 (Maze vertical height 19 blocks) BLOCK_SIZE = 30 (Maze block size = 30 pixels each block) XTOP_LEFT = 25 (Top Left X pixel position for Maze) YTOP_LEFT = 0 (Top Left Y pixel position for Maze) MAX_GHOSTS = 9 (3 = level 1,2 -- 6 = level 3,4,5 -- 9 = level 6+) MAX_POWER = 20 (max number of power pills) MAX_FOOD = 20 (max number of food items) MAX_SCORES = 20 (max number of displayed scores) MAX_BULLETS = 5 (max bullets for ghostbuster gun) MAX_PARTICLES = 250 (max number of particles for explosions etc) SCORE_PELLET = 5 SCORE_POWER = 25 SCORE_FOOD = 100 (fruit x 1, veggie x 3, etc) SCORE_GHOST = 100 (doubles each ghost chomped, 200, 400, 800, 1600, etc) SCORE_EXTRA = 10000 (score for extra Vaz) LEVEL_PAUSE = 1000 pause between levels, and to show Ready!, Go! BULLET_PAUSE = 6 pause time between bullets BULLET_DURATION = 20 how long bullet lasts VAZ_NORMAL = 0 VAZ_DYING = 1 CHASE_NORMAL = 0 // ghost chasing vaz CHASE_AWAY = 1 // ghost running away CHASE_DEMONIC = 2 // ghost demonic chasing CHASE_EYES = 3 // ghost eyes only back to jail GHOST_BLUE = 0 (bmp positions 0,1,2,3, 4,5,6,7) GHOST_GREEN = 8 (bmp positions 8,9,10,11, 12,13,14,15) GHOST_RED = 16 (bmp positions 16,17,18,19, 20,21,22,23) GHOST_SCARED = 24 (bmp positions 24,25,26,27, 28,29,30,31 white/yellow) GHOST_DEMONIC = 32 (bmp positions 32,33,34,35, 36,37,38,39 dark red with horns) GHOST_EYES = 40 (bmp positions 40,41,42,43 eyes only) GHOST_RIGHT = 0 GHOST_DOWN = 1 GHOST_LEFT = 2 GHOST_UP = 3 MAZE_BLUE = 0 MAZE_GREEN = 10 MAZE_RED = 20 etc... ======================================================================= GLOBAL VARS and initial values int game_state = DEMO_INIT; // initial game state int game_score = 0; // game score int chomp_score; // to remember doubling chomp score 100,200,400,800, etc int game_level = 1; // game level (starts at 1) int ghost_speed = 1; // 1 = levels 1,2 -- 2 = 3,4,5 -- 3 = 6+ etc int vaz_left = 0; // number of VazPac left int pellets_left = (total number of pellets counted from Maze array) int level_countdown = LEVEL_PAUSE; int bullet_countdown; // for pause time between bullets int Maze [MAZE_HEIGHT][MAZE_WIDTH]; // 0 = blank space // current maze // 1 = pellet // 2 = power pill int Archive1[ ][ ] // 3 = wall turn bottom-left Archive2[ ][ ] // 4 = wall turn bottom-right Archive3[ ][ ] // 5 = wall turn top-left // copy Archive into Maze // 6 = wall turn top-right // 7 = wall horizontal // 8 = wall vertical // 9 = wall left end // 10 = wall right end // 11 = wall up end // 12 = wall down end NOTE: when reading in maze, count the number of pellets including power pills and save in pellets_left HBITMAP hvazbmp[24] // 0 to 23 total Vaz mouth positions 4 x 6 = 24 BITMAP vazbmp[24] HBITMAP hghostbmp[44] // blue 0-7, green 8-15, red 16-23 BITMAP ghostbmp[44] // scared 24-31, demonic 32-39, eyes 40-43 HBITMAP hmazebmp[30] // 10 for blue, 10 for green, 10 for red walls etc BITMAP mazebmp[30] HBITMAP hfoodbmp[20] BITMAP foodbmp[20] ====================================================================== STRUCTS for VazPac VAZ_STRUCT Vaz (just one) int .state (VAZ_NORMAL or DYING) int .x .y (x y top-left of VazPac) int .xm .ym (x y current movement) int .tomove (direction desired to move) int .mouth (mouth position, 0 to 5 for bmp dir + mouth) int .dir (facing direction) bool .gun (TRUE = has gun and can fire if VAZ_NORMAL, FALSE = no gun) int .count (for dying, vomiting, sneezing positions and delay etc ?) GHOST_STRUCT Ghosts[MAX_GHOSTS] bool .alive (TRUE = exist, FALSE = not) int .color (GHOST_BLUE, _GREEN, _RED -- note: must remember original color) int .chase (CHASE_NORMAL, _AWAY, _DEMONIC, _EYES) int .x .y (x y top-left of ghost) int .xm .ym (x y movement) bool .jailed (TRUE = in jail, FALSE = normal chase) int .count (for flashing during run away, for jail time during jail) POWER_STRUCT Power[MAX_POWER] bool .alive (TRUE = exist, FALSE = not) int .x .y (x y center of power pill) int .count (for size of flashing power pill 0 to 15 ?) BULLET_STRUCT Bullets[MAX_BULLETS] bool .alive (TRUE = exist, FALSE = not) int .x .y (x y top-left of bullet) int .xm .ym (x y movement) int .count (duration of bullet, start at BULLET_DURATION) FOOD_STRUCT Food[MAX_FOOD] bool .alive (TRUE = exist, FALSE = not) int .type (type of food 0 to 19) int .x .y (x y top-left of food) int .xm .ym (x y movement) int .count (how long food lasts) SCORE_STRUCT Scores[MAX_SCORES] bool .alive (TRUE = exist, FALSE = not) int .amount (amount of score) int .x .y (x y top-left of score text) int .count (how long score lasts before fade out) PARTICLE_STRUCT Particles[MAX_PARTICLES] bool .alive (TRUE = exist, FALSE = not) int .x .y (x and y of particle) float .xm .ym (float since using 32 angle positions) int .count (duration of particle) ======================================================================= FUNCTIONS for VazPac GameInit() -- Game Initialization, go full screen GameMain() -- Game Main Loop and Processing GameQuit() -- Game Quit and Clean Up DisplayScore() -- Display Score bottom of screen -- when DEMO_RUN show text instructions also SetMaze() -- inside here load correct maze and calculate total pellets_left DrawMaze() -- called once each frame to refresh maze SetVaz() -- inside here set level_countdown = LEVEL_PAUSE (for Ready! Go! etc) MoveVaz() -- move VazPac once SetGhosts() -- inside here # ghosts depends on level # MoveGhosts() -- move all ghosts once InsertFood() -- insert a food item based on level # MoveFood() -- move all food items once InsertScore(a) -- add a score of amount a DrawScores() -- draw all visible extra scores InsertBullet() -- insert one bullet MoveBullets() -- move all existing bullets once InsertParticles(x,y,t) -- insert particles at x,y of type t (explosion, vomit/sneeze, gun) MoveParticles() -- move all particles once ResetAll() -- resets/erases all current ghosts, food, bullets, scores, particles SetInterm() -- setup intermission animation bool AnimInterm() -- return TRUE when done, otherwise FALSE FlashPower() -- flash all the power pills based on count CheckCollisions() -- Check for ALL potential collisions (Vaz to Pellets/Pills, Vaz to Ghosts, Vaz to Food, Bullets to Ghosts) ================================================================================== CHARACTERISTICS OF OBJECTS Normal classic PacMan rules: Ghosts chase Vaz around, begin in "Jail" in center Vaz chomps pellets, when chomping Power Pill then can eat ghosts Ghosts chase normally, when Vaz eats Power Pill ghosts "run away" When Vaz chomps ghosts, eyes appear and run back to "Jail" in center Where it differs from original PacMan rules: Vaz can fire at ghosts if finding gun, hitting them blue, then eat When find gun play gb1 theme, when hit ghost play gb2 theme Level 1,2 = 3 ghosts (blue maze) Level 3,4,5 = 6 ghosts including some demonic ghosts (green,blue,green maze) Level 6,7,8,9 = 9 ghosts including multiple fast demonic ghosts (red maze) Then repeat random color, random maze type with 9 ghosts ITEMS TO EAT Fruits (shows level 1,2) Veggies (shows level 3+) Candy/Cake/Flowers/Bugs (shows level 6+) Add particles for items appear/disappear, gun bullet hit wall, etc SCREEN TO MAZE CONVERSION FOR COLLISION DETECTION x,y = x,y screen pixel position coordinates c,r = column and row maze position (2 dim array) c = (x - XTOP_LEFT) / BLOCK_SIZE r = (y - YTOP_LEFT) / BLOCK_SIZE x = (c * BLOCK_SIZE) + XTOP_LEFT y = (r * BLOCK_SIZE) + YTOP_LEFT Therefore, object is at Maze[r][c] or Screen x,y for collision detect ======================================================================= PSEUDO CODE for VazPac When DEMO_INIT SetMaze() SetGhosts() set state to DEMO_RUN When DEMO_RUN // NOTE: No Sound in Demo DrawMaze() MoveGhosts() MoveFood() MoveParticles() FlashPower() DrawScores() DisplayScore() Wait for key if pressed, set state to GAME_INIT otherwise, leave state at DEMO_RUN When GAME_INIT game_score = 0, game_level = 1, vaz_left = 5, chomp_score = SCORE_GHOST SetMaze() ResetAll() SetVaz() SetGhosts() set state to GAME_RUN When GAME_RUN DrawMaze() FlashPower() MoveParticles() DrawScores() MoveVaz() // Check level_countdown and if zero then allow movement MoveBullets() MoveGhosts() // if level_countdown zero move ghosts, otherwise just draw ghosts MoveFood() // if level_countdown zero move food, otherwise return and ignore CheckCollisions() // if level_countdown zero then check for collisions DisplayScore() // will only display bottom score/level if "p" key pressed, set state to GAME_PAUSE otherwise, leave state at GAME_RUN When GAME_RESET if pellets_left = 0 then add one to level SetMaze() if at level 3, 6, 10, 15, 20 (every five, etc) set state to INTM_INIT if any other level, play short song/sound etc ResetAll() SetVaz() SetGhosts() set state to GAME_RUN When GAME_PAUSE Stop all movement (by not updating) Wait for key to resume if key pressed, set state to GAME_RUN otherwise, leave state at GAME_PAUSE When INTM_INIT SetInterm() Set state to INTM_RUN When INTM_RUN anim_over = AnimInterm() if anim_over set state to GAME_RUN otherwise leave state at INTM_RUN ======================================================================== VAZPAC screen diagram WINDOW_WIDTH = 800 WINDOW_HEIGHT = 600 Each Maze "block" is 30 pixels wide Maze width = 25 blocks, Maze height = 19 blocks That leaves 25 pixels space on either side of horizontal (Maze is 25 to 775 pixels horiz) That leaves 30 pixels space on bottom of vertical (Maze is 0 to 570 pixels vert) SCORE = XXX LEVEL = XX VAZ = X VazPac a game by PhilVaz (c) 2003 ======================================================================================= END OF DESIGN NOTES