使用Flex和Actionscript开发Flash游戏 —— 双缓冲渲染

使用Flex和Actionscript开发Flash游戏 —— 双缓冲渲染

在该系列的第一篇文章中,我们创建了Flex程序类。这一部分,我们将加上一些states和一个双缓冲渲染流程。 States就如同它自己的名字那样去解释:它表示一个程序所包含的所有状态。

  在该系列的第一篇文章中,我们创建了Flex程序类。这一部分,我们将加上一些states和一个双缓冲渲染流程。
  States就如同它自己的名字那样去解释:它表示一个程序所包含的所有状态。例如:一个在线商店会拥有一个状态让顾客浏览商店,还有一个状态查看某一特定商品的详细内容。我们的游戏也拥有一些状态,包含:主菜单、游戏自身、关底信息以及一个排行榜。
  Flex自身支持多状态(states)。这些状态之间可以相互变化,并伴随着变化动画。但是状态的变化也离不开程序员设置不同状态间功能的变更,这种变化并不必须依赖于用户界面的变化。修改Application的currentState属性将导致状态的转变,同时为enterState和exitState两个事件编写相应的方法,我们就可以更新游戏内部相应的各状态了。
  双缓冲是一种用于避免程序直接绘制到屏幕产生画面不连贯的技术。正如它的名字一样,它采用两个绘制缓冲空间来绘制最终图像:一个久驻内存的后置缓冲和一个用于屏幕显示的前置缓冲。你可以这样理解,后置缓冲是一个草稿画板,你可以在上面绘制独立的元素来组成最终的场景。一旦一帧画面在后置缓冲区中绘制完成,它就将图像拷贝的前置缓冲区中,然后屏幕显示前置缓冲区中的内容。
  接下来我们看看这个概念在Flex中如何实现。
main.mxml <?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
width="600"
height="400"
frameRate="100"
creationComplete="creationComplete()"
enterFrame="enterFrame(event)"
currentState="MainMenu">
<mx:states>
<mx:State
name="Game"
enterState="enterGame(event)"
exitState="exitGame(event)">
</mx:State>
<mx:State name="MainMenu">
<mx:AddChild relativeTo="{myCanvas}" position="lastChild">
<mx:Button x="525" y="368" label="Start" id="btnStart" click="startGameClicked(event)"/>
</mx:AddChild>
</mx:State>
</mx:states>
<mx:Canvas x="0" y="0" width="100%" height="100%" id="myCanvas"/>
<mx:Script>
<![CDATA[
protected var inGame:Boolean = false;
public function creationComplete():void
{
}
public function enterFrame(event:Event):void
{
if (inGame)
{
GameObjectManager.Instance.enterFrame();
myCanvas.graphics.clear();
myCanvas.graphics.beginBitmapFill(GameObjectManager.Instance.backBuffer, null, false, false);
myCanvas.graphics.drawRect(0, 0, this.width, this.height);
myCanvas.graphics.endFill();
}
}
protected function startGameClicked(event:Event):void
{
currentState = "Game"
}
protected function enterGame(event:Event):void
{
GameObjectManager.Instance.startup();
inGame = true;
}
protected function exitGame(event:Event):void
{
inGame = false;
}
]]>
</mx:Script>
</mx:Application>
复制代码首先要注意currentState属性的加入。正如前面说过的,currentState属性定义了当前程序的状态(state)。我们将currentState设置为MainMenu,表示程序是由MainMenu状态开始的。
我们同样加入了mx:States元素。这个元素定义了程序所包含的所有子状态。这里我们定义了MainMenu和Game两种状态。在MainMenu状态中,最终用户将看到开始界面。而Game状态表示游戏本身。
这两个mx:State都拥有name属性。改变currentState属性的值,我们就可以完成状态之间的切换。Game状态包含了enterState和exitState两个事件。我们可以使用为这两个事件添加响应函数的方法来手工“同步”游戏内部逻辑。你看到,我们使用EnterGame函数来启动GameObjectManager(之后将提到)实例,并且设置内部标志inGame为true。这个标志在游戏渲染循环中使用,表示是否需要将游戏画面渲染到屏幕。ExitGame方法简单的将inGame标志设置为false,使用户界面不可见。
记得我提到过Flex中的各种状态可以进行切换?MainMenu状态展示了其简单的实现方法。mx:AddChild节点用于添加图形界面元素。在这里,我们添加一个按钮,使用户可以点击进入游戏。当我们离开MainMenu状态时,Flex会自动移除按钮而不需要任何其它代码和设置。
为了将画面渲染到屏幕,我们添加一个mx:Canvas元素。canvas(更具体的说是它的graphics属性)充当了双缓冲渲染流程中前置缓冲的角色。后置缓冲存在于GameObjectManager类中。在enterFrame函数中,我们调用GameObjectManager中的enterFrame方法,该方法允许将画面绘制到后置缓冲区中。每当一帧绘制完毕,我们使用canvas中graphics对象的clear, beginBitmapFill, drawRect和endFill方法将其绘制到canvas上。
GameObjectManager.as package
{
import mx.core.*;
import mx.collections.*;
import flash.display.*;
public class GameObjectManager
{
// double buffer
public var backBuffer:BitmapData;
// colour to use to clear backbuffer with
public var clearColor:uint = 0xFF0043AB;
/// static instance
protected static var instance:GameObjectManager = null;
// the last frame time
protected var lastFrame:Date;
static public function get Instance():GameObjectManager
{
if ( instance == null )
instance = new GameObjectManager();
return instance;
}
public function GameObjectManager()
{
if ( instance != null )
throw new Error( "Only one Singleton instance should be instantiated" );
backBuffer = new BitmapData(Application.application.width, Application.application.height, false);
}
public function startup():void
{
lastFrame = new Date();
}
public function shutdown():void
{
}
public function enterFrame():void
{
// Calculate the time since the last frame
var thisFrame:Date = new Date();
var seconds:Number = (thisFrame.getTime() - lastFrame.getTime())/1000.0;
lastFrame = thisFrame;
drawObjects();
}
protected function drawObjects():void
{
backBuffer.fillRect(backBuffer.rect, clearColor);
}
}
}
复制代码GameObjectManager对象承担着管理各种游戏元素的责任,包括敌人,玩家和各种背景元素。它也决定着后置缓冲区中哪些元素需要进行绘制。如果你记得前置缓冲器是由canvas元素实现的,最简单的方式就是将canvas作为一个Application的子节点直接加入。后置缓冲区由BitmapData对象实现,这样我们可以快速直接的操作像素来绘制最终图像。
clearColor属性设置的颜色表示用于在场景建立好之前,清除后置缓冲区的颜色。最终整个后置缓冲区将会被游戏元素覆写,使得clearColor完全不相关,但是目前它非常重要,因为它将建立一块最终帧。0xFF0043AB代表深蓝色。前两位代表alpha值,后6位代表红绿蓝值。
静态的instance属性用于实现单件模式。我们的程序中只需要一个GameObjectManager实例,引用这个静态的属性将保证我们只会创建一个GameObjectManager实例。单件模式是程序设计范例中非常常见,尽管Actionscript不支持protected构造函数,但是单件模式依然十分有用(一旦你看到instance属性,这个类很可能就是按照单件模式设计的)。
lastFrame属性存储了最后帧渲染完毕的时间。跟踪这个时间,我们就可以知道最后一帧于当前帧之间的时间间隔,使得我们可以以此更新游戏元素。尽管目前我们没有任何游戏元素,在enterFrame方法中,我们计算了帧于帧之间的时间。lastFrame时间就是在调用startup时被重置。这是由于当整个游戏不在Game state状态下时,GameObjectManager并不更新。如果我们不重置lastFrame,下一关的第一帧将等于玩家在关间菜单所花的时间。最好要避免玩家在第一帧时终止退出。
所以,我们做了些什么呢?为了实现各种状态,我们创建了主菜单画面,可以使用按钮进入游戏。游戏中我们实现了双缓冲模型,可以绘制一个蓝色背景。接下来,我们就会开始做有趣的事情了,在屏幕上绘制一些东西。
最终结果: http://flexfighters.sourceforge.net/flexfighters2.html
源代码:
https://sourceforge.net/project/ ... p;release_id=631382
转自:http://flash.9ria.com/thread-35268-1-1.html

阅读更多
个人分类: Flex AS3
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭