📄 game.cpp
字号:
// -----------------------------------------------------------------------------------------
//
// render scene
//
// -----------------------------------------------------------------------------------------
m_pScene->Render(m_pScene->Root(), m_pCam);
}
// ----------------------------------------------------------------------------------------------------------
//
// Render game over
//
// ----------------------------------------------------------------------------------------------------------
void CGame::RenderGameOver()
{
if (m_kSELECT || m_kCLEAR)
{
CleanUpLevel();
m_dwFrame = 0;
m_jGameStatus = STATUS_INTRO;
return;
}
// render game over sprite
m_pSprGameOver->Draw((m_pEngine->ScreenWidth()-m_pSprGameOver->Width())>>1, (m_pEngine->ScreenHeight()-m_pSprGameOver->Height())>>1);
char szNumber[16];
// remaining flags
SPRINTF(szNumber, "%02u", m_jFlagsLeft);
m_pSprNumbers->DrawNumber(4,m_pEngine->ScreenHeight()-8, szNumber);
// current level
SPRINTF(szNumber, "%02u", m_jLevel);
m_pSprLevel->Draw(4,4);
m_pSprNumbers->DrawNumber(4,10, szNumber);
// current score
SPRINTF(szNumber, "%06u", m_dwScore);
m_pSprScore->Draw(m_pEngine->ScreenWidth()-m_pSprScore->Width()-4,4);
m_pSprNumbers->DrawNumber(m_pEngine->ScreenWidth()-33,10, szNumber);
// "press start"
m_pSprPressStart->Draw((m_pEngine->ScreenWidth()-m_pSprPressStart->Width())>>1, m_pEngine->ScreenHeight()-m_pSprPressStart->Height()-4);
}
// ----------------------------------------------------------------------------------------------------------
//
// Render a game frame
//
// ----------------------------------------------------------------------------------------------------------
void CGame::RenderGame()
{
// -----------------------------------------------------------------------------------------
//
// player movement
//
// -----------------------------------------------------------------------------------------
if (m_kCLEAR)
{
CleanUpLevel();
m_dwFrame = 0;
m_jGameStatus = STATUS_INTRO;
return;
}
byte xx;
if (m_dwFrame > GET_READY_DELAY)
{
//
// 10x10 grid alignment
//
word gdx, gdz;
boolean bMove = FALSE, bAligned = FALSE;
gdx = XTOI(m_pPlayer->Position()[0]) % 10;
gdz = XTOI(m_pPlayer->Position()[2]) % 10;
if (!m_jTurnLeft && !m_jTurnRight)
bMove = TRUE; //m_kUP;
if (gdx || gdz)
{
bMove = TRUE;
bAligned = FALSE;
}
else bAligned = TRUE;
// calculate current centered grid position of player
word gsx, gsz, gsp;
gsx = (XTOI(m_pPlayer->Position()[0]) + 5) / 10;
gsz = (XTOI(m_pPlayer->Position()[2]) + 5) / 10;
gsp = gsx + gsz * GRID_SIZE;
//
// check collision with enemy
//
if (m_pLevelGrid[gsp] == 4)
{
// collided with enemy
m_pSndBang->Play();
m_DieImpulse = DIE_IMPULSE;
m_jGameStatus = STATUS_DYING;
}
//
// turning
//
if (bAligned)
{
//
// automan style player turns
//
boolean bCanLeft, bCanRight;
word ang = XTOI(m_pPlayer->Rotation()[1]);
switch (ang)
{
case 0:
{
bCanLeft = (m_pLevelGrid[gsp-1] != 0);
bCanRight = (m_pLevelGrid[gsp+1] != 0);
break;
}
case 180:
{
bCanLeft = (m_pLevelGrid[gsp+1] != 0);
bCanRight = (m_pLevelGrid[gsp-1] != 0);
break;
}
case 90:
{
bCanLeft = (m_pLevelGrid[gsp+GRID_SIZE] != 0);
bCanRight = (m_pLevelGrid[gsp-GRID_SIZE] != 0);
break;
}
case 270:
{
bCanLeft = (m_pLevelGrid[gsp-GRID_SIZE] != 0);
bCanRight = (m_pLevelGrid[gsp+GRID_SIZE] != 0);
break;
}
}
// ### force no constraints in player rotation
bCanLeft = bCanRight = TRUE;
if (m_kDOWN)
{
if (!m_jTurnLeft && !m_jTurnRight && !m_klastLEFT)
{
m_jTurnLeft = 180;
m_klastLEFT = TRUE;
bMove = FALSE;
}
}
if (m_kLEFT && bCanLeft)
{
if (!m_jTurnLeft && !m_jTurnRight && !m_klastLEFT)
{
m_jTurnLeft = 90;
m_klastLEFT = TRUE;
bMove = FALSE;
}
}
else m_klastLEFT = FALSE;
if (m_kRIGHT && bCanRight)
{
if (!m_jTurnRight && !m_jTurnLeft && !m_klastRIGHT)
{
m_jTurnRight = 90;
m_klastRIGHT = TRUE;
bMove = FALSE;
}
}
else m_klastRIGHT = FALSE;
if (m_jTurnLeft)
{
m_pPlayer->AddRotation(0, ITOX(PLAYER_TURN_SPEED), 0);
m_jTurnLeft -= PLAYER_TURN_SPEED;
}
else m_klastLEFT = FALSE;
if (m_jTurnRight)
{
m_pPlayer->AddRotation(0, -ITOX(PLAYER_TURN_SPEED), 0);
m_jTurnRight -= PLAYER_TURN_SPEED;
}
else m_klastRIGHT = FALSE;
}
m_pPlayer->UpdateDirection();
//
// movement and collision detection
//
int spx=0, spz=0;
// because lack of precision, select a speed based on orthogonal directions
// first we initialize spx and spz to just the direction of movement, further ahead
// we'll multiply then by the PLAYER_MOVE_SPEED.
switch (XTOI(m_pPlayer->Rotation()[1]))
{
case 0:
{
spx = 0;
spz = 1;
break;
}
case 90:
{
spx = -1;
spz = 0;
break;
}
case 180:
{
spx = 0;
spz = -1;
break;
}
case 270:
{
spx = 1;
spz = 0;
break;
}
}
// end positions (used later)
word gex, gez, gep;
// clear current position in the level grid
m_pLevelGrid[gsp] = 5; // put "track" there
//
// check if can move to the cell ahead
//
if (bAligned)
{
gex = (XTOI(m_pPlayer->Position()[0]) + spx*10) / 10;
gez = (XTOI(m_pPlayer->Position()[2]) - spz*10) / 10;
gep = gex + gez * GRID_SIZE;
if (m_pLevelGrid[gep] == 0) bMove = FALSE;
}
// update speed to correct one
spx = ITOX(spx * PLAYER_MOVE_SPEED);
spz = ITOX(spz * PLAYER_MOVE_SPEED);
if (bMove)
{
// end grid position
gex = (XTOI(m_pPlayer->Position()[0] + spx) + 5) / 10;
gez = (XTOI(m_pPlayer->Position()[2] - spz) + 5) / 10;
gep = gex + gez * GRID_SIZE;
//
// check end position
//
switch (m_pLevelGrid[gep])
{
case 0:
{
// wall
break;
}
case 1:
{
// own player
m_pPlayer->AddTranslation(spx, 0, -spz);
break;
}
case 2:
{
// special flag
m_pSndSpecialBonus->Play();
m_pPlayer->AddTranslation(spx, 0, -spz);
m_pPtrGrid[gep]->AddTranslation(0,ITOX(1000),0);
m_dwScore += (1 + m_jFlagsCount - m_jFlagsLeft) * 20;
m_jFlagsLeft--;
break;
}
case 3:
{
// normal flag
m_pSndBonus->Play();
m_pPlayer->AddTranslation(spx, 0, -spz);
m_pPtrGrid[gep]->AddTranslation(0,ITOX(1000),0);
m_dwScore += (1 + m_jFlagsCount - m_jFlagsLeft) * 10;
m_jFlagsLeft--;
break;
}
case 5:
{
// track
m_pPlayer->AddTranslation(spx, 0, -spz);
break;
}
}
}
if (!m_jFlagsLeft)
{
// passed level
m_pSndBonus->Stop();
m_pSndSpecialBonus->Stop();
m_jGameStatus = STATUS_PASSLEVEL;
}
// recalculate current grid position of player
gsx = (XTOI(m_pPlayer->Position()[0]) + 5) / 10;
gsz = (XTOI(m_pPlayer->Position()[2]) + 5) / 10;
gsp = gsx + gsz * GRID_SIZE;
// put player on the new position in level grid
m_pLevelGrid[gsp] = 1;
// -----------------------------------------------------------------------------------------
//
// third person camera
//
// -----------------------------------------------------------------------------------------
m_pCam->TranslateTo(m_pPlayer->Position()[0] - m_pPlayer->Direction()[0]*25,ITOX(20), m_pPlayer->Position()[2] + m_pPlayer->Direction()[2]*25);
VectorCopy(m_pPlayer->Rotation(), m_pCam->Rotation());
m_pCam->AddRotation(ITOX(-45), 0, 0);
m_pCam->UpdateDirection();
// -----------------------------------------------------------------------------------------
//
// enemies movement
//
// -----------------------------------------------------------------------------------------
for (xx=0; xx<m_jEnemyCount; xx++)
{
boolean bEnemyTurned = FALSE;
//
// 10x10 grid alignment
//
gdx = XTOI(m_pEnemies[xx]->Position()[0]) % 10;
gdz = XTOI(m_pEnemies[xx]->Position()[2]) % 10;
if (gdx || gdz)
bAligned = FALSE;
else
bAligned = TRUE;
// because lack of precision, select a speed based on orthogonal directions
// first we initialize spx and spz to just the direction of movement, further ahead
// we'll multiply then by the MOVE_SPEED.
switch (XTOI(m_pEnemies[xx]->Rotation()[1]))
{
case 0:
{
spx = 0;
spz = 1;
break;
}
case 90:
{
spx = -1;
spz = 0;
break;
}
case 180:
{
spx = 0;
spz = -1;
break;
}
case 270:
{
spx = 1;
spz = 0;
break;
}
}
// calculate current centered grid position of enemy
gsx = (XTOI(m_pEnemies[xx]->Position()[0]) + 5) / 10;
gsz = (XTOI(m_pEnemies[xx]->Position()[2]) + 5) / 10;
gsp = gsx + gsz * GRID_SIZE;
//
// check if can move to the cell ahead
//
if (bAligned)
{
gex = (XTOI(m_pEnemies[xx]->Position()[0]) + spx*10) / 10;
gez = (XTOI(m_pEnemies[xx]->Position()[2]) - spz*10) / 10;
gep = gex + gez * GRID_SIZE;
//
// check end position
//
switch (m_pLevelGrid[gep])
{
case 0: // wall
case 4: // other enemy
{
// turn around
TurnEnemy(xx);
bEnemyTurned = TRUE;
break;
}
case 2: // special flag
case 3: // flag
case 5:
{
// track
// first check if it should turn in an open corner
if (m_jEnemyStepsToTurn[xx]) m_jEnemyStepsToTurn[xx]--;
if (!m_jEnemyStepsToTurn[xx])
{
m_jEnemyTurns ^= 255;
word ang = XTOI(m_pEnemies[xx]->Rotation()[1]);
switch (ang)
{
case 0:
case 180:
{
if (m_pLevelGrid[gsp-1] == 5 || m_pLevelGrid[gsp+1] == 5)
{
TurnEnemy(xx);
bEnemyTurned = TRUE;
m_jEnemyStepsToTurn[xx] = ENEMY_STEPS_TURN;
}
break;
}
case 90:
case 270:
{
if (m_pLevelGrid[gsp-GRID_SIZE] == 5 || m_pLevelGrid[gsp+GRID_SIZE] == 5)
{
TurnEnemy(xx);
bEnemyTurned = TRUE;
m_jEnemyStepsToTurn[xx] = ENEMY_STEPS_TURN;
}
break;
}
}
}
break;
}
}
}
if (!bEnemyTurned)
{
// restore old tile value in the level grid
m_pLevelGrid[gsp] = m_jOldValue[xx];
// move enemy
spx = ITOX(spx * ENEMY_MOVE_SPEED);
spz = ITOX(spz * ENEMY_MOVE_SPEED);
m_pEnemies[xx]->AddTranslation(spx, 0, -spz);
// recalculate current grid position of enemy
gsx = (XTOI(m_pEnemies[xx]->Position()[0]) + 5) / 10;
gsz = (XTOI(m_pEnemies[xx]->Position()[2]) + 5) / 10;
gsp = gsx + gsz * GRID_SIZE;
// save old tile value
m_jOldValue[xx] = m_pLevelGrid[gsp];
// put enemy there
m_pLevelGrid[gsp] = 4;
}
}
m_dwFrame++;
} // end if (m_dwFrame > ...)
// -----------------------------------------------------------------------------------------
//
// flags animation
//
// -----------------------------------------------------------------------------------------
for (xx=0; xx<m_jFlagsCount; xx++)
m_pFlags[xx]->AddRotation(0,ITOX(4),0);
// -----------------------------------------------------------------------------------------
//
// render scene
//
// -----------------------------------------------------------------------------------------
m_pScene->Render(m_pScene->Root(), m_pCam);
// -----------------------------------------------------------------------------------------
//
// show some feedback text
//
// -----------------------------------------------------------------------------------------
char szNumber[16];
// remaining flags
SPRINTF(szNumber, "%02u", m_jFlagsLeft);
m_pSprNumbers->DrawNumber(4,m_pEngine->ScreenHeight()-8, szNumber);
// current level
SPRINTF(szNumber, "%02u", m_jLevel);
m_pSprLevel->Draw(4,4);
m_pSprNumbers->DrawNumber(4,10, szNumber);
// current score
SPRINTF(szNumber, "%06u", m_dwScore);
m_pSprScore->Draw(m_pEngine->ScreenWidth()-m_pSprScore->Width()-4,4);
m_pSprNumbers->DrawNumber(m_pEngine->ScreenWidth()-33,10, szNumber);
// lifes
for (xx=1; xx<m_jLifes; xx++)
m_pSprLive->Draw(m_pEngine->ScreenWidth()-(m_pSprLive->Width()+1)*xx-4,m_pEngine->ScreenHeight()-m_pSprLive->Height()-4);
if (m_dwFrame <= GET_READY_DELAY)
{
//
// get ready animation
//
m_pCam->TranslateTo(m_pPlayer->Position()[0] - m_pPlayer->Direction()[0]*25,ITOX(20), m_pPlayer->Position()[2] + m_pPlayer->Direction()[2]*25);
VectorCopy(m_pPlayer->Rotation(), m_pCam->Rotation());
m_pCam->AddRotation(ITOX(-45), 0, 0);
m_pCam->UpdateDirection();
m_pSprGetReady->Draw((m_pEngine->ScreenWidth()-m_pSprGetReady->Width())>>1, (m_pEngine->ScreenHeight()-m_pSprGetReady->Height())>>1);
m_dwFrame++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -