Andreas Jakl munkafüzete alapján készítette Szabóné Nacsa Rozália
Okos telefonok erős processzor nagyméretű kijelző viszonylag nagy memória információ kezelő programok egyéni alkalmazások egyszerű kezelhetőség megbízhatóság erőforrásaival nem pazarló (memória, szolgáltatások, energia fogyasztás) gyors reakcióidő folyamatos üzemmód
Elvárosok megbízható nincs adatvesztés nem dobja el a vonalat optimális a memória felhasználás nincs memória szivárgás minden hibát „értelmesen” kezel nyitott a külső fejlesztések irányába
Symbian operációs rendszer SIBO – Psion Computers (1980) EPOC - irodai kisszámítógép ( ) Symbian OS – (alapítva 1998 : Nokia, Motorola, Psion, Ericsson, 2002: Sony-Ericssson, Siemens) Mérföldkő: 2000-ben megjelent 6.0-ás verzió
S60 áttekintése
1.Perl 5.6.x (Set the pathvariable!) – 5.8 /5.10 nem jó! MSWin32-x86.msi 2.SDK(s)(S60 3rd Ed. MR + újabb) 60_Platform_SDKs/ 3.Carbide.c Developer Edition (vagy újabb) html Eszközök telepítése a felsorolás sorrendjében történjen Az eszközöket ugyanarra a meghajtóra kell telepíteni, ahol az SDK van. (javasolt: C:\. Ne használjon hálózati meghajtót! Fájl nevekben ne hasnáljon helyközt.) Előkészületek
Segédanyagok SDK online dokumentáció: C:\S60\devices\S60_3rd_FP2_SDK_v1.1\docs\eclipse.exe
Carbide.c++ Szoftver frissítés
S60 és UIQ Hardware HW adaptation Symbian OS UI framework UI implementation Application suites S 60 UIQ MOAP
Új projekt létrehozása
GUI alkalmazások felépítése
„.h”.rsg.hrh.rh.rls.cpp.rss.bmp C++ fordító.obj.lib.exe;.dll Erőforrás fordító Bmp konverter.mbm.rss.bmp Bmp konverter linker Aif fordító.rsc.pkg.mbm.aif Sis készítő.sis A fordítás és szerkesztés folyamata
A projekt tesztelése
Hibakezelés Window -> Preferences -> Carbide.c++ -> Build
Fájlok törlése
Futtatás
A képernyő felépítése
A status panel felépítése
Menüpontok megadása
Menüpont paraméterezése EAknCmdExit: Előre definiált parancs azonosító
Címke felirat módosítása Dupla katt.
„About” infó megjelenítése
„About” ablak paraméterezése
Eseménykezelés
Eseménykezelő eljárás megadása TBool CMopoidContainerView::HandleAboutMenuItemSelectedL( TInt aCommand ) { // TODO: implement selected event handler RunNoteAboutL(); return ETrue; } TBool CMopoidContainerView::HandleAboutMenuItemSelectedL( TInt aCommand ) { // TODO: implement selected event handler RunNoteAboutL(); return ETrue; }
new (Eleave) operátor CCat* InitalizeCatL() { CCat* cat = new (ELeave) CCat(); cat->Initialize(); return(cat); } CCat* InitalizeCat() { CCat* cat = new CCat(); if(cat) { cat->Initialize(); return(cat); } else return (NULL); }
Kivételkezelési konvenciók C++ Symbian Throw Catch Függvénydeklaráció: Throw new operátor: nullát ad vissza User::Leave TRAP, TRAPD záró L new (ELeave): kivételt dob, ha nincs memória
Leave mechanizmus CCat* InitalizeCatL() { CCat* cat = new (ELeave) CCat(); cat->Initialize(); return(cat); } CCat* InitalizeCatL() { CCat* cat = new (ELeave) CCat(); cat->InitializeL(); return(cat); } TInt UseCat(CCat* aCat); CCat* InitalizeCatL() { CCat* cat = new (ELeave) CCat(); CleanUpStack::PushL(cat); cat->InitializeL(); User::LeaveIfError(UseCat(cat)); CleanUpStack::PopCat); return(cat); } Nem biztonságos! Leaveléskor a CleanUpStack-be bejegyzett objektumok tárhelye felszabadul.
Leavelő függvények: * LC, * LD, * L /** * Show the popup note for noteAbout aOverrideText optional override text */ void CMopoidContainerView::RunNoteAboutL( const TDesC* aOverrideText ) { CAknInformationNote* note = new ( ELeave ) CAknInformationNote(); if ( aOverrideText == NULL ) { HBufC* noteText = StringLoader::LoadLC( R_MOPOID_CONTAINER_NOTE_ABOUT ); note->ExecuteLD( *noteText ); CleanupStack::PopAndDestroy( noteText ); } else { note->ExecuteLD( *aOverrideText ); }
Játék motor hozzáadása a projekthez
Könyvtárak megadása bitgdi.lib mediaclientaudio.lib mediaclentimage.lib
Mopoid.mmp – projekt leíró fájl
Könyvtárak kiválasztása
Erőforrás fájl, többnyelvűség Mopoid.rls Mopoid.rss xxx.cpp #include
Vektorgrafikus képek használata
Icons_aif_scalable_dc.mk
Saját hang és adatfájlok Minden alkalmazásnak van egy privát könyvtára, amelyet az ő egyedi azonosítója (uid3) azonosít. Az alkalmazáshoz szükséges fájlokat itt kell elhelyezni.
Adatfájlok automatikus exportálása
Hang „bug”
Fájlok elhelyezése a készüléken ;Language - standard language definitions &EN ; standard SIS file header #{"Mopoid"},(0xEA90DC99),1,0,0 ;Localised Vendor name %{"Vendor-EN"} ;Unique Vendor name :"Vendor" ;Supports Series 60 v 3.0 [0x101F7961], 0, 0, 0, {"Series60ProductID"} ;Files to install ;You should change the source paths to match that of your environment ; "$(EPOCROOT)Epoc32\release\$(PLATFORM)\$(TARGET)\Mopoid.exe"-"!:\sys\bin\Mopoid.exe" "$(EPOCROOT)Epoc32\data\z\resource\apps\Mopoid.r01"-"!:\resource\apps\Mopoid.r01" "$(EPOCROOT)Epoc32\data\z\private\10003a3f\apps\Mopoid_reg.r01"- "!:\private\10003a3f\import\apps\Mopoid_reg.r01" "$(EPOCROOT)epoc32\data\z\resource\apps\Mopoid_aif.mif" -"!:\resource\apps\Mopoid_aif.mif" "$(EPOCROOT)epoc32\data\z\resource\apps\Mopoid.mbm" -"!:\resource\apps\Mopoid.mbm" ; Add any installation notes if applicable ;"Mopoid.txt" -"!:\private\0xEA90DC99\Mopoid.txt" "$(EPOCROOT)epoc32\data\z\resource\apps\MopoidGraphics.mif" -"!:\resource\apps\MopoidGraphics.mif" "..\gfx\hit.wav" -"!:\private\EA90DC99\hit.wav" "..\gfx\bounce.wav" -"!:\private\EA90DC99\bounce.wav" "..\gfx\levels.dat" -"!:\private\EA90DC99\levels.dat" ; Required for the application to be covered by backup/restore facility "..\sis\backup_registration.xml"-"!:\private\EA90DC99\backup_registration.xml" Mopoid.pkg ! jelentése: Telepítéskor megkérdezi, hová tegye a fájlokat. ! jelentése: Telepítéskor megkérdezi, hová tegye a fájlokat.
Képek futásidejű betöltése Az SVG-T kép betöltése a.mif fájlból Az SVG-T kép átméretezése képernyőméretűre pixelben A kép kirajzolása
CSpriteHandler osztály class C SpriteHandler : public C Base { public: static CSpriteHandler* NewL( R Fs& aFs); void ConstructL(RFs& aFs); CSpriteHandler(); ~CSpriteHandler(); inline CFbsBitmap* GetSprite(MopoidShared::TSpriteIds aSpriteId); void SetSpriteSize(const MopoidShared::TSpriteIds aSpriteId, const TSize& aNewSize); private: void DoSetSpriteSize(const MopoidShared::TSpriteIds aSpriteId,const TSize& aNewSize); private: T FixedArray iSprites; }; A képeket a CSpriteHandler osztály kezeli. Feladat: Képek betöltése Képek méretezése Egyedi azonosítók tárolása Feladat: Képek betöltése Képek méretezése Egyedi azonosítók tárolása
T, C, R és M osztályok T: egyszerű típus; nincs destruktora; csak T-ből, vagy M- ből öröklődhet; értékként átadható; stack-en tárolható C: csak a heapen foglalható; van destruktora; pontosan egy C és tetszőleges M osztályból származhat; nem adható át értékként M: interfész; csak virtuális metódusok; nincsenek tagváltozók; nem példányosítható R: erőforrás, melyet meg kell nyitni és be kell zárni
Kétfázisú konstrukció A „két fázist” a NewL, NewLC függvényekbe „becsomagolják”.
„Második” konstruktor void CSpriteHandler::ConstructL(RFs& aFs) { // TODO: Declare the filename of the mif-file (without the directory) _LIT(KMifFile, "MopoidGraphics.mif"); // Load sprites RBuf fileName; fileName.CleanupClosePushL(); // TODO: uncomment this line //NCommonFunctions::AddResourceDirL(KMifFile, fileName); // TODO: Load panel + mask // TODO: Load ball + mask // TODO: Load bricks CleanupStack::PopAndDestroy(&fileName); } Definiálunk egy konstans sztringet, amely megadja a képeket tartalmazó fájl nevét.
CSpriteHandler osztály class C SpriteHandler : public C Base { public: static CSpriteHandler* NewL( R Fs& aFs); void ConstructL(RFs& aFs); CSpriteHandler(); ~CSpriteHandler(); inline CFbsBitmap* GetSprite(MopoidShared::TSpriteIds aSpriteId); void SetSpriteSize(const MopoidShared::TSpriteIds aSpriteId, const TSize& aNewSize); private: void DoSetSpriteSize(const MopoidShared::TSpriteIds aSpriteId,const TSize& aNewSize); private: T FixedArray iSprites; }; CSpriteHandler* CSpriteHandler::NewL(RFs& aFs) { CSpriteHandler* self = new (ELeave) CSpriteHandler; CleanupStack::PushL(self); self->ConstructL(aFs); CleanupStack::Pop(self); return self; }
Adattagok megadása class C SpriteHandler : public C Base { public: static CSpriteHandler* NewL( R Fs& aFs); void ConstructL(RFs& aFs); CSpriteHandler(); ~CSpriteHandler(); inline CFbsBitmap* GetSprite(MopoidShared::TSpriteIds aSpriteId); void SetSpriteSize(const MopoidShared::TSpriteIds aSpriteId, const TSize& aNewSize); private: void DoSetSpriteSize(const MopoidShared::TSpriteIds aSpriteId,const TSize& aNewSize); private: T FixedArray iSprites; }; A képeket az iSprites tömbben tároljuk.
Konstruktor – 2. fázis void CSpriteHandler::ConstructL(RFs& aFs) { //Declare the filename of the mif-file (without the directory) _LIT(KMifFile, "MopoidGraphics.mif"); // Load sprites RBuf fileName; fileName.CleanupClosePushL(); NCommonFunctions::AddResourceDirL(KMifFile, fileName); // Load panel + mask iSprites[ESpritePanel] = AknIconUtils::CreateIconL(fileName, EMbmMopoidgraphicsPanel); iSprites[ESpritePanelM] = AknIconUtils::CreateIconL(fileName, EMbmMopoidgraphicsPanel_mask); // Load ball + mask iSprites[ESpriteBall] = AknIconUtils::CreateIconL(fileName, EMbmMopoidgraphicsBall); iSprites[ESpriteBallM] = AknIconUtils::CreateIconL(fileName, EMbmMopoidgraphicsBall_mask); // Load bricks iSprites[ESpriteBrickNormal] = AknIconUtils::CreateIconL(fileName,EMbmMopoidgraphicsBrick_green);... iSprites[ESpriteBrickSofterBrick] = AknIconUtils::CreateIconL(fileName,EMbmMopoidgraphicsBrick_blue); CleanupStack::PopAndDestroy(&fileName); } enum TMifMopoidgraphics { EMbmMopoidgraphicsBrick_brown = 16384, EMbmMopoidgraphicsBrick_red = 16386,... EMbmMopoidgraphicsBall_mask = 16399, EMbmMopoidgraphicsLastElement }; enum TMifMopoidgraphics { EMbmMopoidgraphicsBrick_brown = 16384, EMbmMopoidgraphicsBrick_red = 16386,... EMbmMopoidgraphicsBall_mask = 16399, EMbmMopoidgraphicsLastElement }; MopoidGraphics.mbg
„Memóriaszivárgás! Lefoglaltunk tárhelyet a képek számára, de nem szabadítottuk fel. „Memóriaszivárgás! Lefoglaltunk tárhelyet a képek számára, de nem szabadítottuk fel.
Tárhely felszabadítása void CSpriteHandler::ConstructL(RFs& aFs) { //Declare the filename of the mif-file (without the directory) _LIT(KMifFile, "MopoidGraphics.mif"); // Load sprites RBuf fileName; fileName.CleanupClosePushL(); NCommonFunctions::AddResourceDirL(KMifFile, fileName); // Load panel + mask iSprites[ESpritePanel] = AknIconUtils::CreateIconL(fileName, EMbmMopoidgraphicsPanel); iSprites[ESpritePanelM] = AknIconUtils::CreateIconL(fileName, EMbmMopoidgraphicsPanel_mask); // Load ball + mask iSprites[ESpriteBall] = AknIconUtils::CreateIconL(fileName, EMbmMopoidgraphicsBall); iSprites[ESpriteBallM] = AknIconUtils::CreateIconL(fileName, EMbmMopoidgraphicsBall_mask); // Load bricks iSprites[ESpriteBrickNormal] = AknIconUtils::CreateIconL(fileName,EMbmMopoidgraphicsBrick_green);... iSprites[ESpriteBrickSofterBrick] = AknIconUtils::CreateIconL(fileName,EMbmMopoidgraphicsBrick_blue); CleanupStack::PopAndDestroy(&fileName); } CSpriteHandler::~CSpriteHandler() { // Delete bitmaps iSprites.DeleteAll(); } CSpriteHandler::~CSpriteHandler() { // Delete bitmaps iSprites.DeleteAll(); }
Indexhatár túllépés
Hibaüzenet értelmezése Symbian OS v9.x -> Symbian Os Reference -> System panic reference -> USER
Komponensek dinamikus átméretezése
Méretváltozás kezelése void CMopoidContainer::HandleResourceChange(TInt aType) { CCoeControl::HandleResourceChange(aType); // Adapt the game field size to the current screen resolution // and orientation by calling SetExtentToWholeScreen() // in case the resource change type is a layout variant switch. if(aType == KEikDynamicLayoutVariantSwitch) { // User switched the layout configuration or the screen resolution :) // -> we have to recreate the layout SetExtentToWholeScreen();// Results in a call of SizeChanged() } void CMopoidContainer::ConstructL(const TRect& aRect, const CCoeControl* aParent, MEikCommandObserver* aCommandObserver) {... // Set the window to fullscreen including the softkey-bar, not to the rectangle // that the application gets with this function (which would not draw over the // softkey-bar). SetExtentToWholeScreen();// Results in a call of SizeChanged() iGameEngine->StartNewGameL(); ActivateL(); }
void CMopoidContainer::SizeChanged() { CCoeControl::SizeChanged(); LayoutControls(); if (iGameEngine) { // Query the current (= new) size of the control // and send it to the game engine, so that it can resize // all the graphics accordingly. iGameEngine->SetScreenSize(this->Size()); }
Játék ciklus
Háttér kirajzolása void CMopoidGameEngine::DrawFrame() const { if (!iBackBufferBmpGc) return; // Clear back buffer iBackBufferBmpGc->SetPenStyle(CGraphicsContext::ENullPen); iBackBufferBmpGc->SetBrushColor( KRgbBlack); iBackBufferBmpGc->SetBrushStyle(CGraphicsContext::ESolidBrush); iBackBufferBmpGc->DrawRect(iSettings->iScreenRect);... }
Labda kirajzolása void CMopoidGameEngine::DrawFrame() const {... // Draw ball iBackBufferBmpGc->BitBltMasked(ConvToScreenCoord(ballSpritePos), iSpriteHandler->GetSprite(MopoidShared::ESpriteBall), iSpriteHandler->GetSprite(MopoidShared::ESpriteBall)->SizeInPixels(), iSpriteHandler->GetSprite(MopoidShared::ESpriteBallM), EFalse);... } Paraméterek: 1.Pozíció 2.Képre mutató pointer 3.A másolandó kép mérete 4.Maszkra mutató pointer 5.Kell-e invertálni a maszkot Paraméterek: 1.Pozíció 2.Képre mutató pointer 3.A másolandó kép mérete 4.Maszkra mutató pointer 5.Kell-e invertálni a maszkot
Téglák kirajzolása void CMopoidGameEngine::DrawFrame() const {... // Draw bricks for (TInt x=0; x iGridCols; x++) { for (TInt y=0; y iGridRows; 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;... default: spriteId = MopoidShared::ESpriteBrickNormal; } //Draw bricks iBackBufferBmpGc->BitBlt(ConvToScreenCoord(iGrid->ConvertGridToXY(x, y)), iSpriteHandler->GetSprite(spriteId)); }
Korong kirajzolása //Draw Panel iBackBufferBmpGc->BitBltMasked(ConvToScreenCoord(iPanel.iPos), iSpriteHandler->GetSprite(MopoidShared::ESpritePanel), iSpriteHandler->GetSprite(MopoidShared::ESpritePanel)->SizeInPixels(), iSpriteHandler->GetSprite(MopoidShared::ESpritePanelM), EFalse);
Aktív objektumok használata
CPeriodic használata private: CMopoidContainer* iOwningControl; CSpriteHandler* iSpriteHandler; TMopoidLevels iLevels; CMopoidGrid* iGrid; TPanel iPanel; TBall iBall; CFbsBitGc* iBackBufferBmpGc; CFbsBitmapDevice* iBackBufferBmpDrawingDevice; TTime iLastFrameTime; TReal iThisFrameStep; TTime iLastScoreDecreaseTime; CSoundManager* iSoundManager; CPeriodic* iPeriodicTimer; RFs iFs; GameEngine.h
Timer elindítása – Call-Back hívás void CMopoidGameEngine::StartTimerL() { //Define the tick interval in microseconds: 5000 equals to 0,005 seconds const TTimeIntervalMicroSeconds32 KTickInterval = 5000; //Create the timer if necessary if (!iPeriodicTimer) { iPeriodicTimer = CPeriodic::NewL(CActive::EPriorityStandard); } // TODO: Start the timer with the tick interval that you defined. // Use CMopoidGameEngine::TimerCallBack for the function pointer // of the callback object and "this" for the instance pointer that // will be sent to the callback function. iPeriodicTimer->Start(KTickInterval, KTickInterval, TCallBack( TimerCallBack, this)); } TInt CMopoidGameEngine::TimerCallBack(TAny* aObject) { // Call non-static method return ((CMopoidGameEngine*)aObject)->DoFrame(); } static TInt TimerCallBack(TAny* aObject);
Timer leállítása void CMopoidGameEngine::StopTimer() { // If the timer object exists: stop and delete it. // TODO: Check if the timer exists and cancel it. // Also delete the timer instance and set the pointer // to NULL. if (iPeriodicTimer) { iPeriodicTimer->Cancel(); delete iPeriodicTimer; iPeriodicTimer = NULL; }
Animáció „kisímítása” Az aktív objektumok használatakor nem mindig „ütemesen, egyenletesen” kapj meg az objektum a vezérlést: Másik aktív objektum éppen fut, amikor megérkezik a szignál Másik aktív objektum prioritása nagyobb void CMopoidGameEngine::CalcTimeDifference() { TTime curFrameTime; curFrameTime.UniversalTime(); TTimeIntervalMicroSeconds tStepMicroS = curFrameTime.MicroSecondsFrom(iLastFrameTime); iThisFrameStep = ((TReal)(tStepMicroS.Int64())) / ; // Security check if the pause between two frames was too long - limit it // so that the ball can't jump around too much and pass through bricks. if (iThisFrameStep > 1.0) iThisFrameStep = 1.0; iLastFrameTime = curFrameTime; }
Háttér világítás megtartása TBool CMopoidGameEngine::DoFrame() { // Check how much time has passed since we calculated the last frame CalcTimeDifference(); // Decrease score every x seconds if (iLastFrameTime.MicroSecondsFrom(iLastScoreDecreaseTime) > iSettings->iScoreDecreaseTime) { // Decrease score iSettings->iScore -= iSettings->iScoreDecrement; // Refresh back light timer User::ResetInactivityTime(); // Update last setting time iLastScoreDecreaseTime.UniversalTime(); }... }
Kezdeti képernyő törlés kikapcsolása A képernyő törlést kikapcsoljuk, hogy megelőzzük a villogást.
Billentyűkezelés A view által létrehozott konténer osztály felel a főablak megjelenítéséért. A billentyű leütésre reagálni kívánó objektumokat a ControlStack-ben kell elhelyezni. A keretrendszer a billentyű műveleteket rendre „felajánlja” a ControlStack-ben található objektumoknak mindaddig, amíg valamelyik EKeyWasConsumed értéket nem ad vissza. void CMopoidContainerView::DoActivateL( const TVwsViewId& /*aPrevViewId*/, TUid /*aCustomMessageId*/, const TDesC8& /*aCustomMessage*/ ) { // [[[ begin generated region: do not modify [Generated Contents] SetupStatusPaneL(); if ( iMopoidContainer == NULL ) { iMopoidContainer = CreateContainerL(); iMopoidContainer->SetMopParent( this ); AppUi()->AddToStackL( *this, iMopoidContainer ); } // ]]] end generated region [Generated Contents] }
Billentyű állapot tárolása class TKeyHandler { public: TKeyHandler(); MopoidShared::TDirection GetDirection() const; void LeftPressed(); void RightPressed(); void NoDirection(); private: MopoidShared::TDirection iDirection; }; namespace MopoidShared { enum TDirection { ELeft, ERight, ENoDirection };... } MopoidSharedData.h TKeyHandler.h A labdának mindaddig mozogni kell, amíg az adott irányú billentyűt lenyomva tartjuk. A játékot a billentyű lenyomása és elengedése vezérli. A labdának mindaddig mozogni kell, amíg az adott irányú billentyűt lenyomva tartjuk. A játékot a billentyű lenyomása és elengedése vezérli.
Billentyű esemény kezelése TKeyResponse CMopoidContainer::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType) { TKeyResponse handled = EKeyWasNotConsumed; if (aType == EEventKeyDown){ // Player pressed a key. Store this so that the panel moves in the // corresponding direction until the player releases the key. switch (aKeyEvent.iScanCode) { // Handle left and right keys case EStdKeyLeftArrow: { iGameEngine->iKeyHandler.LeftPressed(); handled = EKeyWasConsumed; break;... } }else if (aType == EEventKeyUp){ // Player released a key. switch (aKeyEvent.iScanCode) { case EStdKeyLeftArrow: case EStdKeyRightArrow: case '4': case '6': { // Not moving in any direction anymore. iGameEngine->iKeyHandler.NoDirection(); handled = EKeyWasConsumed; break; } return handled; } A játékos lenyomott egy billentyűt. Tároljuk ezt az állapotot mindaddig, amíg el nem engedi azt. A játékos elengedte a billentyűt. A billentyű állapotát a TKeyHandler típusú objektumban tároljuk.
Játék közben
Grafikus környezet kialakítása void CMopoidGameEngine::SetScreenSize(const TSize& aNewSize) { // Save the screen size in the settings object iSettings->SetScreenSize(aNewSize); // (re)create the back buffer bitmap with the new size // We can't leave in this method. // -> Ignore the error. Might not be the best solution of course, // but shouldn't be a big problem. TRAPD(err, CreateBackBufferL(aNewSize)) ; void CMopoidGameEngine::CreateBackBufferL(const TSize& aSize) { // First remove the old back buffer if it already exists DeleteBackBuffer(); iBackBufferBmp = new (ELeave) CFbsBitmap; // Create a new back buffer with 16 million colors + alpha transparency // Should be the fastest mode in most caes, according to the // "Games on Symbian OS"-book, as it doesn't have to be converted // when drawing to the screen. User::LeaveIfError(iBackBufferBmp->Create(aSize, EColor16MA)); iBackBufferBmpDrawingDevice = CFbsBitmapDevice::NewL(iBackBufferBmp); //create graphics context for the bitmap User::LeaveIfError(iBackBufferBmpDrawingDevice->CreateContext(iBackBufferBmpGc) ); }
Szöveg megjelenítése void CMopoidGameEngine::DrawTextL() const { iBackBufferBmpGc->SetPenStyle(CGraphicsContext::ESolidPen); iBackBufferBmpGc->SetPenColor(KRgbRed); iBackBufferBmpGc->UseFont(iSettings->iFontUsed); TBuf tempStr; CEikonEnv* env = CEikonEnv::Static(); const TInt yTextStartBottom = iSettings->iDrawRect.iTl.iY - iSettings->iTextBaselineOffset; // High Score env->ReadResourceL(tempStr, R_HIGHSCORE); tempStr.AppendNum(iSettings->iHighScore); iBackBufferBmpGc->DrawText(tempStr, TPoint(5, yTextStartBottom)); // Score env->ReadResourceL(tempStr, R_SCORE); tempStr.AppendNum(iSettings->iScore); iBackBufferBmpGc->DrawText(tempStr, TPoint(5, yTextStartBottom - iSettings->iTextYOffset));... } deszkriptor
Deszkriptorok
Játékállás megjelenítése – Font beállítása CMopoidSettings.cpp void CMopoidSettings::ConstructL() { iFontUsed = (CFont*) AknLayoutUtils::LayoutFontFromId(EAknLogicalFontPrimarySmallFont); iFontHeight = iFontUsed->AscentInPixels(); iTextBaselineOffset = iFontHeight / 4; iTextYOffset = iFontHeight + iTextBaselineOffset; }
Szöveg beolvasása erőforrásfájlból... // High Score env->ReadResourceL(tempStr, R_HIGHSCORE ); tempStr.AppendNum(iSettings->iHighScore); iBackBufferBmpGc->DrawText(tempStr, TPoint(5, yTextStartBottom)); // Score env->ReadResourceL(tempStr, R_SCORE ); tempStr.AppendNum(iSettings->iScore); iBackBufferBmpGc->DrawText(tempStr, TPoint(5, yTextStartBottom - iSettings->iTextYOffset));... RESOURCE TBUF r_score { buf = STR_score; } RESOURCE TBUF r_highscore { buf = STR_highscore; } RESOURCE TBUF r_score { buf = STR_score; } RESOURCE TBUF r_highscore { buf = STR_highscore; } MopoidContainer.rssi #define STR_score "Score: " #define STR_highscore "High Score: " #define STR_score "Score: " #define STR_highscore "High Score: " MopoidContainer.l01 #include CMopoidEngine.h Mopoid.rsg... #define R_SCORE 0x413fd00d #define R_LEVEL 0x413fd00e... #define R_HIGHSCORE 0x413fd016 #define R_TITLE 0x413fd017 CMopoidEngine.cpp epocroot\include\
Szöveg igazítása // Title iBackBufferBmpGc->SetPenColor(TRgb(240, 200, 50)); env->ReadResourceL(tempStr, R_TITLE) ; iBackBufferBmpGc->DrawText(tempStr, iSettings->iScreenRect, // téglalap, ahová írni kell iSettings->iTextYOffset, // pozíció CGraphicsContext::ECenter, // igazítás 3); // margó }
Játék közben - eredménykijelzéssel
Fájlkezelés – Data Caging cage: kalitka, hadifogolytábor cagey: gyanakvó, ravasz, óvatos cage: kalitka, hadifogolytábor cagey: gyanakvó, ravasz, óvatos
Fájlkezelés – Data Caging //Add include file for file operations #include // Add lib: estor.lib, efsrv.lib... #define MOPOID_FILE_VERSION_NUMBER 1 _LIT(KMopoidDataFile, "settings.dat"); CMopoidEngine.h
Fájl név beállítása const void NCommonFunctions::AddPrivateDirL(RFs& aFs, const TDesC& aFilename, RBuf& aCompleteName) { // Retrieve the full drive + path + filename of the application TFileName appNamePath = CEikonEnv::Static()->EikAppUi()->Application()->AppFullName(); if (appNamePath.Length() == 0) User::Leave(KErrGeneral); #if defined(__WINS__) // The emulator returns z as the drive, as for it, applicationsare installed on the ROM-drive (z). // However, the resources are placed in the simulated c:\-drive, // so replace the drive in case we're running within the emulator appNamePath.Replace(0,1,_L("c")); #endif // Make sure the private path exists on the drive we need // Would actually not be needed, as we copy files into the // private directory during the installation process, so we // could be sure that it's here. But it's always better to // make sure. TInt driveNum; aFs.CharToDrive(appNamePath[0], driveNum); aFs.CreatePrivatePath(driveNum); // Reset the RBuf-variable and create it with the required size aCompleteName.Close(); aCompleteName.CreateL(KMaxPath); // Get the private path, does not contain the drive aFs.PrivatePath( aCompleteName ); // Insert the drive to the private path, otherwise it'd be missig aCompleteName.Insert(0, appNamePath.Left(2)); // Add the filename to the path, so that we now have a full URI, containing // the drive, path and filename aCompleteName.Append(aFilename); }
Játékállás elmentése void CMopoidGameEngine::SaveGameProgressL() { // Add the path to the filename RBuf fileName; fileName.CleanupClosePushL(); //Add the private directoy to the filename and storethe complete URI in the fileName descriptor. //The name of the file itself is stored in KMopoidDataFile. NCommonFunctions::AddPrivateDirL(iFs, KMopoidDataFile, fileName); //Open a file store CFileStore* store = CDirectFileStore::ReplaceLC(iFs, fileName, EFileWrite); store->SetTypeL(KDirectFileStoreLayoutUid); //Create the stream RStoreWriteStream stream; TStreamId id = stream.CreateLC(*store); //Write file version number & highscore stream.WriteInt32L(MOPOID_FILE_VERSION_NUMBER); stream.WriteInt32L(iSettings->iHighScore); //Commit the changes to the stream stream.CommitL(); CleanupStack::PopAndDestroy(&stream); //Set the stream in the store and commit the store store->SetRootL(id); store->CommitL(); CleanupStack::PopAndDestroy(store); CleanupStack::PopAndDestroy(&fileName); }
Játékállás visszatöltése void CMopoidGameEngine::LoadGameProgressL() { RBuf fileName; fileName.CleanupClosePushL(); //Add the private directoy to the filename and store // the complete URI in the fileName descriptor. // The name of the file itself is stored in KMopoidDataFile. NCommonFunctions::AddPrivateDirL(iFs, KMopoidDataFile, fileName); //Open the file store in read mode CFileStore* store = CDirectFileStore::OpenLC(iFs, fileName, EFileRead); //Open the data stream inside the store RStoreReadStream stream; stream.OpenLC(*store, store->Root()); //Read all the data TInt versionNumber = stream.ReadInt32L(); if (versionNumber != MOPOID_FILE_VERSION_NUMBER) User::Leave(KErrNotFound); iSettings->iHighScore = stream.ReadInt32L(); //Delete all the remaining stuff on the cleanup stack(store, stream) CleanupStack::PopAndDestroy(&stream); CleanupStack::PopAndDestroy(store); CleanupStack::PopAndDestroy(&fileName); }
Alkalmazás ikon módosítása application.uidesign
Mopoid.rss megváltozása RESOURCE LOCALISABLE_APP_INFO r_localisable_app_info { short_caption = STR_MopoidApplication_5; caption_and_icon = CAPTION_AND_ICON_INFO { caption = STR_MopoidApplication_4; number_of_icons = 0; }; } RESOURCE LOCALISABLE_APP_INFO r_localisable_app_info { short_caption = STR_MopoidApplication_5; caption_and_icon = CAPTION_AND_ICON_INFO { caption = STR_MopoidApplication_4; number_of_icons = 1; icon_file = "\\resource\\apps\\Mopoid_aif.mif"; }; }