📄 mopoidgameengine.cpp
字号:
if (iThisFrameStep > 1)
iThisFrameStep = 1;
iLastFrameTime = curFrameTime;
}
// -----------------------------------------------------------------------
void CMopoidGameEngine::AnimatePanel()
{
iPanel.KeyboardMove(iKeyHandler.GetDirection());
// Move the panel according to its speed.
iPanel.ConvertToPos(iThisFrameStep);
}
// -----------------------------------------------------------------------
void CMopoidGameEngine::AnimateBall()
{
// Store the sound we're about to play so that we will only start one
// sound in case more than one things happen at the same time.
TMopoidSounds playSound = ENumSounds;
// Move to a new temponary pos
if (iBall.Move(iThisFrameStep))
playSound = ESoundHit;
// Check collision with panel
if (iBall.CheckPanelCollision(iPanel, iThisFrameStep))
playSound = ESoundBounce;
// Check collision with bricks
TBrick::TBrickType brickColl = iBall.CheckBrickCollision(iGrid, iThisFrameStep, TBall::ECenter);
// Also do a collision check for both sides of the ball, if no hit was found yet.
// As we only handle one collision at once, we still check the center of the ball first to make
// sure the main brick is hit when it's not clear which one is the main target.
if (brickColl == TBrick::EBrickInactive)
{
brickColl = iBall.CheckBrickCollision(iGrid, iThisFrameStep, TBall::ELeft);
if (brickColl == TBrick::EBrickInactive)
{
brickColl = iBall.CheckBrickCollision(iGrid, iThisFrameStep, TBall::ERight);
}
}
// Check if a brick has been removed.
if (brickColl == TBrick::EBrickNormal)
{
// Brick has been destroyed!
iSettings.iScore += 25;
iSettings.iBricksRemaining --;
if (iSettings.iBricksRemaining == 0)
{
// Played through level...
if (iSettings.iLevel < NUM_LEVELS)
{
// We've got another level...
iSettings.iGameStatus = TMopoidSettings::ENewLevel;
iSettings.iLevel ++;
iSettings.iScore += 50;
iSettings.iBricksRemaining = iGrid.LoadLevel(iLevels->iLevels[iSettings.iLevel-1]);
PauseGame();
ResetBallAndPanel();
}
else
{
// Played through game
iSettings.iGameStatus = TMopoidSettings::EFinished;
iSettings.iScore += 150;
PauseGame();
}
}
}
// If any brick was hit (doesn't matter if it was destroyed), play a sound
if (brickColl != TBrick::EBrickInactive)
playSound = ESoundHit;
// Let's play the sound!
if (playSound != ENumSounds)
{
TRAPD(error, iSoundManager->PlayL(playSound));
}
// Check if we're still alive
if (iBall.CheckDeath(iPanel))
{
// No, the ball has passed below the lower border.
PauseGame();
iSettings.iLives --;
iSettings.iScore -= 100;
// Check if game is over.
if (iSettings.iLives == 0)
iSettings.iGameStatus = TMopoidSettings::EDied;
else
iSettings.iGameStatus = TMopoidSettings::ELifeLost;
}
// Copy temp pos to real pos
iBall.ConvertToPos();
}
// -----------------------------------------------------------------------
void CMopoidGameEngine::DrawFrame() const
{
// Clear back buffer
iBackBufferBmpGc->SetPenStyle( CGraphicsContext::ENullPen );
iBackBufferBmpGc->SetBrushColor( KRgbBlack );
iBackBufferBmpGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
iBackBufferBmpGc->DrawRect( TRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) );
// Set brush style to none so that transparency is drawn as transparent and not with a color (!)
iBackBufferBmpGc->SetBrushStyle( CGraphicsContext::ENullBrush );
// Put ball first, so that it is behind other objects should it be that at any time
TPoint ballSpritePos(iBall.iPos.iX - iBall.iSizeHalf.iWidth, iBall.iPos.iY - iBall.iSizeHalf.iHeight);
iBackBufferBmpGc->BitBltMasked(ballSpritePos, iSpriteHandler->GetSprite(MopoidShared::ESpriteBall), iBall.iSize, iSpriteHandler->GetSprite(MopoidShared::ESpriteBallM), EFalse);
// Draw bricks
for (TInt x=0; x<GRID_COLS; x++)
{
for (TInt y=0; y<GRID_ROWS; y++)
{
// Check if there is a brick to draw at this position
if (iGrid.DrawBrickAtPos(x, y))
{
// Draw according bitmap.
MopoidShared::TSpriteIds spriteId;
switch (iGrid.GetBrickTypeAtPos(x, y))
{
case TBrick::EBrickNormal:
spriteId = MopoidShared::ESpriteBrickNormal;
break;
case TBrick::EBrickDouble:
spriteId = MopoidShared::ESpriteBrickDouble;
break;
case TBrick::EBrickIndestructible:
spriteId = MopoidShared::ESpriteBrickIndestructible;
break;
default:
spriteId = MopoidShared::ESpriteBrickNormal;
}
iBackBufferBmpGc->BitBlt(iGrid.ConvertGridToXY(x,y), iSpriteHandler->GetSprite(spriteId));
}
}
}
// Put Panel
iBackBufferBmpGc->BitBltMasked(iPanel.iPos, iSpriteHandler->GetSprite(MopoidShared::ESpritePanel), iPanel.iSize, iSpriteHandler->GetSprite(MopoidShared::ESpritePanelM), EFalse);
// HUD
iBackBufferBmpGc->SetPenStyle(CGraphicsContext::ESolidPen);
iBackBufferBmpGc->SetPenColor(KRgbRed);
iBackBufferBmpGc->UseFont(CEikonEnv::Static()->AnnotationFont());
TBuf<30> tempStr;
// Score
CEikonEnv::Static()->ReadResource(tempStr, RS_R_SCORE);
tempStr.AppendNum(iSettings.iScore);
iBackBufferBmpGc->DrawText(tempStr, TPoint(5, 25));
// High Score
CEikonEnv::Static()->ReadResource(tempStr, RS_R_HIGHSCORE);
tempStr.AppendNum(iSettings.iHighScore);
iBackBufferBmpGc->DrawText(tempStr, TPoint(5, 38));
// Level
CEikonEnv::Static()->ReadResource(tempStr, RS_R_LEVEL);
tempStr.AppendNum(iSettings.iLevel);
iBackBufferBmpGc->DrawText(tempStr, TRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 25, CGraphicsContext::ERight, 3);
// Lives
CEikonEnv::Static()->ReadResource(tempStr, RS_R_LIVES);
tempStr.AppendNum(iSettings.iLives);
iBackBufferBmpGc->DrawText(tempStr, TRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 38, CGraphicsContext::ERight, 3);
// Draw a line between status messages and play area
iBackBufferBmpGc->DrawLine(TPoint(0, BORDER_TOP), TPoint(SCREEN_WIDTH, BORDER_TOP));
// Title
// TODO: Uncomment code block
iBackBufferBmpGc->SetPenColor(TRgb(240, 200, 50));
CEikonEnv::Static()->ReadResource(tempStr, RS_R_TITLE);
iBackBufferBmpGc->DrawText(tempStr, TRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 11, CGraphicsContext::ECenter, 3);
// Status messages
TBool displayStatus = ETrue;
switch (iSettings.iGameStatus)
{
case TMopoidSettings::ELifeLost:
{
CEikonEnv::Static()->ReadResource(tempStr, RS_R_LIFELOST);
}
break;
case TMopoidSettings::EDied:
{
CEikonEnv::Static()->ReadResource(tempStr, RS_R_GAMEOVER);
}
break;
case TMopoidSettings::EStarted:
case TMopoidSettings::ENewLevel:
{
CEikonEnv::Static()->ReadResource(tempStr, RS_R_ENTERLEVEL);
tempStr.AppendNum(iSettings.iLevel);
break;
}
case TMopoidSettings::EFinished:
{
CEikonEnv::Static()->ReadResource(tempStr, RS_R_FINISHED);
}
break;
default:
displayStatus = EFalse;
}
// If there is a status message to display, show it to the user.
if (displayStatus)
{
iBackBufferBmpGc->SetPenColor(KRgbRed);
iBackBufferBmpGc->UseFont(CEikonEnv::Static()->TitleFont());
iBackBufferBmpGc->DrawText(tempStr, TRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 125, CGraphicsContext::ECenter);
}
}
// -----------------------------------------------------------------------
void CMopoidGameEngine::PauseGame()
{
// Update highscore
if (iSettings.iScore > iSettings.iHighScore)
{
iSettings.iHighScore = iSettings.iScore;
TRAPD(err, SaveGameProgressL());
}
iSettings.iGamePaused = ETrue;
// Stop the timer. The active object will be stopped by the DoFrame-function
// after the next update.
StopTimer();
}
// -----------------------------------------------------------------------
void CMopoidGameEngine::ResumeGameL()
{
if (iSettings.iGameStatus == TMopoidSettings::EFinished ||
iSettings.iGameStatus == TMopoidSettings::EDied)
{
// Don't resume the game, we've already played through it / we're dead.
return;
}
iLastFrameTime.UniversalTime();
iSettings.iGamePaused = EFalse;
// If we were waiting for the user to do something, switch back to
// the normal play-mode
if (iSettings.iGameStatus == TMopoidSettings::EStarted ||
iSettings.iGameStatus == TMopoidSettings::ENewLevel ||
iSettings.iGameStatus == TMopoidSettings::ELifeLost)
{
ResetBallAndPanel();
iSettings.iGameStatus = TMopoidSettings::EPlaying;
}
// Start the point-decreasing + backlight timer
StartTimerL();
// re-activate our active object
iUpdateAO->Reactivate();
}
//------------------------------------------------------------------------------
void CMopoidGameEngine::SaveGameProgressL()
{
// TODO: Add the path to the filename
// ...
// TODO: Open a file store
// ...
// TODO: Create the stream
// ...
// TODO: Write file version number
// ...
// TODO: Write highscore
// ...
// TODO: Write sound level
// ...
// TODO: Commit the changes to the stream
// ...
// TODO: Set the stream in the store and commit the store
// ...
}
//------------------------------------------------------------------------------
void CMopoidGameEngine::LoadGameProgressL()
{
// TODO: Add the path to the filename
// ...
// TODO: Open file
// ...
// TODO: Open the data stream inside the store
// ...
// TODO: Read all the data
// ...
// TODO: Delete all the remaining stuff on the cleanup stack
// (store, stream)
// ...
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -