2

我尝试使用双缓冲区来开发一个简单的 Flash 游戏来绘制动画。

重绘发生在 Event.ENTER_FRAME 被触发时。

用于双缓冲的后缓冲是 BitmapData 类型。

动画非常简单:我在后台缓冲区中绘制了一个 20x20 像素的位图,随着 x 坐标的增加,它应该从画布的左侧平滑地移动到右侧。这基本上可以正常工作,但如果你仔细观察,你会发现这个运动有很大的中断。这似乎与帧速率无关,因为它经常超过 60。平滑移动的中断对于动画来说是不可接受的,但我很确定我在双缓冲方面没有做错任何事情,所以我我害怕这可能是 Flash 播放器的问题或其他什么...如果不是这种情况,我会很欣慰

请看一下显示简单动画的 swf:

https://dl.dropbox.com/u/55967135/test.swf

(顺便说一句。当运动基于两帧之间的时间时,动画的中断也不会消失 - 现在每帧恒定 2 个像素。)

我上传了一个非常轻量级的 flash builder 项目,包括上面 swf 的整个源代码: https ://dl.dropbox.com/u/55967135/test.zip

    public function enterFrame():void               
      {

           // Calculate the time since the last frame  (NOT USED IN THE EXAMPL PROGRAM)                   
           var thisFrame : Date = new Date();               
           var dT : Number = (thisFrame.getTime() - lastFrame.getTime())/1000.0;               
           lastFrame = thisFrame;          

           // erase backBuffer
           backBuffer.fillRect(backBuffer.rect, 0xFFFFFFFF);


           // set new postion of the small testimage
           if (this.pos > 600 || this.pos < 0) {
                this.direction = !this.direction;
           }

           // increase / decrease vertical position
           if (this.direction) {
                this.pos += 2;
           } else {
                this.pos -= 2;
           }

           //trace(pos);
           // draw small test image at postion "offset"
           backBuffer.copyPixels(     this.testGraphic.bitmap.bitmapData, 
                                         this.testGraphic.bitmap.bitmapData.rect, 
                                         new Point(pos, 0.0));               
      }

enterFrame() 是我的类 GraphicsController 的一个方法,它处理双缓冲。它由应用程序的 enterFrame(event) 方法启动:

        public function enterFrame(event:Event):void
           {
                GraphicsController.Instance.enterFrame();     
                myCanvas.graphics.clear();
                myCanvas.graphics.beginBitmapFill(GraphicsController.Instance.backBuffer, null, false, false);                              
                myCanvas.graphics.drawRect(0, 0, this.width, this.height);                              
                myCanvas.graphics.endFill();
                stage.invalidate();
           }  

帮助将不胜感激

谢谢

4

2 回答 2

1

在 chrome 上运行对我来说非常流畅,但我知道你描述的效果。我在 Firefox 中的一个应用程序中体验过它,但我使用的是显示列表而不是位图数据。我的问题是因为将显示对象移动了不到一个像素,而 flash 对此并不满意。一旦我将对象缩放到 0.99,它就被修复了。

您可以尝试绘制 dT 并查看它是否稳定。它应该是 16.6666(或 0.0166),因为如果它在波动,那么您以 60fps 的速度运行,那么某些东西会导致输入帧事件被推回。

这也可能有用:http ://www.craftymind.com/2008/04/18/updated-elastic-racetrack-for-flash-9-and-avm2/

于 2012-09-07T13:31:22.717 回答
1

首先,您的 backBuffer 没问题,您只需在更新之前 lock() 它,然后在完成更新后 unlock() 它。接下来,当您可以使用 Bitmap 对象时,为什么要重绘图形?因此,您保留 GraphicsController.enterFrame() 原样,在方法代码的开头和结尾添加一个backBuffer.lock();backBuffer.unlock();调用,并在初始化阶段使用单个 Bitmap 对象,该对象将在 enterFrame 调用期间自动更新。应用程序的 enterFrame() 中的所有其他内容都将变得无用。

基本上我所说的是将你的画布从 Shape 类型更改为 Bitmap 类型,该位图将硬链接到 GraphicsController 的 backBuffer 并将自动更新。

于 2012-09-07T13:32:11.553 回答