bada 2D游戏编程之六——一个基于线程的游戏循环

本文介绍了如何在bada平台上利用线程机制实现基于时间的游戏循环。通过创建一个工作者线程,并在其中运行游戏循环,可以确保游戏逻辑的平滑执行。文章详细展示了TGThreadLoop类的设计与实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

bada 2D游戏编程之六——一个基于线程的游戏循环

 

上篇文章中用定时器实现了一个“基于时间的固定间隔游戏循环”,这篇文章还是在上篇文章的基础上,用bada平台提供的线程机制来实现这么一个游戏循环。这中实现方式的主要特点是采用了多线程编程的机制,用单独的一个线程来实现游戏循环,在这个线程当中进行HandleEvent(),UpdateLogic()Draw()的处理。

 

1, bada平台线程机制

bada平台的线程功能是由Osp::Base::Runtime::Thread类来提供的。在bada平台上存在2种类型的线程,

一种是事件驱动(Event-driven)线程,这种类型的线程运行起来之后,它的Run()函数一直运行着,直到停止线程运行才会从Run()函数返回退出,同时它在Run()函数中进行事件监听,当其它运行的线程通过调用Thread::SendUserEvent()来向它发送事件通知后,它在Thread:: OnUserEventReceivedN ()函数对接收到的事件进行处理。

 

还有一种是工作者(Worker)线程,这种线程需要和Osp::Base::Runtime::IRunnable结合使用,工作者线程在执行时会调用IRunnable::Run()函数,这样将需要运行的代码放到IRunnable::Run()函数中就可以了,在这里Run()函数中的代码是按照线性的方式被执行一次,执行完成后线程也就结束了。

 

在这里我们选择工作者线程来实现游戏循环,因为事件驱动线程与其它线程之间采用的是异步的通信方式,无法与基于定时器的实现接口保持一致;而采用工作者线程,可以在Run()函数中加入一个While()死循环,再加入线程的Sleep()功能就能够实现定时循环了,实现方式上可以和基于定时器的方式保持一致。

 

2, 线程的使用方法

在实现循环时用到的Osp::Base::Runtime::Thread的主要方法:

函数

功能描述

Thread(void)

默认构造函数

Construct(IRunnable& targe, long stackSize, ThreadPriority priority)

初始化函数,传入IRunnable

Start(void)

开始线程

Sleep(long milliSeconds)

暂停线程执行

 

IRunnable提供的方法:

函数

功能描述

Run(void)

通过被线程回调来执行函数中的代码

 

这样将需要被线程执行的代码块放到IRunable::Run()函数中,线程开始执行后就会调用IRunable::Run()方法,执行其中的代码,所以游戏循环的实现代码都是放在了IRunable::Run()函数中。

 

3,类图

下图是游戏循环涉及到的各类之间的关系。

4,相关的类和接口

下面对实现游戏循环的一些基本的接口和类进行介绍:

1TGThreadLoop类,这是游戏循环对应的一个具体的类,它继承了TGLoopBase,并使用Osp::Base::Runtime::Thread来实现循环功能。

 

classTGThreadLoop : publicTGLoopBase,

                    public Osp::Base::Runtime::IRunnable

{

public:

    TGThreadLoop();

    virtual ~TGThreadLoop();

    result Construct(void);

public:

    virtual Osp::Base::Object* Run(void);

public:

    void Start();

    void Pause();

    void Stop();

private:

    Osp::Base::Runtime::Thread* __pThread;

    bool__isRunning;

    bool__isPaused;

};

 

5,循环实现

游戏循环是在TGThreadLoop中实现的,主要在Run()函数中完成循环逻辑,其它的像Start(),Pause(),Stop()等函数对循环进行控制。

 

TGThreadLoop::TGThreadLoop() : __pThread(NULL),__isRunning(true),__isPaused(false)

{

}

 

TGThreadLoop::~TGThreadLoop()

{

    if(__pThread)

    {

       delete__pThread;

       __pThread = NULL;

    }

}

 

result

TGThreadLoop::Construct(void)

{

    result r = E_SUCCESS;

 

    __pThread = newThread();

    __pThread->Construct(*this,THREAD_PRIORITY_HIGH);

 

    return r;

}

 

Osp::Base::Object*

TGThreadLoop::Run(void)

{

    while(__isRunning)

    {

       longlong startTime = 0;

       Osp::System::SystemTime::GetTicks(startTime);

 

       if(__pStatusListener && !__isPaused)

       {

           __pStatusListener->HandleEvent();

           __pStatusListener->UpdateLogic(__frameInterval);

           __pStatusListener->Draw();

       }

       longlong endTime = 0;

       Osp::System::SystemTime::GetTicks(endTime);

 

       longlong deltaTime = endTime - startTime;

 

       int leftTime = __frameInterval - deltaTime;

       if(leftTime > 0)

       {

           __pThread->Sleep(leftTime);

       }

       else

       {

           //Do Nothing

       }

    }

    return NULL;

 

}

 

void

TGThreadLoop::Start()

{

    __isPaused = false;

    __pThread->Start();

}

 

void

TGThreadLoop::Pause()

{

    __isPaused = true;

}

 

void

TGThreadLoop::Stop()

{

    __isRunning = false;

}

 

TGThreadLoop类中通过引起了__isPaused__isRunning这两个标志位来对线程的状态进行标识,从而实现对游戏循环的控制。

 

6,总结

下面前面的两种实现方式之间的类图关系,

 

可以看出这两种实现方式在接口上保持了完全一致,仅仅是实现的方式不一样,这样即使在开发过程中将这两种游戏循环进行相互替换也不需要改变任何接口,非常的方便。

 

下面是这两种实现方式之间的一个简单比较:

基于定时器的游戏循环,按照这种机制开发的游戏是运行在单线程环境之中,所有的任务都是交给程序的主线程来处理。这种方式的好处是实现简单,不需要考虑多线程编程;但也可能存在主线程处理任务过多而造成游戏阻塞的情况。

基于线程的游戏循环,采用的是多线程编程,主线程用于相应用户的输入事件,而循环线程则负责游戏的运行,可以避免主线程阻塞的情况;但是引入的这个线程一直运行着,非常的消耗系统资源,最直接的表现就是游戏比较耗电。

 

大家可以根据自己的需要来选择合适的实现方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值