定时器设计:定时器的设计和实现



开始想学习DX编程时个朋友介绍了这个网站WebSite平时在里面也学习了不少内容自己经常听同事说起定时器而自己第次使用时所设计个定时器是问题多多经过些整理总结和研究设计了个新定时器拿出来和大家共享也免了总是拿来而不付出:}

定时器个应该来说游戏最基本常用功能易用和否直接影响了开发效率;功能完备和否直接导致实现难易;性能好坏直接影响到了游戏运行表现那么如何实现个简单易用、功能完善、性能较好定时器呢?

prefix = o />

首先先看功能完善



定时器那么我们希望他能有最基本定时功能:指定段时间以后发生某个事件

然后如果所有事件都是定时间以后发生我们经常可能由于某个操作会取消前面事件或无效前面事件比如:定时炸弹段时间以后会爆炸在爆炸以前是可以拆毁那么就需要能取消或无效某个定时

这就是个最基本定时器能够设定时间能够取消设定就有如下接口:

=GramE>Time( time,… 可能还不明确改为: timeEvent( time,Event &e)

cancelTime( timeID) 名字: =GramE>void cancelEvent( e)

但是往往我们很多游戏希望能暂停然后从暂停点继续

=GramE>void pauseTime

=GramE>void resumeTime

如何暂停就有个游戏时间、系统时间(时间获取般都是以系统时间为基础)了

=GramE>unsigned playTime

=GramE>unsigned sysTime

功能上就有了:定时、取消、暂停、继续、查询作为游戏开发已经相对比较充分了



再看简单易用





我们在前面引入了个事件概念Event这样个类如果按照前面思路那么就需要在时间到了发生时间

Event::=GramE>onOcured

实际使用中发现自己处理自己发生了不是个好方式我们再通过个中转:

EventHandler::=GramE>occurred(Event &e)

使用时每个事件都要有个对象而且是临时创建还要销毁并且要处理必需继承EventHandler使用相当不方便需要最好不要继承也不需要创建对象

设计模式里有个proxy可以借鉴我们改为从proxy去取发生了事件

=GramE>bool EventProxy::fetchEvent(Event &e)

=GramE>void EventProxy::addOccured(Evene &e)

我们再使用时只需要fetch看有没有了有、处理取消也用proxy:

=GramE>void EventProxy::cancelEvent( e)

干脆更方便易于理解我们把所有借口都放这个proxy里算了不过不能叫EventProxy

=GramE> Timer:: timeEvent( time,Event &e)

=GramE>void Timer::cancelEvent( e)

=GramE>void Timer::pauseTime

=GramE>void Timer::resumeTime

=GramE>bool Timer::fetchEvent(Event &e)

这样所有操作都只需要通过Timer不过为了防止多份事件需要采用singleton(单件)模式同时把时间获取也加进来



=GramE>typedef unsigned U32;

=GramE> TimeOffice

{

=GramE>public:

/**

* 定时邮递

* @ 邮递定时器

* @para ms 间隔毫秒

* @para receiver 接收对象

* @para packet 邮递包裹

* @para count 邮递次数(< 0 每隔ms毫秒邮递次包裹)

*/



U32 =GramE>timePost( U32 ms,const void *receiver,

=GramE>const Packet &packet, count = 1 );

/**

* 取消邮递(取消指定定时器)

* @ 定时器存在=GramE>否

* @para timer 邮递定时器

*/

=GramE>bool cancelPost( U32 timer );

/**

* 取消邮递(取消发往指定接收对象所有定时器)

* @ 被取消邮递定时器个数

* @para receiver 接收者



*/

U32 =GramE>cancelPost( const void *receiver );

/**

* 邮递到了包裹数

* @ 已到达接收者但尚未取出包裹数目

* @para receiver 包裹接收者

*/

U32 =GramE>arrivedPackets( const void *receiver );

/**

* 取邮递包裹

* @ 有可取包裹=GramE>否

* @para receiver 接收者



* @para packet 取出包裹

*/

=GramE>bool fetchPacket( const void *receiver,Packet &packet);

/**

* 丢弃接收者所有已邮递包裹

* @ 丢弃包裹数目

* @para receiver 接收者

*/

U32 =GramE>discardPackets( const void *receiver );



/**

* 生成时间戳

* @ 基于操作系统或游戏时间戳



* @para system 是否采用依赖操作系统时间戳

*/

=GramE> U32 stampTime( bool system = true );

/**

* 暂停游戏时间流逝

* @

*/

=GramE> void pause( void );

/**

* 启动被暂停游戏时间流逝

* @

*/



=GramE> void resume( void );



/**

* 申请定时器例子

* @ 定时器例子

*/

=GramE> TimeOffice *getInstance( void );

/**

* 释放定时器

* @

*/

=GramE> void release( void );





=GramE>private:

=GramE>TimeOffice( void );

~=GramE>TimeOffice( void );



=GramE>void step( void );

};



最后是性能这个问题个比较难以=GramE>象前面泛泛而谈



我们学过数据结构知道空间和运算性能通常是互斥既要空间利用少又要运算性能高通常是比较困难幸好我们这里fetchtimediscard等基本都是列表操作由于cancel可能从中间删除事件那么我们可以选择std::list舍弃std::vector具体实现就看大家如何写了



通篇没有什么内容只是个研究过程和最后设计结果如果对此定时器有什么疑问或讨论或对文章字句不解者或对文章描述很烦者都可建议修改敬请在论坛发表帖子个人会抽时间去=GramE>论讨和大家起讨论比较遗憾自己机器上没有UML工具因此也没有相关“协作图”可供大家图形感觉(实在太过粗浅这里不敢擅用“理解”词)

如果本文能对大家以后游戏开发学习或游戏实际开发有所帮助个人将深感高兴并抽空再和大家起讨论windows游戏基本流程改进恳请宝贵意见于论坛个人已准备好cn_zhangJW用户接受大家臭鸡蛋了:}





Tags:  定时器设计

延伸阅读

最新评论

发表评论