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

📄 game.cpp

📁 VIGASOCO (VIdeo GAmes SOurce COde) Windows port (v0.01)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
{
	// if we haven't detected a collision yet and pacman has eaten a big pill
	if ((collisionObject == 0) && (pacman->superPillEffect)) {
		bool collision = false;

		for (int i = 3; i >= 0; i--){
			// if the ghost is alive
			if (ghost[i]->state == 0){
				// if the distance in both coordinates is < 4, we've detected a collision
				if (((abs(ghost[i]->posX - pacman->posX)) < 4) && ((abs(ghost[i]->posY - pacman->posY)) < 4)){
					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
			}
		}
	}
}

/////////////////////////////////////////////////////////////////////////////
// game's animation methods
/////////////////////////////////////////////////////////////////////////////

void Game::animateGhostDead()
{
	ghostDeadSubstates[ghostDeadAnimState]->run();
}

void Game::updateGhostAnimCounters()
{
	cntGhostsAnimations++;

	// change animation frame each 8 ticks
	if (cntGhostsAnimations == 8){
		cntGhostsAnimations = 0;
		ghostsAnimationFrame = ghostsAnimationFrame ^ 1;  
	}
}

void Game::updateSuperPillState()
{
	cntSuperPillsAnimation++;

	// change pill state each 10 ticks
	if (cntSuperPillsAnimation == 10){
		cntSuperPillsAnimation = 0;

		// if we're playing in the level
		if (states[PLAYING]->substate == 3){
			int color = (CRAM[0x064] == 0x010) ? 0x00 : 0x10;

			// change super pills visibility
			CRAM[0x064] = CRAM[0x078] = CRAM[0x384] = CRAM[0x398] = color;
		} else {
			// we are in the demo
			int color = (CRAM[0x332] == 0x010) ? 0x00 : 0x10;

			// change super pills visibility
			CRAM[0x278] = CRAM[0x332] = color;
		}
	}
}

void Game::moveGhostAtHome()
{
	// if there wasn't any unhandled collision
	if (collisionObject == 0){
		// update movement bit pattern
		cntGhostsMovHome = Operations::rotateLeft<UINT8, 8>((UINT8)cntGhostsMovHome);

		// if we have to move, update ghosts move at home
		if (cntGhostsMovHome & 0x01){
			for (int i = 0; i < 4; i++){
				ghost[i]->moveAtHome();
			}
		}
	}
}

void Game::setDeadGhostsColor()
{
	// in demo, dead ghost are not visible, otherwise we see their eyes only
	int color = (states[DEMO]->substate == 0x22) ? 0x00 : 0x19;

	// change dead ghost colors
	for (int i = 0; i < 4; i++){
		if (ghost[i]->state != 0){
			ghost[i]->color = color;
		}
	}
}

void Game::setGhostsColors()
{
	// if there wasn't any unhandled collision
	if (collisionObject == 0){
		// when the counter is 0, update ghost colors
		if (cntGhostsPanicAnim == 0){

			cntGhostsPanicAnim = 0x0e;

			if (pacman->superPillEffect){
				if (remainingTimeInPanicState < 0x100){
					// TODOSOUND: something sound related here

					if (pacman->color != 0x09){
						pacman->color = 0x09;
					} else {
						// TODOSOUND: something sound related here
					}
				}
			}

			// set ghost colors
			for (int i = 0; i < 4; i++){
				if (ghost[i]->panicMode){
					// if super pill effect is ending, alternate colors
					if (remainingTimeInPanicState < 0x100){
						ghost[i]->color = (ghost[i]->color == 0x11) ? 0x12 : 0x11;
					}
				} else {
					// set normal color
					ghost[i]->color = i*2 + 1;
				}
			}
		}

		cntGhostsPanicAnim--;
	}
}

/////////////////////////////////////////////////////////////////////////////
// misc methods
/////////////////////////////////////////////////////////////////////////////

// update score (and maybe hi-score) and check for bonus life after picking an item
void Game::updateScore(int action)
{
	static int scorePoints[14] = { 
		10, 50, 200, 400, 800, 1600, 100, 300, 500, 700, 1000, 2000, 3000, 5000 
	};

	// if we're not in demo mode
	if (state != DEMO){
		// get a pointer to the score and add the points for the action
		int *score = (currentPlayer == 0) ? &score1P : &score2P;
		bool *gotBonusLife = (currentPlayer == 0) ? &gotBonusLife1P : &gotBonusLife2P;
		*score += scorePoints[action];

		// check if the player deserves a bonus live
		if ((!(*gotBonusLife)) && (*score > settings.bonusLife)){
			// increments number of lives and set bonus flag
			*gotBonusLife = true;
			levelState[0].lives++;
			levelState[0].displayedLives++;

			// TODOSOUND: play a sound

			// update lives
			Video::drawLives(levelState[0].displayedLives);
		}

		// print current player score
		Writer::printScore(*score, (currentPlayer == 0) ? 0x3fc : 0x3e9, 6, 4);

		// check if the player has more points than the high score
		if (*score > highScore){
			highScore = *score;

			// print high score
			Writer::printScore(highScore, 0x3f2, 6, 4);
		}
	}
}

void Game::initSuperPillVars()
{
	// init panic state time
	remainingTimeInPanicState = timeInPanicState;

	pacman->superPillEffect = true;
	pacman->hasToChangeOrientation = true;	// used in demo mode

	// notify the ghosts of the super pill effect
	for (int i = 0; i < 4; i++){
		ghost[i]->panicMode = true;
		ghost[i]->hasToChangeOrientation = true;
	}

	// init ghost animation counter
	cntGhostsPanicAnim = 0;

	currentKills = 0;

	// change ghosts sprite numbers and colors
	for (int i = 0; i < 4; i++){
		ghost[i]->sprite = 0x1c;
		ghost[i]->color = 0x11;
	}

	// TODOSOUND: change channel 1 sound
}

void Game::savePillsConfiguration()
{
	int offset = 0;

	// iterate through normal pills
	for (int i = 0; i < 240; i++){
		offset += Video::pillOffsets[i];

		// save pill state
		levelState[0].normalPills[i] = theGame->VRAM[offset] == 0x10;
	}

	// save big pills state
	theGame->levelState[0].superPills[0] = theGame->VRAM[0x064];
	theGame->levelState[0].superPills[1] = theGame->VRAM[0x078];
	theGame->levelState[0].superPills[2] = theGame->VRAM[0x384];
	theGame->levelState[0].superPills[3] = theGame->VRAM[0x398];
}

void Game::checkForOrienationChange()
{
	if (pacman->superPillEffect || (indexOrientationChanges == 7)) return;

	cntOrientationChanges++;

	// get next change counter value
	int nextChange = ghostsOrientationChanges[indexOrientationChanges];

	// if it's time to change orientation
	if (nextChange == cntOrientationChanges){
		indexOrientationChanges++;
		for (int i = 0; i < 4; i++){
			ghost[i]->hasToChangeOrientation = true;
		}
	}
}

void Game::checkDisplayFruit()
{
	static int fruitData[21][3] = {
		{ 0x00, 0x14, 0x06 },
		{ 0x01, 0x0f, 0x07 },
		{ 0x02, 0x15, 0x08 },
		{ 0x02, 0x15, 0x08 },
		{ 0x04, 0x14, 0x09 },
		{ 0x04, 0x14, 0x09 },
		{ 0x05, 0x17, 0x0a },
		{ 0x05, 0x17, 0x0a },
		{ 0x06, 0x09, 0x0b },
		{ 0x06, 0x09, 0x0b },
		{ 0x03, 0x16, 0x0c },
		{ 0x03, 0x16, 0x0c },
		{ 0x07, 0x16, 0x0d },
		{ 0x07, 0x16, 0x0d },
		{ 0x07, 0x16, 0x0d },
		{ 0x07, 0x16, 0x0d },
		{ 0x07, 0x16, 0x0d },
		{ 0x07, 0x16, 0x0d },
		{ 0x07, 0x16, 0x0d },
		{ 0x07, 0x16, 0x0d },
		{ 0x07, 0x16, 0x0d }
	};

	if (pacman->deadAnimState == 0){
		// if there's a fruit out, exits
		if (fruitEntry != 0) return;

		bool showFruit = false;

		// check if it's time to show a fruit (if it hasn't showed up yet)
		if (levelState[0].eatenPills == 0x46){
			if (!levelState[0].firstFruit){
				levelState[0].firstFruit = true;
				showFruit = true;
			}
		} else if (levelState[0].eatenPills == 0xaa){
			if (!levelState[0].secondFruit){
				levelState[0].secondFruit = true;
				showFruit = true;
			}
		}

		if (showFruit){
			int index = levelState[0].currentLevel;
			if (index > 20) index = 20;

			// set fruit data
			fruitPosition = 0x8094;
			fruitSprite = fruitData[index][0];
			fruitColor = fruitData[index][1];
			fruitEntry = fruitData[index][2];

			// clear fruit in 10 seconds
			theScheduler->addScheduledTask(new Task(4, Task::SECONDS, 10));
		}
	}
}

/////////////////////////////////////////////////////////////////////////////
// helper methods
/////////////////////////////////////////////////////////////////////////////

void Game::killGhosts()
{
	// if there's a ghost to kill
	if (killingGhostState != 0){
		// kill ghost and reset state
		ghost[killingGhostState - 1]->state = 1;
		killingGhostState = 0;
	}
}

void Game::checkEndOfSuperPillEffect()
{
	if (pacman->superPillEffect){
		bool anyGhostInPanicState = false;

		// check if any ghost is in panic mode
		for (int i = 0; i < 4; i++){
			anyGhostInPanicState |= ghost[i]->panicMode;
		}

		if (anyGhostInPanicState){
			remainingTimeInPanicState--;

			// if the super pill effect hasn't expired yet, exits
			if (remainingTimeInPanicState != 0) return;
		}

		// finish super pill effect

		pacman->color = 0x09;

		// if a ghost was alive, disables its panic mode
		for (int i = 0; i < 4; i++){
			if (ghost[i]->state == 0){
				ghost[i]->panicMode = false;
			}
		}

		remainingTimeInPanicState = 0;
		pacman->superPillEffect = false;
		cntGhostsPanicAnim = 0;
		currentKills = 0;
	}
}

void Game::checkIfPinkGhostGoesOut()
{
	// if the ghost is at home
	if (ghost[PINK]->substate == 0){
		if (levelState[0].easierFlag){
			// set pink ghost to cross the door after 7 eaten pills
			if (eatenPillsAfterDead == 7){
				ghost[PINK]->substate = 2;
			}
		} else {
			// set pink ghost to cross the door if its home counter has exceeded the limit
			if (levelState[0].pinkGhostHomeCounter >= pinkGhostExitHomeCounterLimit){
				ghost[PINK]->substate = 2;
			}
		}
	}
}

void Game::checkIfBlueGhostGoesOut()
{
	// if the ghost is at home
	if (ghost[BLUE]->substate == 0){
		if (levelState[0].easierFlag){
			// set blue ghost to cross the door after 17 eaten pills
			if (eatenPillsAfterDead == 17){
				ghost[BLUE]->substate = 3;
			}
		} else {
			// set blue ghost to cross the door if its home counter has exceeded the limit
			if (levelState[0].blueGhostHomeCounter >= blueGhostExitHomeCounterLimit){
				ghost[BLUE]->substate = 3;
			}
		}
	}
}

void Game::checkIfOrangeGhostGoesOut()
{
	// if the ghost is at home
	if (ghost[ORANGE]->substate == 0){
		if (levelState[0].easierFlag){
			// reset easier flag after 32 eaten pills
			if (eatenPillsAfterDead == 32){
				levelState[0].easierFlag = false;
				eatenPillsAfterDead = 0;
			}
		} else {
			// set orangeghost to cross the door if its home counter has exceeded the limit
			if (levelState[0].orangeGhostHomeCounter >= orangeGhostExitHomeCounterLimit){
				ghost[ORANGE]->substate = 3;
			}
		}
	}
}

void Game::drawFruit()
{
	// if there's a fruit displayed, add fruit sprite
	if (fruitEntry != 0){
		Sprite spr((fruitPosition >> 8) & 0xff, fruitPosition & 0xff, fruitSprite, fruitColor);
		theGame->sprites.push_back(spr);
	}
}

⌨️ 快捷键说明

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