bada 2D 游戏编程之五——一个基于定时器的游戏循环
 
 
在上篇《 bada 2D 游戏编程之四——设计游戏循环》中对比较常见的几种设计游戏循环的理论知识进行了阐述,下面按照 bada 平台的编程知识来实现一种游戏循环。实现“时间驱动”的 游戏循环通常采用 2 种方式,一种是基于定时器的游戏循环,还有一种是基于线程的游戏循环。在本篇文章中给大家介绍如何在 bada 平台上实现一个基于定时器的游戏循环。
 
1 ,定时器使用方法
bada 平台提供了 Osp::Base::Runtime::Timer 来作为系统的定时器,这是 Timer 的主要函数:

函数
功能描述
Construct(const ITimerEventListener& listener)
初始化函数,传入监听器
Start(int timeout)
开始计时
Cancel(void)
取消计时
 
同时还有一个 Osp::Base::Runtime::ITimerEventListener 接口类来配合它一起使用, ITimerEventListener 类的主要函数:

函数
功能描述
OnTimerExpired(Timer& timer)
定时器到时时被回调到
 
这样当 Timer 设定的时间到达后, ITimerEventListener 中的事件处理函数 OnTimerExpired(Timer& timer) 就会被回调到,在这里面进行事件处理就可以了。
 
2 ,实现的思路
实现的思路主要是将游戏的循环和游戏 ( 事件处理、逻辑更新、渲染绘制 ) 进行分离,从而可以将游戏循环模块和游戏模块分离开来,降低相互之间的依赖程度。通过加入一个接口类将 HandleEvent(),UpdateLogic() Draw() 封装起来,然后在游戏循环中调用这个接口类的函数来通知游戏模块进行处理,从而实现了相互之间的独立。
 
在写这个博客系列的过程中,希望能够实现一个简单的游戏引擎,并将这个游戏引擎的缩写定为 TG ,一是表示为二维游戏 (Two-Dimensional Game) 的意思,再是现在网上有传言要将 bada Tizen 进行合并,到时这个基于 bada 的游戏引擎应该是可以运行在 Tizen 上的,所以也可以表示为 Tizen Game 的缩写。这样设计的属于游戏引擎的类都会加入 TG 做为标识。
 
3 ,类图
下图是对游戏循环涉及到的各类之间的关系。
 

4 ,相关的类和接口
下面对实现游戏循环的一些基本的接口和类进行介绍:
1 ITGStateListener 类, I 表示是一个接口类 (Interface) 。这个类封装了游戏的三种状态,分别是处理事件、更新逻辑和渲染绘制。游戏模块只需要实现这个接口,进行注册后就可以接到来自游戏循环的通知,在各个处理函数中进行相应的处理就可以了,从而驱动游戏运行。
class ITGStateListener {
public :
    virtual ~ITGStateListener(){};
    virtual void HandleEvent() = 0;
    virtual void UpdateLogic( int frameInterval) = 0;
    virtual void Draw() = 0;
};
 
2 TGLoopBase 类,这是游戏循环的基类,实现各种游戏循环都可以通过继承这个类来实现循环,它封装了游戏循环的一些基本方法和成员。这个类包含一些纯虚函数,所以是不能被实例化的。
class TGLoopBase {
public :
    TGLoopBase();
    virtual ~TGLoopBase();
    virtual result Construct( void ) = 0;
 
public :
    virtual void SetFrameInterval( int interval);
    virtual void SetStateListener( ITGStateListener * pListener);
    virtual void Start() = 0;
    virtual void Pause() = 0;
    virtual void Stop() = 0;
 
protected :
    int __frameInterval ;
    ITGStateListener * __pStatusListener ;
};
 
3 TGTimerLoop 类,这是游戏循环对应的一个具体的类,它继承了 TGLoopBase ,并使用 Osp::Base::Runtime:: Timer 来实现循环功能。
 
class TGTimerLoop : public TGLoopBase ,
                    public Osp::Base::Runtime:: ITimerEventListener
{
public :
    TGTimerLoop();
    virtual ~TGTimerLoop();
    result Construct( void );
public :
    virtual void OnTimerExpired(Osp::Base::Runtime:: Timer & timer);
 
public :
    void Start();
    void Pause();
    void Stop();
 
private :
    Osp::Base::Runtime:: Timer * __pTimer ;
};
 
5 ,循环实现
游戏循环是在 TGTimerLoop 中实现的,主要在 OnTimerExpired() 函数中完成循环逻辑,其它的像 Start(),Pause(),Stop() 等函数对循环进行控制。
TGTimerLoop::TGTimerLoop () : __pTimer (NULL)
{
 
}
 
TGTimerLoop::~TGTimerLoop ()
{
if (__pTimer)
{
    delete __pTimer
__pTimer = NULL
}
}
 
result
TGTimerLoop::Construct ( void )
{
    result r = E_SUCCESS;
 
    __pTimer = new Timer ();
    r = __pTimer -> Construct (* this );
 
 
    return r;
}
 
void
TGTimerLoop::OnTimerExpired (Osp::Base::Runtime:: Timer & timer)
{
    long long startTime = 0;
    Osp::System:: SystemTime :: GetTicks (startTime);
 
    if ( __pStatusListener )
    {
       __pStatusListener ->HandleEvent();
       __pStatusListener ->UpdateLogic( __frameInterval );
       __pStatusListener ->Draw();
    }
 
    long long endTime = 0;
    Osp::System:: SystemTime :: GetTicks (endTime);
 
    long long deltaTime = endTime - startTime;
 
    AppLog( "deltaTime %ls" , LongLong :: ToString (deltaTime). GetPointer ());
 
    int leftTime = __frameInterval - deltaTime;
    if (leftTime > 0)
    {
       __pTimer -> Start (leftTime);
    }
    else
    {
       __pTimer -> Start (1);
    }
 
}
 
void
TGTimerLoop::Start ()
{
    if ( __pTimer )
    {
       __pTimer -> Cancel ();
       __pTimer -> Start ( __frameInterval );
    }
}
 
void
TGTimerLoop::Pause ()
{
    if ( __pTimer )
    {
       __pTimer -> Cancel ();
    }
}
 
void
TGTimerLoop::Stop ()
{
    if ( __pTimer )
    {
       __pTimer -> Cancel ();
    }
}
 
其中的 OnTimerExpired() 函数中的代码就是游戏循环的关键代码,从代码中可以看出这个实现的是上篇文章提到的“基于时间的固定间隔游戏循环”。