⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 game.cpp

📁 VIGASOCO (VIdeo GAmes SOurce COde) Windows port (v0.01)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Game.cpp
//
/////////////////////////////////////////////////////////////////////////////

#include "Game.h"
#include "InitState.h"
#include "DemoState.h"
#include "CharacterSubstate.h"
#include "CoinInsertedState.h"
#include "GhostDeadSubstates.h"
#include "PlayingState.h"
#include "RedGhost.h"
#include "PinkGhost.h"
#include "BlueGhost.h"
#include "OrangeGhost.h"
#include "../Operations.h"
#include "Pacman.h"
#include "Video.h"
#include "Writer.h"

GameState *Game::states[4];

/////////////////////////////////////////////////////////////////////////////
// initialization and cleanup
/////////////////////////////////////////////////////////////////////////////

Game::Game()
{
	resetState();

	// inits scheduled tasks list
	Task::initScheduledTasksList();

	state = 0;

	// creates the states
	states[0] = new InitState();
	states[1] = new DemoState();
	states[2] = new CoinInsertedState();
	states[3] = new PlayingState();

	// creates the characters
	pacman = new Pacman();
	ghost[RED] = new RedGhost();
	ghost[PINK] = new PinkGhost();
	ghost[BLUE] = new BlueGhost();
	ghost[ORANGE] = new OrangeGhost();

	ghostDeadSubstates[0x00] = new GhostInitKillSubstate();
	ghostDeadSubstates[0x01] = new GhostDeadNopSubstate();
	ghostDeadSubstates[0x02] = new GhostEndKillSubstate();
}

Game::~Game()
{
	// deletes dead substates
	for (int i = 0; i < 3; i++){
		delete ghostDeadSubstates[i];
	}

	// deletes the characters
	delete pacman;
	for (int i = 0; i < 4; i++){
		delete ghost[i];
	}

	// delete game states
	for (int i = 0; i < 4; i++){
		delete states[i];
	}

	// deletes scheduled tasks list
	Task::endScheduledTasksList();
}

void Game::resetState()
{
	for (int i = 0; i < 7; i++){
		ghostsOrientationChanges[i] = 0;
	}

	indexOrientationChanges = cntOrientationChanges = 0;

	// counters for movement
	cntGhostsMovHome = 0;
	cntGhostsAnimations = ghostsAnimationFrame = 0;
	cntGhostsPanicAnim = 0;
	cntSuperPillsAnimation = 0;

	// difficulty
	firstDiffFlag = secondDiffFlag = false;
	pillsFirstDiffFlag = pillsSecondDiffFlag = 0;

	pinkGhostExitHomeCounterLimit = blueGhostExitHomeCounterLimit = orangeGhostExitHomeCounterLimit = 0;
	inactivityCounterLimit = inactivityCounter = 0;
	eatenPillsAfterDead = 0;

	timeInPanicState = remainingTimeInPanicState = 0;

	currentKills = 0;

	fruitPosition = fruitEntry = fruitSprite = fruitColor = 0;

	cntShowHide1P2P = 0;

	collisionObject = 0;
	killingGhostState = ghostDeadAnimState = 0;

	for (int i = 0; i < 3; i++){
		cutsceneState[i] = 0;
	}

	currentPlayer = 0;
	numberOfPlayers = 0;

	score1P = score2P = highScore = 0;
	gotBonusLife1P = gotBonusLife2P = false;
}

/////////////////////////////////////////////////////////////////////////////
// game's initialization methods
/////////////////////////////////////////////////////////////////////////////

void Game::initGameState()
{
	pacman->resetState();

	for (int i = 0; i < 4; i++){
		ghost[i]->resetState();
	}

	for (int i = 0; i < 7; i++){
		ghostsOrientationChanges[i] = 0;
	}
	indexOrientationChanges = cntOrientationChanges = 0;

	cntGhostsMovHome = 0;
	cntGhostsAnimations = ghostsAnimationFrame = 0;
	cntGhostsPanicAnim = 0;
	cntSuperPillsAnimation = 0;

	firstDiffFlag = secondDiffFlag = false;
	pillsFirstDiffFlag = pillsSecondDiffFlag = 0;

	pinkGhostExitHomeCounterLimit = blueGhostExitHomeCounterLimit = orangeGhostExitHomeCounterLimit = 0;
	inactivityCounter = inactivityCounterLimit = 0;
	eatenPillsAfterDead = 0;

	timeInPanicState = remainingTimeInPanicState = 0;

	currentKills = 0;

	fruitPosition = fruitEntry = fruitSprite = fruitColor = 0;

	cntShowHide1P2P = 0;

	collisionObject = 0;
	killingGhostState = ghostDeadAnimState = 0;
}

void Game::initCharacterState(bool special)
{
	pacman->initState(special);

	for (int i = 0; i < 4; i++){
		ghost[i]->initState(special);
	}

	fruitSprite = 0x3f;
	fruitColor = 0x00;
	fruitPosition = 0;
}

void Game::resetCharacterPositions()
{
	fruitPosition = 0;
	pacman->posX = pacman->posY = 0;
	ghost[RED]->posX = ghost[RED]->posY = 0;
	ghost[PINK]->posX = ghost[PINK]->posY = 0;
	ghost[BLUE]->posX = ghost[BLUE]->posY = 0;
	ghost[ORANGE]->posX = ghost[ORANGE]->posY = 0;
}

void Game::initPlayersLevelData()
{
	currentPlayer = 0;

	// init player state
	PlayerLevelState *p = &levelState[0];
	p->diffEntry = 0;
	p->firstFruit = false;
	p->secondFruit = false;
	p->eatenPills = 0;
	p->pinkGhostHomeCounter = 0;
	p->blueGhostHomeCounter = 0;
	p->orangeGhostHomeCounter = 0;
	p->easierFlag = false;
	p->currentLevel = 0;

	// init player pills
	p->initPills();

	// copy settings to the other player
	levelState[1].clone(p);
}

/////////////////////////////////////////////////////////////////////////////
// main loop
/////////////////////////////////////////////////////////////////////////////

// resumes execution
void Game::run()
{
	// fill sprite list
	sprites.clear();
	drawFruit();
	pacman->draw();
	for (int i = 0; i < 4; i++){
		ghost[i]->draw();
	}

	// updates the internal timers
	scheduler.updateInternalTimers();

	// executes scheduled tasks
	scheduler.executeScheduledTasks();

	// resumes execution
	states[state]->run();

	// if we're not initializing, adjust and animate sprites
	if (state != INIT){
		// animate sprites
		if (pacman->deadAnimState != 0){
			for (int i = 0; i < 4; i++){
				ghost[i]->selectProperAnimation();
			}
		} else {
			if (collisionObject == 0){
				pacman->selectProperAnimation();
				for (int i = 0; i < 4; i++){
					ghost[i]->selectProperAnimation();
				}
			}
		}

		// update credits if a new coin is inserted
		settings.checkForCoinInserted();
		settings.checkForNewCredit();

		// show/hide 1UP or 2UP
		Writer::showOrHide1UP2UP();

		if (state == DEMO){
			// TODOSOUND: if we're in demo mode, make sure that we aren't playing any sound
		}
	}
}

/////////////////////////////////////////////////////////////////////////////
// game counters
/////////////////////////////////////////////////////////////////////////////

// check if we have to set the difficulty flags
void Game::updateDifficultyFlags()
{
	// if orange ghost has exited home
	if (theGame->ghost[PINK]->substate != 0){

		int remainingPills = 244 - theGame->levelState[0].eatenPills;

		// check if we have to set the first difficulty flag
		if (!theGame->firstDiffFlag){
			if (remainingPills <= theGame->pillsFirstDiffFlag){
				theGame->firstDiffFlag = true;
			}
		}

		// check if we have to set the second difficulty flag
		if (!theGame->secondDiffFlag){
			if (remainingPills <= theGame->pillsSecondDiffFlag){
				theGame->secondDiffFlag = true;
			}
		}
	}
}

// check if a ghost has to exit home
void Game::checkGhostsExitHomeCounters()
{
	// if pacman has died in this level, wait a bit to let the ghosts go out
	if (levelState[0].easierFlag){
		eatenPillsAfterDead++;
	} else {
		// increment ghosts counters checking which ones are out
		if (ghost[ORANGE]->substate == 0){
			if (ghost[BLUE]->substate == 0){
				if (ghost[PINK]->substate == 0){
					levelState[0].pinkGhostHomeCounter++;
				} else {
					levelState[0].blueGhostHomeCounter++;
				}
			} else {
				levelState[0].orangeGhostHomeCounter++;
			}
		}
	}
}

void Game::checkGhostsExitHomeInactivity()
{
	// if pacman has just eaten a pill, reset inactivity counter
	if (pacman->pillsInLastMove != levelState[0].eatenPills){
		inactivityCounter = 0;
	} else {
		inactivityCounter++;

		// if there's too much inactivity, get ghost out of home
		if (inactivityCounter == inactivityCounterLimit){
			inactivityCounter = 0;

			// get a ghost out of home
			if (ghost[PINK]->substate == 0) {
				ghost[PINK]->substate = 2;
			} else if (ghost[BLUE]->substate == 0){
				ghost[BLUE]->substate = 3;
			} else if (ghost[ORANGE]->substate == 0){
				ghost[ORANGE]->substate = 3;
			}
		}
	}
}


/////////////////////////////////////////////////////////////////////////////
// movement and collision detection
/////////////////////////////////////////////////////////////////////////////

void Game::moveAndHandleCollisions()
{
	// if pacman is dying, keep animating
	pacman->animateDead();

	// if pacman is alive
	if (pacman->deadAnimState == 0){
		// if the game has to kill a ghost, does it
		killGhosts();

		// move killed ghosts
		for (int i = 0; i < 4; i++){
			ghost[i]->moveWhenKilled();
		}

		// if there's a ghost dying, animate it
		if (collisionObject > 0){
			animateGhostDead();
		} else {
			moveAndCheckCollisions();
		}
	}
}

void Game::moveAndCheckCollisions()
{
	// calculate pacman collision with each ghost at tile level
	checkTileColision();

	// calculate pacman collision with each ghost using absolute positions
	checkAbsolutePosColision();

	// if there wasn't a collision
	if (collisionObject == 0){
		// move pacman
		pacman->run();

		// move the ghosts
		for (int i = 0; i < 4; i++){
			ghost[i]->run();
		}

		// if we're playing
		if (states[PLAYING]->substate == 0x03){
			// check if the big pill effect has ended, and update ghosts accordingly
			checkEndOfSuperPillEffect();

			// check if the ghosts have to go out
			checkIfPinkGhostGoesOut();
			checkIfBlueGhostGoesOut();
			checkIfOrangeGhostGoesOut();
		}
	}
}

// check collisions at the tile level
void Game::checkTileColision()
{
	bool collision = false;

	for (int i = 3; i >= 0; i--){
		// if the ghost is alive
		if (ghost[i]->state == 0){
			// if it's in the same tile as pacman, we've detected a collision
			if ((pacman->tilePosX == ghost[i]->actualTilePosX) && (pacman->tilePosY == ghost[i]->actualTilePosY)){
				collisionObject = i + 1;
				pacman->deadAnimState = i + 1;
				collision = true;

				break;
			}
		}
	}

	if (collision){
		// if the ghost was in panic state, pacman continues alive
		if (ghost[collisionObject - 1]->panicMode){
			pacman->deadAnimState = 0;

			// increment number of kills
			currentKills++;

			// updates the score
			updateScore(currentKills + 1);

			// TODOSOUND: set eaten sound in channel 2
		}
	}
}

// check collisions using absolute positions
void Game::checkAbsolutePosColision()

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -