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

📄 cengine.cpp

📁 一个SYMBIAN下的3D游戏引擎,爱好游戏的朋友下载了
💻 CPP
字号:
   /*
============================================================================
    * Name : CEngine.cpp
    * Part of : Example3D
    * Description : Definition of CEngine
    * Copyright (c) 2005 Nokia Corporation
============================================================================
    */

// INCLUDES
#include "CEngine.h"
#include "CGameTimer.h"
#include "CGame.h"
#include "CPictureLoader.h"
#include <eikenv.h>
#include <eikappui.h>

// CONSTANTS
const TInt KUpdateInterval = 1000000 / 64;	// 64 times per second "Move" update
const TInt KMaxNumUpdates = 10;

// MEMBER FUNCTIONS



CEngine* CEngine::NewL( CWindowGc& aGc, RWindow& aWindow, 
						TDisplayMode aDisplayMode )
	{
	CEngine* self = new( ELeave )CEngine( aGc, aWindow, aDisplayMode );
	CleanupStack::PushL( self );
	self->ConstructL();
	CleanupStack::Pop( self );
	return self;
	}



CEngine::~CEngine()
	{
	iFile.Close();
	iFs.Close();

	delete iFbsBitmapBuffer;
	delete iTimer;
	delete iGame;
	delete iFbsScreenDevice;
	delete iBitmapUtil;

	
#ifdef GLES
	eglMakeCurrent( iGldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
    eglDestroyContext( iGldisplay, iGlcontext );
    eglDestroySurface( iGldisplay, iGlsurface );
    eglTerminate( iGldisplay );
#endif
	}



void CEngine::ConstructL()
	{
	iFs.Connect();
	iFile.Replace( iFs, _L("c:\\debug.txt"), EFileWrite );
	iPaused = ETrue;


#ifdef GLES

	// Define properties for the preferred EGLSurface, try to match with window depth
	EGLint attribList[ ] = { EGL_BUFFER_SIZE, 0,
	EGL_DEPTH_SIZE, 15,
	EGL_NONE };

	switch( iWindow.DisplayMode() )
		{
		case( EColor4K ) : { attribList[1] = 12; break; }
		case( EColor64K ): { attribList[1] = 16; break; }
		case( EColor16M ): { attribList[1] = 24; break; }
		default: attribList[1] = 32; // for EColor16MU
		}	
	
	EGLint numConfigs;
	EGLint majorVersion;
	EGLint minorVersion;
	
	iGldisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY );
	if( iGldisplay == EGL_NO_DISPLAY )
		{
		User::Panic( _L("GL No Display"),0 );
		}
	if( !eglInitialize( iGldisplay, &majorVersion, &minorVersion ) ) 
		{
		User::Panic( _L("GL Init"), 0 );
		}
	if( !eglChooseConfig( iGldisplay, attribList, &iGlconfig, 1, &numConfigs ) )
		{
		User::Panic(_L("GL Config"), 0 );
		}
	iGlcontext = eglCreateContext( iGldisplay, iGlconfig, NULL, NULL );
	if( iGlcontext==0 )
		{
		User::Panic( _L("GL Context"), 0 );
		}
	iGlsurface = eglCreateWindowSurface( iGldisplay, iGlconfig, &iWindow, NULL );
	if( iGlsurface==0 )
		{
		User::Panic( _L("GL Surface"), 0 );
		}
	
	eglMakeCurrent( iGldisplay, iGlsurface, iGlsurface, iGlcontext );


#else

	// create screen device for direct screen access
	iFbsScreenDevice = CFbsScreenDevice::NewL( _L(""), iDisplayMode, NULL );

	iFbsBitmapBuffer = new( ELeave )CFbsBitmap();

	iBitmapUtil = new( ELeave )TBitmapUtil( iFbsBitmapBuffer );

	#ifndef __WINS__

			TScreenInfoV01 screenInfo;
			TPckg<TScreenInfoV01> sInfo(screenInfo);
			UserSvr::ScreenInfo(sInfo);
         
			TUint16* screenAddr = screenInfo.iScreenAddressValid ? (TUint16*)screenInfo.iScreenAddress : 0;
			User::LeaveIfNull( screenAddr );

			// skip the palette data in the beginning of frame buffer (16 entries in 12bit mode)
			screenAddr += 16;
                
			iScreen.iData = screenAddr;
			iScreen.iSize = screenInfo.iScreenSize;
	#endif



#endif

	iGame = CGame::NewL( iDisplayMode );

	iTimer = CGameTimer::NewL( *this );

	iTime.HomeTime();

	// Some devices have difficulties to multitask with
	// this application using idle time.
	// This should help it a little
	RProcess().SetPriority( EPriorityLow );

	}



void CEngine::InitScreen( const TRect& aRect )
	{
	iDrawRect = aRect;
	
	
#ifdef GLES

#else

	iFbsBitmapBuffer->Reset();
	iFbsBitmapBuffer->Create( iDrawRect.Size(), iDisplayMode );
	iBuffer.iData = iFbsBitmapBuffer->DataAddress();

#endif

	iBuffer.iSize = iDrawRect.Size();
	iBuffer.iMode = iDisplayMode;
	}



CEngine::CEngine( CWindowGc& aGc, RWindow& aWindow, 
				  TDisplayMode aDisplayMode )
	: iGc( aGc )
	, iWindow( aWindow )
	, iDisplayMode( aDisplayMode )
	{

	}



TInt CEngine::DoGameFrameL()
	{
	if( iPaused )
		{
		// stop gametimer
		return EFalse;
		}


	TPoint pos = iWindow.Position();
	TSize size = iWindow.Size();
	if( size != iDrawRect.Size() || pos != iDrawRect.iTl )
		{
		TRect rect( pos, size );
		InitScreen( rect );
		return ETrue;
		}


	
	//
	// Calculate number of updates that should happen since last game frame
	//
	TTime time;
	time.HomeTime();
	TInt updates = time.MicroSecondsFrom( iTime ).Int64().Low();
	iUpdates += updates;

	updates = iUpdates / KUpdateInterval;
	
	iTime = time.Int64();
	
	TInt i;
	for( i=0; i<updates; i++ )
		{
		iGame->Move( iKey );
		}
	iUpdates -= updates * KUpdateInterval;
	
	
	

#ifdef GLES
	// Draw with OpenGL
	eglMakeCurrent( iGldisplay, iGlsurface, iGlsurface, iGlcontext );
	// GL double buffer swap
	eglSwapBuffers( iGldisplay, iGlsurface);
	iGame->Draw( iBuffer );
	RRegion drawRegion;
	drawRegion.AddRect( iDrawRect );
	drawRegion.Clear();


#else
	
	// Draw with software renderer
	// Lock the bitmap we are drawing to
	iBitmapUtil->Begin( TPoint( 0,0 ) );

	// CFbsBitmap data address can change
	iBuffer.iData = iFbsBitmapBuffer->DataAddress();
	iBuffer.iMode = iDisplayMode;

	iGame->Draw( iBuffer );

	//
	// During the direct screen draw we don't want any interruptions
	// So adjust priority high at this time
	//
	RProcess().SetPriority( EPriorityHigh );

	iWindow.Invalidate();
	RRegion drawRegion;
	iWindow.GetInvalidRegion( drawRegion );
	iGc.Activate( iWindow );
	iWindow.BeginRedraw();

	TDrawBuffer drawBuffer = EBitmapCopy;

	#ifdef __WINS__
		drawBuffer = EBitmapCopy;
	#else
		// check if draw area is free to draw
		// only then use directly screen memory to draw
		// ( with doublebuffer to prevent display artifacts )
/*
		if( drawRegion.Count() == 0 )
			{
			drawBuffer = ENoScreen;
			}
		else 		
			{
			TRect rect = ( drawRegion.RectangleList()[ 0 ] );
			TPoint windowPos = iWindow.Position();
			rect.iTl.iX += windowPos.iX;
			rect.iBr.iX += windowPos.iX;
			rect.iTl.iY += windowPos.iY;
			rect.iBr.iY += windowPos.iY;

			if( iDrawRect.iTl.iX >= rect.iTl.iX && 
				iDrawRect.iTl.iY >= rect.iTl.iY &&
				iDrawRect.iBr.iX <= rect.iBr.iX &&
				iDrawRect.iBr.iY <= rect.iBr.iY )
				{
				drawBuffer = EDoubleBuffered;
				}
			}
*/
	#endif

	drawBuffer = EBitmapCopy;

	switch( drawBuffer )
		{
		case EBitmapCopy:
			{

			// Blit to top left corner of our window
			// this doesn't have to be top left corner of the screen
			iGc.BitBlt( TPoint( 0,0 ), iFbsBitmapBuffer );

			break;
			}
		case EDoubleBuffered:
			{
			// Since draw rect can be different from actual screen size
			// this copy has to be done line-by-line
			TUint16* sourceAddress = ( TUint16* )iBuffer.iData;
			TUint16* targetAddress = ( TUint16* )iScreen.iData;
			
	        // add offset from drawing rect
	        targetAddress += iDrawRect.iTl.iX;
	        targetAddress += iDrawRect.iTl.iY * iScreen.iSize.iWidth;

			// bytes to copy per line
			TInt numBytes = iDrawRect.Width() * 2; // 16 bit pixels
			
			for( TInt y=0; y<iBuffer.iSize.iHeight; y++ )
				{
				Mem::Copy( targetAddress, sourceAddress, numBytes );
				sourceAddress += iBuffer.iSize.iWidth;
				targetAddress += iScreen.iSize.iWidth;
				}
			break;
			}

		}

		
	drawRegion.Clear();
	drawRegion.AddRect( iDrawRect );
	iFbsScreenDevice->Update( drawRegion );
	// RRegion leaks memory if Clear isn't called
	drawRegion.Clear();
	
	iWindow.EndRedraw();

	iGc.Deactivate();

	// Unlock the bitmap we are drawing to 
	iBitmapUtil->End();

	//
	// Set priority back to normal
	//
	RProcess().SetPriority( EPriorityLow );

	

#endif
	
			
	// continue gametimer
	return ETrue;
	}


void CEngine::KeyEvent( const TKeyEvent& aKeyEvent,TEventCode aType )
	{
	switch( aType )
		{
		case EEventKeyDown:
			{
			iKey[ aKeyEvent.iScanCode ] = 1;
			break;
			}
		case EEventKeyUp:
			{
			iKey[ aKeyEvent.iScanCode ] = 0;
			break;
			}
		default:
			{
			break;
			}
		}
	}


void CEngine::Start()
	{
	if( !iPaused ) return;
	iPaused = EFalse;
	iTimer->Start();
	}


void CEngine::Stop()
	{
	if( iPaused ) return;
	iPaused = ETrue;
	iTimer->Cancel();
	}


void CEngine::Command( TInt aCommand )
	{
	if( iGame )
		{
		iGame->Command( aCommand );
		}
	}

⌨️ 快捷键说明

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