CEngine.cpp
上传用户:snevogroup
上传日期:2008-06-06
资源大小:432k
文件大小:13k
- #include <eikenv.h>
- #include <fbs.h>
- #include <aknutils.h>
- #include <s32file.h>
- #include <aknquerydialog.h>
- #include <bautils.h>
- #include "CEngine.h"
- #include "CGameTimer.h"
- #include "CSplash.h"
- #include "CMenu.h"
- #include "CGameTetris.h"
- #include "TetrisAppUi.h"
- #include <Tetris.rsg>
- #include "Tetris.hrh"
- #include "TScore.h"
- // sound
- #include "CWaveLoader.h"
- #include "CSoundMixer.h"
- _LIT(KFileStore,"save.dat");
- // construct and destruct
- // NewL()
- CEngine* CEngine::NewL( CGameTetris* aGame, CWindowGc& aGc, RWindow& aWindow, TDisplayMode aDisplayMode )
- {
- CEngine* self = new( ELeave )CEngine(aGame, aGc, aWindow, aDisplayMode );
- CleanupStack::PushL( self );
- self->ConstructL();
- CleanupStack::Pop( self );
- return self;
- }
- // ~
- CEngine::~CEngine()
- {
- if(iTimer)
- {
- iTimer->Cancel();
- delete iTimer;
- }
- delete iBackBufferGc;
- delete iBackBufferDevice;
- delete iBackBufferBitmap;
- delete iMenu;
- delete iBitmapUtil;
- delete iScoreTable;
- // sound
- delete iSound;
- delete iSoundBg.iData;
- delete iSoundGameOver.iData;
- delete iSoundOnClick.iData;
- delete iSoundMenu.iData;
- delete iSoundClearRow.iData;
- delete iSoundWellDone.iData;
- delete iSoundLevelUp.iData;
- }
- // ConstructL()
- void CEngine::ConstructL()
- {
- // get the draw region
- TPoint pos = iWindow.Position();
- TSize size = iWindow.Size();
- iDrawRect.SetRect(pos, size);
- // Create a new bitmap with size of view’s rect and color depth of
- // screen
- iBackBufferBitmap = new(ELeave) CFbsBitmap();
- User::LeaveIfError(iBackBufferBitmap->Create(iDrawRect.Size(), iDisplayMode));
-
- // Create bitmap device for the bitmap
- iBackBufferDevice = CFbsBitmapDevice::NewL(iBackBufferBitmap);
-
- // Create graphics context for the bitmap
- User::LeaveIfError(iBackBufferDevice->CreateContext(iBackBufferGc));
- iBitmapUtil = new(ELeave)TBitmapUtil(iBackBufferBitmap);
- // Create a menu
- iMenu = CMenu::NewL(iBackBufferGc);
- iTimer = CGameTimer::NewL(*this);
- iPause = ETrue;
- // Load sound
- CWavLoader* wavLoader = CWavLoader::NewLC();
- iSoundBg = wavLoader->LoadL(_L("bg.wav"));
- iSoundGameOver = wavLoader->LoadL(_L("gameover.wav"));
- iSoundOnClick = wavLoader->LoadL(_L("click.wav"));
- iSoundMenu = wavLoader->LoadL(_L("menu.wav"));
- iSoundClearRow = wavLoader->LoadL(_L("cleanrow.wav"));
- iSoundLevelUp = wavLoader->LoadL(_L("levelup.wav"));
- iSoundWellDone = wavLoader->LoadL(_L("welldone.wav"));
- CleanupStack::PopAndDestroy( wavLoader );
- // create sound mixer
- iSound = CSoundMixer::NewL();
- // make iSoundBg repeat itself
- iSoundBg.iRepEnd = iSoundBg.iLength;
- //iSound->Play(iSoundBg, 0, 16000, 256);
-
-
- // create score table
- iScoreTable = new (ELeave) CArrayFixSeg<TScore>(1);
- ScoreLoadL();
- iGameState = ENewSplash;
- //iGameState = EMenu;
- }
- // CEngine()
- CEngine::CEngine( CGameTetris* aGame, CWindowGc& aGc, RWindow& aWindow, TDisplayMode aDisplayMode )
- : iGame(aGame)
- , iGc( aGc )
- , iWindow( aWindow )
- , iDisplayMode( aDisplayMode )
- {}
- ///////////////////////////////////////////////////////////////////////////////////
- // Other Method
- // DoGameFrameL()
- TInt CEngine::DoGameFrameL()
- {
- // Prepare to Splash
- if(iGameState == ENewSplash)
- {
- if(!ShowSplash())
- iGameState = EMenu;
- }
- if(iGameState == EExit)
- {
- if(!ShowSplash())
- {
- CTetrisAppUi* appUi = static_cast<CTetrisAppUi*> (CEikonEnv::Static()->AppUi());
- appUi->Quit();
- //User::Exit(0); // this cann't check memory leak ,why create it ,i'm confused!
- }
- }
- // Prepare for showing the menu, used for state changing.
- if(iGameState == EMenu)
- {
- // Stop bg music
- iSound->Stop(0);
- // set Menu running frequency
- iTimer->SetTickTime(40000);
- iGameState = EMenuRunning;
- }
- // Menu running
- if(iGameState == EMenuRunning)
- {
- // show main menu
- TInt32 signal = iMenu->Command(iKey);
- switch(signal)
- {
- case 1 : // quit
- {
- iGameState = EExit;
- }break;
- case 2 : // Start new game
- {
- if(!iMusicOff)
- iSound->Play(iSoundBg, 0, 16000, 64);
- iGameState = ERunning;
- iGame->iStateRunning = 0;
- iTimer->SetTickTime(50000);
- }break;
- case 3 : // continue game
- {
- if(!iMusicOff)
- iSound->Play(iSoundBg, 0, 16000, 64);
- if(!iGame->iStateRunning)
- return 1;
- iGameState = ERunning;
- iTimer->SetTickTime(50000);
- }break;
- case 4:
- {
- iDisplayTop5 = 1;
- }break;
- case 5:
- {
- iDisplayTop5 = 0;
- }break;
- case 11 : // Set brick rotation
- {
- if(iMenu->iSetting[0] == 0)
- iGame->iStateRotateDir = -1;
- else
- iGame->iStateRotateDir = 1;
- }break;
- case 12 : // Set Sound
- {
- if(iMenu->iSetting[1] == 2) // set sound effect
- iSoundEffectOff = 0;
- else
- iSoundEffectOff = 1;
- if(iMenu->iSetting[2] == 4) // set background music
- iMusicOff = 0;
- else
- iMusicOff = 1;
- iSound->SetVolume( (iMenu->iSetting[3] - 5) * 256 / 4 );
- }break;
- case 13 : // Set Difficult
- {
- // start lines, scratching
- iGame->iStateStartLines = static_cast<TUint8> ((iMenu->iSetting[4] - 10) * 5);
- // Difficulty
- iGame->iStateDifficulty = static_cast<TUint8> (iMenu->iSetting[5] - 14);
- }break;
- default:
- {
- iGc.Activate( iWindow );
- iMenu->Draw();
- iGc.BitBlt(iDrawRect.iTl, iBackBufferBitmap);
- if(iDisplayTop5)
- ScoreDisplay();
- iGc.Deactivate();
- }break;
- }
-
- iKey = 0;
- }
-
- // game over
- if(iGameState == EGameOver)
- {
- // show Txt "game over" and some other effects
- // check if it is a new high score
- // if it is, then prompt to input user's name
- // else goto main menu directly
- iBitmapUtil->Begin(TPoint(0, 0)); // lock the heap
- TUint16* addr = (TUint16*)iBackBufferBitmap->DataAddress();
- // width and height in pixel
- TInt width = iBackBufferBitmap->SizeInPixels().iWidth;
- TInt height = iBackBufferBitmap->SizeInPixels().iHeight;
-
- if(!iControl)
- DipBlackwhite(addr, width, height);
- if(++iControl > 15)
- DipEffect(addr, width, height);
- iBitmapUtil->End(); // unlock the heap
-
- if(iControl == 35)
- {
- iControl = 0;
-
- iGameState = EMenu;
- ScoreAddL();
- return 1;
- }
- iGc.Activate( iWindow );
- iGc.BitBlt(TPoint(0, 0), iBackBufferBitmap);
-
- const CFont* font;
- font = CEikonEnv::Static()->LegendFont();
- iGc.UseFont(font);
- iGc.SetPenColor(KRgbRed);
- iGc.DrawText(_L("Game Over"), TPoint(65, 100));
-
- iGc.DiscardFont();
- iGc.Deactivate();
- iKey = 0;
- }
- // running
- if(iGameState == ERunning)
- {
- TInt8 state = iGame->Run();
- if(state == 1) // game over
- {
- if(!iSoundEffectOff)
- iSound->Play(iSoundGameOver, 1, 16000, 64);
- iGameState = EGameOver;
- return 1;
- }
- // draw screen
- if(iGame->Command(iKey) || state == 2)
- {
- iGc.Activate( iWindow );
-
- iGame->Draw(iBackBufferGc);
- iGc.BitBlt(iDrawRect.iTl, iBackBufferBitmap);
- iGc.Deactivate();
- }
- iKey = 0;
- // play sound effect
- if(!iSoundEffectOff)
- {
- // only play one sound effect ,there is a priority
- if(iGame->iStateLevelUp)
- {
- iSound->Play(iSoundLevelUp, 1, 16000, 64);
- iGame->iStateLevelUp = 0;
- //return 1;
- }
- if(iGame->iStateWellDone)
- {
- iSound->Play(iSoundWellDone, 2, 16000, 64);
- iGame->iStateWellDone = 0;
- }
- if(iGame->iStateClearRow)
- {
- iSound->Play(iSoundClearRow, 3, 16000, 64);
- iGame->iStateClearRow = 0;
- //return 1;
- }
- }
- }
- return ETrue;
- }
- // Start()
- void CEngine::Start()
- {
- if( !iPause )
- return;
- iPause = EFalse;
- iTimer->Start();
- iSound->Resume();
- }
- // Stop()
- void CEngine::Stop()
- {
- if( iPause )
- return;
- iPause = ETrue;
- iTimer->Cancel();
- iSound->Pause();
- }
- // Pause()
- void CEngine::Pause()
- {
- if(iPause)
- Start();
- else
- Stop();
- }
- // Command()
- void CEngine::Command(TInt aCommand)
- {
- if(aCommand == 'q')
- {
- if(iGameState == ERunning || iGameState == EMenuRunning)
- iGameState = EMenu;
- else
- return;
- }
- if(aCommand == '0' && iGameState == ERunning)
- Pause();
- iKey = aCommand;
- if(iSoundEffectOff)
- return;
- if(iGameState == EMenuRunning)
- {
- switch(iKey)
- {
- case EStdKeyDevice5:
- case '5':
- case 63557:
- {
- iSound->Play(iSoundOnClick, 2, 16000, 64);
- }break;
-
- case EKeyUpArrow : // UP
- case '2' :
- case EKeyDownArrow : // Down
- case '8' :
- case EKeyLeftArrow : // Left
- case '4' :
- case EKeyRightArrow : // Right
- case '6' :
- {
- iSound->Play(iSoundMenu, 3, 16000, 64);
- }break;
- default:
- break;
- }
- }
- }
- // ShowSplash()
- TBool CEngine::ShowSplash()
- {
- if(!iSplash)
- {
- iSplash = CSplash::NewL(iGc, iWindow);
- iTimer->SetTickTime(100000);
- }
- else if(!iSplash->Draw())
- {
- delete iSplash;
- iSplash = NULL;
- return 0; // stop splashing
- }
- return 1; // keep splashing
- }
- // DipEffect()
- void CEngine::DipEffect(TUint16* aAddr, TInt aWidthInPixel, TInt aHeightInPixel)
- {
- TInt i, j;
- TUint16* index;
- for(i = 0; i < aHeightInPixel; i++)
- {
- index = aAddr + aWidthInPixel * i; // get address of each row
- for(j = 0; j < aWidthInPixel; j++)
- {
- TInt8 r = static_cast<TInt8> (*index & 0x00f);
- TInt8 g = static_cast<TInt8> ((*index & 0x0f0) >> 4);
- TInt8 b = static_cast<TInt8> ((*index & 0xf00) >> 8);
- r--;
- g--;
- b--;
-
- (r < 0) ? *index = 0 : *index = r;
- (g < 0) ? *index &= 0xf0f : *index |= g << 4;
- (b < 0) ? *index &= 0x0ff : *index |= b << 8;
- //(r > 0xf) ? *index = 0xf : *index = r;
- //(g > 0xf) ? *index |= 0x0f0 : *index |= g << 4;
- //(b > 0xf) ? *index |= 0xf00 : *index |= b << 8;
- index ++;
- }
- }
- }
- void CEngine::DipBlackwhite(TUint16* aAddr, TInt aWidthInPixel, TInt aHeightInPixel)
- {
- TInt i, j;
- TUint16* index;
- for(i = 0; i < aHeightInPixel; i++)
- {
- index = aAddr + aWidthInPixel * i; // get address of each row
- for(j = 0; j < aWidthInPixel; j++)
- {
- *index = *index > 0x800 ? 0xfff : 0;
- index ++;
- }
- }
- }
- // method deal with score
- void CEngine::ScoreLoadL()
- {
- // in my opinion, this can only be used in real handset, not emulator
- TFileName fileName( KFileStore );
- CompleteWithAppPath( fileName );
- if(!BaflUtils::FileExists(CEikonEnv::Static()->FsSession(), fileName))
- {
- ScoreSaveL();
- return;
- }
- CFileStore* store = CDirectFileStore::OpenLC(CEikonEnv::Static()->FsSession(), fileName, EFileRead);
- RStoreReadStream stream;
- stream.OpenLC(*store,store->Root());
-
- TScore sc;
- TInt i, count=stream.ReadInt32L();
- for(i = 0; i < count; i++)
- {
- stream >> sc;
- iScoreTable->AppendL(sc);
- }
- CleanupStack::PopAndDestroy(2); // (store and stream)
- }
- void CEngine::ScoreAddL()
- {
- // first clear score table
- ScoreReset();
- // load score
- ScoreLoadL();
-
- // check if the score is a new Top5 score
- if(iScoreTable->Count() == TopNum) // not full
- if(iGame->iStateScore <= -iScoreTable->At(TopNum - 1).iValue)
- return;
-
- TBuf<15> name;
- CAknTextQueryDialog* dialog = CAknTextQueryDialog::NewL(name);
- if(!dialog->ExecuteLD(R_INPUT_USERNAME_DIALOG))
- return;
- // new score
- TScore newScore(iGame->iStateScore, name);
- // Insert the element in the Score table (using an Integer key on iValue)
- TKeyArrayFix byScore(_FOFF(TScore, iValue), ECmpTInt);
- iScoreTable->InsertIsqAllowDuplicatesL(newScore, byScore);
-
- // Remove the last player from the table if necessary and compress the table
- if(iScoreTable->Count() > TopNum)
- iScoreTable->Delete(TopNum);
- iScoreTable->Compress();
- // save the score
- ScoreSaveL();
- }
- void CEngine::ScoreSaveL()
- {
- // in my opinion, this can only be used in real handset, not emulator
- TFileName fileName( KFileStore );
- CompleteWithAppPath( fileName );
- CFileStore* store = CDirectFileStore::ReplaceLC(CEikonEnv::Static()->FsSession(), fileName, EFileWrite);
- store->SetTypeL(KDirectFileStoreLayoutUid);
- // Create the hi-score stream
- RStoreWriteStream stream;
- TStreamId id = stream.CreateLC(*store);
- // Write the number of score table entries in the store
- TInt count= iScoreTable->Count();
- stream.WriteInt32L(count);
- // Then write each entry
- for(TInt i = 0; i < count; i++)
- {
- stream << iScoreTable->At(i);
- }
- // Commit the changes to the stream
- stream.CommitL();
- CleanupStack::PopAndDestroy();
- // Set the stream in the store and commit the store
- store->SetRootL(id);
- store->CommitL();
- CleanupStack::PopAndDestroy();
- }
- void CEngine::ScoreDisplay()
- {
- // note this don't has iGc.Activate( iWindow ); & iGc.Deactivate();
- //iGc.Activate( iWindow );
- const CFont* font;
- font = CEikonEnv::Static()->TitleFont();
- iGc.UseFont(font);
- iGc.SetPenColor(KRgbWhite);
- iGc.DrawText(_L("Top 5"), TPoint(75, 30));
- for(TInt i = 0; i < iScoreTable->Count(); i++)
- {
- iGc.DrawText(iScoreTable->At(i).iName, TPoint(30, 60 + 30*i));
- TBuf16<10> score;
- score.Num(-iScoreTable->At(i).iValue);
- iGc.DrawText(score, TPoint(130, 60 + 30*i));
- }
-
- iGc.DiscardFont();
- //iGc.Deactivate();
- }
- void CEngine::ScoreReset()
- {
- iScoreTable->Delete(0, iScoreTable->Count());
- }