📄 redghost.cpp
字号:
// RedGhost.cpp
//
/////////////////////////////////////////////////////////////////////////////
#include "RedGhost.h"
#include "Difficulty.h"
#include "Game.h"
#include "GameState.h"
#include "GhostMoveAtHomeActions.h"
#include "GhostMoveWhenKilledActions.h"
#include "../Operations.h"
#include "Pacman.h"
#include "Path.h"
#include "Video.h"
/////////////////////////////////////////////////////////////////////////////
// initialization and cleanup
/////////////////////////////////////////////////////////////////////////////
RedGhost::RedGhost() : Ghost(RED)
{
resetState();
// fills the actions arrays
moveAtHomeAction = new GhostAction*[2];
moveAtHomeAction[0] = new GhostExitHomeAction();
moveAtHomeAction[1] = new GhostNopAction();
moveWhenKilledAction = new GhostAction*[3];
moveWhenKilledAction[0] = new GhostNopAction();
moveWhenKilledAction[1] = new GhostGoHomeAction();
moveWhenKilledAction[2] = new GhostEnterHomeAndEndAction();
}
RedGhost::~RedGhost()
{
// deallocates the actions arrays
for (int i = 0; i < 2; i++){
delete moveAtHomeAction[i];
}
delete[] moveAtHomeAction;
for (int i = 0; i < 3; i++){
delete moveWhenKilledAction[i];
}
delete[] moveWhenKilledAction;
}
void RedGhost::resetState()
{
Ghost::resetState();
movDiffFlag1Pattern = movDiffFlag2Pattern = 0;
}
void RedGhost::initState(bool special)
{
Ghost::initState(special);
if (!special){
posX = 0x80;
posY = 0x64;
tilePosX = actualTilePosX = 0x2e;
tilePosY = actualTilePosY = 0x2c;
movOffsX = prevMovOffsX = 1;
movOffsY = prevMovOffsY = 0;
orientation = prevOrientation = LEFT;
}
}
/////////////////////////////////////////////////////////////////////////////
// red ghost AI
/////////////////////////////////////////////////////////////////////////////
void RedGhost::run()
{
// if it's going for pacman and alive
if ((substate != 0) && (state == 0)){
// check if we have to set the difficulty flags
theGame->updateDifficultyFlags();
// check if we have to move
// 0x1b is set at the tunnels
if (theGame->CRAM[Video::tilePos2ScreenCoord(actualTilePosX, actualTilePosY)] == 0x1b) {
// check if we have to move according to the movement bit pattern
movTunnelPattern = Operations::rotateLeft<UINT32, 32>(movTunnelPattern);
if ((movTunnelPattern & 0x01) == 0) return;
} else if (panicMode){
// check if we have to move according to the movement bit pattern
movPanicPattern = Operations::rotateLeft<UINT32, 32>(movPanicPattern);
if ((movPanicPattern & 0x01) == 0) return;
} else if (theGame->secondDiffFlag){
// check if we have to move according to the movement bit pattern
movDiffFlag2Pattern = Operations::rotateLeft<UINT32, 32>(movDiffFlag2Pattern);
if ((movDiffFlag2Pattern & 0x01) == 0) return;
} else if (theGame->firstDiffFlag){
// check if we have to move according to the movement bit pattern
movDiffFlag1Pattern = Operations::rotateLeft<UINT32, 32>(movDiffFlag1Pattern);
if ((movDiffFlag1Pattern & 0x01) == 0) return;
} else {
// check if we have to move according to the movement bit pattern
movNormalPattern = Operations::rotateLeft<UINT32, 32>(movNormalPattern);
if ((movNormalPattern & 0x01) == 0) return;
}
// move
move();
}
}
void RedGhost::moveInNormalState()
{
// in odd orientation changes indexes, when first difficulty flag is set,
// or if we are in demo mode, try to go to pacman position
if (((theGame->indexOrientationChanges & 0x01) == 0x01) ||
(theGame->firstDiffFlag) || (theGame->states[PLAYING]->substate != 3)){
destTilePosX = theGame->pacman->tilePosX;
destTilePosY = theGame->pacman->tilePosY;
Path::calcPath(tilePosX, tilePosY, orientation,
destTilePosX, destTilePosY,
movOffsX, movOffsY, orientation);
} else {
// searchs the best direction to choose to go to the upper left corner
destTilePosX = 0x20;
destTilePosY = 0x20;
Path::calcPath(tilePosX, tilePosY, orientation, 0x22, 0x1d, movOffsX, movOffsY, orientation);
}
}
/////////////////////////////////////////////////////////////////////////////
// animation
/////////////////////////////////////////////////////////////////////////////
void RedGhost::selectProperAnimation()
{
// in the second cutscene, change ghost animation if necessary
if (theGame->cutsceneState[1] >= 0x0a){
color = 0x1d;
sprite = (theGame->cutsceneState[1] >= 0x0c) ? 0x33 : 0x32;
} else if (theGame->cutsceneState[2] >= 1){
// change ghost animation in the third cutscene
if (theGame->cutsceneState[2] >= 3){
// set "naked" ghost sprite number
sprite = 0x0c + ((posX >> 3) & 0x01);
} else {
// set "fixed" ghost sprite number
sprite = 0x08 + theGame->ghostsAnimationFrame;
}
} else {
Ghost::selectProperAnimation();
}
}
void RedGhost::draw()
{
// if we're in third cutscene, draw naked ghost
if (theGame->cutsceneState[2] >= 3){
// draw ghost's sprites
Sprite spr1(posX, posY, sprite, color);
Sprite spr2(posX - 8, posY, sprite - 2, 0x1e);
theGame->sprites.push_back(spr1);
theGame->sprites.push_back(spr2);
// clear sprite attributes
flipX = flipY = false;
priority = 0;
} else {
Ghost::draw();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -