登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

游戏记忆...

竹石 Blog

 
 
 

日志

 
 

转个很好的教程-Optimized AS3 Game Timer Loop  

2010-01-16 19:47:46|  分类: as/flash |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
原文 http://www.8bitrocket.com/newsdisplay.aspx?newspage=10248

摘取重要的部分做点简单的翻译把  我的e文也很差阿   注意我这并非直译,e文好的最好看原文

这个主要是用来解决游戏在不同的播放器中fps不稳定。

在游戏循环中增加3步优化:1。在使用copyPixels 像素前先lock画布,操作后在调用unlock   2。实现一个基于渲染计时器的sleep  3。确保游戏循环中的update都是在每次事件后而不是每frame后。

1。 BitmapData.lock and BitmapData.unlock
这个原理就是在调用BitmapData.lock后,当对这个BitmapData执行多次copyPixels操作时flash会停止所有引用这个BitmapData对象的刷新,在调用BitmapData.unlock后所有改变才会在引用这个BitmapData的对象上体现。
下面的代码中
  drawBackground();
    drawPlayer();
    drawRocks();
    drawMissiles();
    drawParts();
这5个操作flash只会在canvasBD.unlock();后执行一次更新,不是在每个操作后都刷新显示。

checkKeys();
    updatePlayer();
    updateRocks();
    updateMissiles();
    checkCollisions();
    canvasBD.lock();
    drawBackground();
    drawPlayer();
    drawRocks();
    drawMissiles();
    drawParts();
    canvasBD.unlock();

2. 基于计时器的Sleep
这个好像在Andrew 那个最流行的书里有(我没看过...)。
代码如下:
  1. private function runGame(e:TimerEvent) {
  2.     _beforeTime = getTimer();
  3.     _overSleepTime = (_beforeTime - _afterTime) - _sleepTime;


  4.     checkKeys();
  5.     updatePlayer();
  6.     updateRocks();
  7.     updateMissiles();
  8.     checkCollisions();
  9.     canvasBD.lock();
  10.     drawBackground();
  11.     drawPlayer();
  12.     drawRocks();
  13.     drawMissiles();
  14.     drawParts();
  15.     canvasBD.unlock();
  16.    
  17.     _afterTime = getTimer();
  18.     _timeDiff = _afterTime - _beforeTime;
  19.     _sleepTime = (_period - _timeDiff) - _overSleepTime;        
  20.     if (_sleepTime <= 0) {
  21.         _excess -= _sleepTime
  22.         _sleepTime = 2;
  23.     }        
  24.     gameTimer.reset();
  25.     gameTimer.delay = _sleepTime;
  26.     gameTimer.start();

  27.     while (_excess > _period) {
  28.         checkKeys();
  29.         updatePlayer();
  30.         updateRocks();
  31.         updateMissiles();
  32.         checkCollisions();
  33.         _excess -= _period;
  34.     }
  35.    
  36.     frameTimer.countFrames();
  37.     frameTimer.render();
  38.     if (aRock.length ==0 && aActiveParticle.length==0) stopRunningGame();
  39.    
  40. }


FRAME_RATE  每秒的刷新次数,我设为40
_period 每次循环所有操作预定的毫秒数  即25 (1000/40)     
_beforeTime and _afterTime 辅助变量,用来计算实际的执行时间,我们希望这个时间小于25ms(or _period value).
_timeDiff the _afterTime and the _beforeTime的差
_sleepTime = period (25) -  _timeDiff.
_overSleepTime 用来校正sleepTime
_excess 保存所有处理时间, 当_excess 大于period (25),我们将执行额外的checkeys(), update(), and check collisions() ,但不渲染这些对象。


3. UpdateAfterEvent()
通过调用TimerEvent .updateAfterEvent() ,可以强迫Flash 立即刷新屏幕。用这种方法我们可以设置游戏的Frame Rate为一个相对较低的值,而游戏却可以以较高的Frame Rate运行。
如游戏中有一个18 FPS的动画,而游戏需要以30FPS运行,这时我们可以设置这个flash的Frame Rate为18, 而上面代码中的FRAME_RATE设为30,这样动画以18 FPS播放,而游戏是以30 FPS运行。 (就是代码的最后面几行)   终于完了.......
  1. private function runGame(e:TimerEvent) {
  2.     _beforeTime = getTimer();
  3.     _overSleepTime = (_beforeTime - _afterTime) - _sleepTime;


  4.     checkKeys();
  5.     updatePlayer();
  6.     updateRocks();
  7.     updateMissiles();
  8.     checkCollisions();
  9.     canvasBD.lock();
  10.     drawBackground();
  11.     drawPlayer();
  12.     drawRocks();
  13.     drawMissiles();
  14.     drawParts();
  15.     canvasBD.unlock();
  16.    
  17.     _afterTime = getTimer();
  18.     _timeDiff = _afterTime - _beforeTime;
  19.     _sleepTime = (_period - _timeDiff) - _overSleepTime;        
  20.     if (_sleepTime <= 0) {
  21.         _excess -= _sleepTime
  22.         _sleepTime = 2;
  23.     }        
  24.     gameTimer.reset();
  25.     gameTimer.delay = _sleepTime;
  26.     gameTimer.start();

  27.     while (_excess > _period) {
  28.         checkKeys();
  29.         updatePlayer();
  30.         updateRocks();
  31.         updateMissiles();
  32.         checkCollisions();
  33.         _excess -= _period;
  34.     }
  35.    
  36.     frameTimer.countFrames();
  37.     frameTimer.render();
  38.     if (aRock.length ==0 && aActiveParticle.length==0) stopRunningGame();
  39.     e.updateAfterEvent();
  40. }
  评论这张
 
阅读(440)| 评论(2)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018