简介
与使用者相关的核心模块包括 JApp,JGE,JRender。 类图如下所示:

JApp 类,即主应用程序类,用户基于 JGE 引擎开发游戏时需要实现 JApp 的子类,
通过在子类中实现 Update(),Render ()等方法来处理游戏的逻辑和渲染。
JGE 类,即引擎类,封装了引擎主要的方法,如 Init(), Run(), End(),
Update(), Render (), Pause(), Resume()。另外,从设计模式看,JGE 类本身
是个单件(singleton)模式,在整个系统中只存在一个实例。
JRender 类,即渲染类,该类封装了所有与绘制相关的方法,如画线、画三角形、
画多边形、绘制纹理、平移、旋转、矩阵运算等。在游戏中绘制对象时,需要先
获得一个 JRender 实例,然后调用它的成员方法完成各种绘制操作。从设计模
式看,JRender 类也是一个单件 (singleton)。
JGE 类定义及其核心方法的实现
JGE 类的成员:
- mApp:指向应用程序对象的指针,通过这个指针 JGE 会去调用应用程序的
Update(),Render () 等方法,处理游戏逻辑和渲染;
- mDone:表示是否游戏退出游戏;
- mDelta: 表示相对于上一个 frame 的时间变化;
- mInstance:指向 JGE 对象的指针。
JGE 类的方法:
- GetInstance:获得 JGE 实例的指针;
- SetApp:记录应用程序对象的指针;
- Init:初始化引擎;
- Update:在这个方法中调用用户应用类(JApp 的子类)的 Update 的方法,处
理游戏逻辑;
- Render:在这个方法中调用用户应用类的 Render 方法,完成渲染工作。
JGE 类的定义及核心方法的实现如下所示:
class JGE
{
private:
JApp *mApp;
bool mDone;
float mDelta;
static JGE* mInstance;
public:
//Get JGE instance.
static JGE* GetInstance();
//Set the user's core application class.
void SetApp(JApp *app);
void Init();
void Run();
void End();
void Update();
void Render();
void Pause();
void Resume();
};
JGE* JGE::GetInstance()
{
if (mInstance == NULL)
{
mInstance = new JGE();
}
//gCount++;
return mInstance;
}
void JGE::Update()
{
if (mApp != NULL)
mApp->Update();
}
void JGE::Render()
{
JRenderer* renderer = JRenderer::GetInstance();
renderer->BeginScene();
if (mApp != NULL)
mApp->Render();
renderer->EndScene();
}
void JGE::End()
{
mDone = true;
}
void JGE::Pause()
{
if (mPaused) return;
mPaused = true;
if (mApp != NULL)
mApp->Pause();
}
void JGE::Resume()
{
if (mPaused)
{
mPaused = false;
if (mApp != NULL)
mApp->Resume();
}
}
JApp 类定义及其核心方法的实现
开发人员用 JGE 引擎开发自己的游戏时需要实现 JApp 类,最核心的是两个方
法,一个是 Update() 方法,处理游戏逻辑、更新对象属性信息;另一个是
Render() 方法,渲染所有的对象。
JApp 类的定义及其核心方法实现如下所示:
/*
* Main application class for the system to run. The core game class
* should be derived from this base class.
*/
class JApp
{
public:
JApp();
virtual ~JApp();
/*
* Initialization function.
*
*/
virtual void Create() = 0;
/*
* Cleanup function before exiting from the game.
*
*/
virtual void Destroy() = 0;
/*
* Update function to be called for each frame update. Should perform
* all the game logic here.
*
* @par Example: A simple Update() implementation:
* @code
* void Update()
* {
* float dt = JGE::GetInstance()->GetDelta();
* mX += mSpeed*dt;
* }
* @endcode
*
*/
virtual void Update() = 0;
/*
* Render function to be called for each frame update. Should do all the
* game rendering here.
*
* @par Example: A simple Render() implementation:
* @code
* void Render()
* {
* JRenderer *r = JRenderer::GetInstance();
* r->FillRect(0,0,480,272,ARGB(255,0,0,0));
* }
* @endcode
*
*/
virtual void Render() = 0;
/*
* Callback function called when the game is paused by the system.
*
*/
virtual void Pause() = 0;
/*
* Callback function called when the game is resumed by the system.
*
*/
virtual void Resume() = 0;
};
引擎总体逻辑
引擎总体逻辑就是一个无限循环,除非停止事件发生。
我们把每次循环看作游戏的一个 frame,在每个 frame 中主要完成两件事:
- 调用引擎的 Update () 方法处理游戏的逻辑,更新各个对象的属性;
- 调用引擎的 Render () 方法绘制游戏的各个对象。
一个 frame 接着 frame,我们就看到了动态变化的游戏。
下面是 JGE 引擎总体逻辑部分的 Windows 平台代码,核心部分是那个 while
循环。
int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
g_engine->Render();
return TRUE; // Everything Went OK
}
void Update(int dt)
{
......
g_engine->SetDelta(dt);
g_engine->Update();
}
WinMain ()
{
......
CreateWindow ();
while (!done) {
/* Handle window message */
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
if (msg.message==WM_QUIT) {
done=TRUE; // If So done=TRUE
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
else {/* game engine loop */
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if (active) // Program Active?
{
if (g_engine->IsDone())
{
done=TRUE; // ESC Signalled A Quit
}
else // Not Time To Quit, Update Screen
{
tickCount = GetTickCount(); // Get The Tick Count
dt = (tickCount - lastTickCount);
lastTickCount = tickCount;
Update(dt); // Update frame
DrawGLScene(); // Draw The Scene
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
}
}// end of active
}// end of PeekMessage
}// end of while
}//end of WinMain
JGE Tutorial : HelloWorld
下面用一个经典的例子 Helloworld 演示一下如何用 JGE 引擎开发自己的应用。
这个例子在 JGE 代码包的 Tutorials 目录下可以找到。
Helloworld 源代码包括三个文件:
- GameApp.h: 定义了一个 GameApp 类,该类从 JApp 类派生而来,是应用程
序主类;
- GameApp.cpp:GameApp 类的方法的具体实现;
- GameLauncher.cpp:这个文件本文没有介绍,可以简单理解成是应用的参数
文件,记录应用名称等信息。
GameApp 类的定义如下所示:
class JLBFont;
class GameApp: public JApp
{
private:
JLBFont* mFont;
public:
GameApp();
virtual ~GameApp();
virtual void Create();
virtual void Destroy();
virtual void Update();
virtual void Render();
virtual void Pause();
virtual void Resume();
};
GameApp.cpp 如下所示:
#include <stdio.h>
#include <JGE.h>
#include <JRenderer.h>
#include <JLBFont.h>
#include "GameApp.h"
/*
* Constructor. Variables can be initialized here.
*/
GameApp::GameApp()
{
mFont = NULL;
}
/*
* Destructor.
*/
GameApp::~GameApp()
{
}
/*
* This is the init callback function. You should load and create your in-game
* resources here.
*/
void GameApp::Create()
{
// Load a bitmap font for displaying text
mFont = new JLBFont("f3", 16, true);
}
/*
* This is the clean up callback function. You should delete all your in-game
* resources, for example texture and quads, here.
*/
void GameApp::Destroy()
{
// Cleaning up
if (mFont)
delete mFont;
}
/*
* This is the update callback function and is called at each update frame
* before rendering. You should update the game logic here.
*/
void GameApp::Update()
{
JGE* engine = JGE::GetInstance();
// do a screen shot when the TRIANGLE button is pressed
if (engine->GetButtonClick(PSP_CTRL_TRIANGLE))
{
char s[80];
// save screen shot to root of Memory Stick
sprintf(s, "ms0:/screenshot.png");
JRenderer::GetInstance()->ScreenShot(s);
}
// exit when the CROSS button is pressed
if (engine->GetButtonClick(PSP_CTRL_CROSS))
{
engine->End();
return;
}
}
/*
* All rendering operations should be done in Render() only.
*/
void GameApp::Render()
{
// get JRenderer instance
JRenderer* renderer = JRenderer::GetInstance();
// clear screen to black
renderer->ClearScreen(ARGB(0,0,0,0));
// set font colour
mFont->SetColor(ARGB(255,255,255,255));
// render text
mFont->DrawString("Hello World!", 240.0f, 130.0f, JGETEXT_CENTER);
}
/*
* This function is called when the system wants to pause the game. You can set a flag
* here to stop the update loop and audio playback.
*/
void GameApp::Pause()
{
// we haven't had anything to do here yet
}
/*
* This function is called when the game returns from the pause state.
*/
void GameApp::Resume()
{
// we haven't had anything to do
}
GameLauncher.cpp 如下所示:
#include <JGameLauncher.h>
#include "GameApp.h"
JApp* JGameLauncher::GetGameApp()
{
return new GameApp();
};
char *JGameLauncher::GetName()
{
return "JGE++: Hello World!";
}
u32 JGameLauncher::GetInitFlags()
{
return JINIT_FLAG_NORMAL;
}
|