⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 retroengine.cpp

📁 s60 二维动画教程 含源码及 s60 二维动画教程 含源码及
💻 CPP
字号:
////////////////////////////////////////////////////////////////////////
//
// RetroEngine.cpp
//
// Copyright (c) 2003 Nokia Mobile Phones Ltd.  All rights reserved.
//
////////////////////////////////////////////////////////////////////////

#include "RetroEngine.h"

//System includes
#include <e32math.h>

//User includes
#include "KeyHandler.h"
#include "ImageFactory.h"
#include "DoublebufferedArea.h"
#include "RenderableFactory.h"
#include "BaseAnim.h"         
#include "BitmapAnimFrame.h"  
#include "BitmapTile.h"       
#include "FireAnim.h"         
#include "ParticleSystem.h"   
#include "RetroLeafTileset.h" 
#include "RetroNodeTileset.h" 
#include "ShipAnim.h"         
#include "Tilemap.h"          
#include "Tileset.h"          
#include "GameTimer.h"

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

CRetroEngine* CRetroEngine::NewLC(RWsSession& aClient, CWsScreenDevice& aScreenDevice, RWindow& aWindow,TKeyHandler& aKeyHandler, CImageFactory& aImageFactory, const TSize& aSize)
	{
	CRetroEngine* self = new (ELeave) CRetroEngine(aClient, aScreenDevice, aWindow, aKeyHandler, aImageFactory, aSize);
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
	}

////////////////////////////////////////////////////////////////////////

CRetroEngine* CRetroEngine::NewL(RWsSession& aClient, CWsScreenDevice& aScreenDevice, RWindow& aWindow,TKeyHandler& aKeyHandler, CImageFactory& aImageFactory, const TSize& aSize)
	{
	CRetroEngine* self = CRetroEngine::NewLC(aClient, aScreenDevice, aWindow, aKeyHandler, aImageFactory, aSize);
	CleanupStack::Pop();
	return self;
	}

////////////////////////////////////////////////////////////////////////

CRetroEngine::CRetroEngine(RWsSession& aClient, CWsScreenDevice& aScreenDevice, RWindow& aWindow,TKeyHandler& aKeyHandler, CImageFactory& aImageFactory, const TSize& aSize) :
	iClient(aClient),
	iScreenDevice(aScreenDevice),
	iWindow(aWindow),
	iKeyHandler(aKeyHandler),
	iImageFactory(aImageFactory),
	iSize(aSize),
	iDropRenderFrames(ETrue), // Set to "EFalse" to demonstrate ViewSrv 11 problem
	iFrameCounter(0)
	{
	}

////////////////////////////////////////////////////////////////////////
	
void CRetroEngine::ConstructL()
	{
	iPlaying = EFalse;

	iGameTimer = CGameTimer::NewL(*this);
	// Direct screen access
	iDirectScreenAccess = CDirectScreenAccess::NewL(iClient, iScreenDevice, iWindow, *this);

//	ConstructSimpleMapL();
	ConstructCompoundMapL();
	ConstructShipL();

	iDoubleBufferedArea = CDoubleBufferedArea::NewL(iSize, EColor4K);
	iOffscreenContext = &(iDoubleBufferedArea->GetDoubleBufferedAreaContext());
	}

////////////////////////////////////////////////////////////////////////

CRetroEngine::~CRetroEngine()
	{
	delete iGameTimer;
	iGameTimer = NULL;
	
	delete iDirectScreenAccess;
	iDirectScreenAccess = NULL;
	
	delete iDoubleBufferedArea;
	iDoubleBufferedArea = NULL;

	delete iMap;
	iMap = NULL;

	delete iNodeFactory;
	iNodeFactory = NULL;
	
	delete iLeafFactory;
	iLeafFactory = NULL;
	
	delete iEngineExhaust;
	iEngineExhaust = NULL;

	delete[] iShipVectors;
	iShipVectors = NULL;

	delete iShipAnim;
	iShipAnim = NULL;
	
	delete iFireAnim;
	iFireAnim = NULL;
	}

////////////////////////////////////////////////////////////////////////

void CRetroEngine::ConstructSimpleMapL()
    {
	TInt mapData[] = 
		{
		0,4,0,4,0,4,0,4,0,4,0,4,0,4,0,4,
		4,0,4,0,4,0,5,2,4,0,4,0,4,0,4,0,
		0,4,0,4,0,5,3,6,0,4,0,4,0,4,0,4,
		4,0,4,0,4,1,7,2,4,0,4,0,4,0,4,0,
		0,4,0,4,0,4,1,6,0,4,0,4,0,4,0,4,
		4,0,4,0,4,0,4,0,4,0,4,0,4,0,4,0,
		0,4,0,4,0,4,0,4,0,4,0,4,0,4,0,4,
		4,0,4,0,4,0,4,0,4,0,4,0,4,0,4,0,
		0,4,0,4,0,4,0,4,0,4,0,4,0,4,0,4,
		4,0,4,0,4,0,4,0,4,0,4,0,4,0,4,0,
		0,4,0,4,0,4,0,4,0,4,0,4,0,4,0,4,
		4,0,5,2,4,0,4,0,4,0,4,0,5,2,4,0,
		0,4,1,6,0,4,0,4,0,4,0,4,1,6,0,4,
		4,0,5,2,4,0,4,0,4,0,4,0,4,0,4,0,
		0,4,1,6,0,4,0,4,0,4,0,4,0,4,0,4,
		4,0,4,0,4,0,4,0,4,0,4,0,4,0,4,0,
		};

	iShipBounds		= TRect(TPoint(0x00000800,0x00000800),TPoint(0x00001800,0x00001800));
	iShipWorldPos	= iShipBounds.Center();
	iShipVelocity	= TPoint(0x000e,0x0013);

	iLeafFactory = CRetroLeafTileset::NewL(iImageFactory.TileImage());
	iMap = CTilemap::NewL(16,16,&mapData[0],*iLeafFactory);
	}

////////////////////////////////////////////////////////////////////////

void CRetroEngine::ConstructCompoundMapL()
    {
	TInt mapData[] = 
		{
		15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
		15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
		15,15, 7, 3,11,15, 7, 3, 3, 3, 3, 3, 3,11,15,15,
		15,15, 5, 0, 2, 3, 1, 0, 0, 0, 0, 0, 0,10,15,15,
		15,15, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,10,15,15,
		15,15, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,10,15,15,
		15,15, 5, 0, 0, 8, 4, 0, 0, 0, 0, 0, 0,10,15,15,
		15,15, 5, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0,10,15,15,
		15,15, 5, 0, 0, 0, 0, 0, 8, 4, 0, 0, 0,10,15,15,
		15,15, 5, 0, 0, 0, 0, 0, 2, 9, 4, 0, 0,10,15,15,
		15,15, 5, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0,10,15,15,
		15,15, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,10,15,15,
		15,15, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,10,15,15,
		15,15,13,12,12,12,12,12,12,12,12,12,12,14,15,15,
		15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
		15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
		};

	iShipBounds		= TRect(TPoint(0x00000800,0x00000800),TPoint(0x00007800,0x00007800));
	iShipWorldPos	= iShipBounds.Center();

	iLeafFactory = CRetroLeafTileset::NewL(iImageFactory.TileImage());
	iNodeFactory = CRetroNodeTileset::NewL(*iLeafFactory);
	iMap = CTilemap::NewL(16,16,&mapData[0],*iNodeFactory);
	}

////////////////////////////////////////////////////////////////////////

void CRetroEngine::ConstructShipL()
	{
	iShipVelocity	= -TPoint(0x000e,0x0013);

	iShipFrame = 8;
	iShipScreenPos = TPoint(88,104);
	iShipScreenPosUp4 = TPoint(iShipScreenPos.iX << 4, iShipScreenPos.iY << 4);

	iShipAnim = CShipAnim::NewL(iImageFactory.ShipAnim());
	iFireAnim = CFireAnim::NewL(iImageFactory.FireAnim());

	iEngineExhaust = CParticleSystem::NewL(16,*iFireAnim);

	// Physics parameters for ship motion:
	iDragDownshift = 8;
	iDragRatio = 0xff;
	iThrust = 6;
	iGravity = 1;


	// Allocate and initialise ship vectors
	// (each one a vector lying along the central axis of the ship
	// in the corresponding animation frame):
	iShipVectors = new TVectorFP[64];
	User::LeaveIfNull(iShipVectors);

	TReal degreesToRadians = 3.141592 / 180.0;

	// Animation frame #0 is at 45 degrees, so:
	TReal angle = 45.0 * degreesToRadians;
	TReal angleStep = ( 360.0 / 64.0 ) * degreesToRadians;

	for ( TInt frame = 0 ; frame < 64 ; frame++ )
		{
		TReal cos;
		TReal sin;

		Math::Cos(cos,angle);
		Math::Sin(sin,angle);

		TInt16 cosFP;
		TInt16 sinFP;

		Math::Int(cosFP,cos * 256.0);
		Math::Int(sinFP,sin * 256.0);

		iShipVectors[frame] = TVectorFP(TPoint(cosFP,sinFP));

		angle += angleStep;
		}
	}

////////////////////////////////////////////////////////////////////////

void CRetroEngine::Simulate()
	{
	UpdatePosition();
	iEngineExhaust->Simulate();

	if( iKeyHandler.Direction() == TKeyHandler::ELeft )
		{
		iShipFrame--;
		}
	else if ( iKeyHandler.Direction() == TKeyHandler::ERight )
		{
		iShipFrame++;
		}

	if (iKeyHandler.FirePressed())
		{
		iEngineExhaust->Generate(iShipWorldPos,iShipVectors[iShipFrame],iShipVelocity,13 << 4,128);
		}

	iShipFrame &= 0x3f;
	}

////////////////////////////////////////////////////////////////////////

void CRetroEngine::UpdatePosition()
	{

	if (iKeyHandler.FirePressed())
		{
			TPoint deltaV = iShipVectors[iShipFrame].ScaleToPoint(-iThrust);
			iShipVelocity += deltaV;
		}

	TInt vSquared = ( iShipVelocity.iX * iShipVelocity.iX ) + ( iShipVelocity.iY * iShipVelocity.iY );

	TInt dragRatio = iDragRatio;

	if ( vSquared < 1024 )
		{
		// Very slow - no drag needed:
		dragRatio = 0x0100;
		}
	else if ( vSquared > 4096 )
		{
		// Fast - apply strong drag:
		dragRatio = 0x00fc;
		}
	else if ( vSquared > 8192 )
		{
		// Very fast - apply stronger drag:
		dragRatio = 0x00f0;
		}

	if ( vSquared > 1024 )
	{
		iShipVelocity.iX = ( iShipVelocity.iX * dragRatio ) >> iDragDownshift;
		iShipVelocity.iY = ( iShipVelocity.iY * dragRatio ) >> iDragDownshift;
	}

	iShipVelocity.iY += iGravity;

	TPoint newWorldPos = iShipWorldPos + iShipVelocity;

	if ( iShipBounds.Contains(newWorldPos) )
		{
		iShipWorldPos = newWorldPos;	
		}
	else
		{
		if ( ( newWorldPos.iX < iShipBounds.iTl.iX ) || ( newWorldPos.iX >= iShipBounds.iBr.iX ) )
			{
			iShipVelocity.iX = -iShipVelocity.iX;
			}

		if ( ( newWorldPos.iY < iShipBounds.iTl.iY ) || ( newWorldPos.iY >= iShipBounds.iBr.iY ) )
			{
			iShipVelocity.iY = -iShipVelocity.iY;
			}
		}

	iMapWindowTopLeft = iShipWorldPos - iShipScreenPosUp4;
	}

////////////////////////////////////////////////////////////////////////

void CRetroEngine::Render(const TRect& aRect,CFbsBitGc* aCallerGc) const
	{
	TPoint pixelTopLeft(iMapWindowTopLeft.iX >> 4,iMapWindowTopLeft.iY >> 4);
	iMap->Render(pixelTopLeft,aRect,aCallerGc);


	iEngineExhaust->Render(pixelTopLeft,aRect,aCallerGc);
	iShipAnim->RenderFrameCentered(iShipFrame,iShipScreenPos,aRect,aCallerGc);
	}

////////////////////////////////////////////////////////////////////////

void CRetroEngine::SetupDirectScreenAccessL()
	{
	// Initialise DSA
	iDirectScreenAccess->StartL();

	// Get graphics context for it
	iGc = iDirectScreenAccess->Gc();

	// Get region that DSA can draw in
	iRegion = iDirectScreenAccess->DrawingRegion();

	// Set the display to clip to this region
	iGc->SetClippingRegion(iRegion);
	}

////////////////////////////////////////////////////////////////////////

void CRetroEngine::StartFirstGameL()
	{
	StartGameL();
	// We only want to play the game if we have the whole screen available so 
	// on first start we record the region available for comparision later (in restart)
	iGameDawingArea = iRegion->BoundingRect();
	}

////////////////////////////////////////////////////////////////////////

void CRetroEngine::StartGameL()
	{
	iPaused = EFalse;
	if(!iPlaying)
		{
		SetupDirectScreenAccessL();
		iGameTimer->Restart();
		}
	iPlaying = ETrue;
	}

////////////////////////////////////////////////////////////////////////

void CRetroEngine::StopGame()
	{
	iPlaying = EFalse;
	iPaused = ETrue;
	iGameTimer->CancelTimer();
	iDirectScreenAccess->Cancel();
	}

////////////////////////////////////////////////////////////////////////

TInt CRetroEngine::DoGameFrame()
	{
	// Force screen update:
	iDirectScreenAccess->ScreenDevice()->Update();

	Simulate();

	// Drop 1 render frame in every 128, to avoid ViewSrv 11 problems:
	if (iDropRenderFrames & ((iFrameCounter & 0x007f) != 0x007f))
		{
		Render(iGameDawingArea, iOffscreenContext);
		}

	iFrameCounter++;

	// Draw from offscreen bitmap
	iGc->BitBlt(TPoint(0,0), &(iDoubleBufferedArea->GetDoubleBufferedAreaBitmap()));

	iClient.Flush();	

	if(iPaused)
		{
		return CGameTimer::StopTicking;
		}
	else
		{
		return CGameTimer::TickAgain;
		}
	}

////////////////////////////////////////////////////////////////////////

void CRetroEngine::Restart(RDirectScreenAccess::TTerminationReasons /*aReason*/)
	{
	// Restart display
	// Note that this will result in the clipping region being updated
	// so that menus, overlaying dialogs, etc. will not be drawn over
	SetupDirectScreenAccessL();
	if(iPaused)
		{
		if(iGameDawingArea == iRegion->BoundingRect())
			{
			iPaused = EFalse;	
			if(!iGameTimer->IsActive())
				{
				iGameTimer->Restart();
				}
			}
		else
			{
			PauseFrame();
			}
		}
	else
		{
		if(!iGameTimer->IsActive())
			{
			iGameTimer->Restart();
			}
		}
	}

////////////////////////////////////////////////////////////////////////

void CRetroEngine::AbortNow(RDirectScreenAccess::TTerminationReasons /*aReason*/)
	{
	// Cancel timer and display
	iDirectScreenAccess->Cancel();
	iPaused = ETrue;
	}

////////////////////////////////////////////////////////////////////////

void CRetroEngine::PauseFrame()
	{
	// Force screen update: this is required for WINS, but may
	// not be for all hardware:
	iDirectScreenAccess->ScreenDevice()->Update();

	// and draw from unchanged offscreen bitmap
	iGc->BitBlt(TPoint(0,0), &(iDoubleBufferedArea->GetDoubleBufferedAreaBitmap()));

	iClient.Flush();		
	}

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -