使用FLEX 和 Actionscript 开发FLASH 游戏2

来源:互联网 发布:网上赚钱的软件 编辑:程序博客网 时间:2024/04/30 02:06

使用FLEX 和 Actionscript开发FLASH 游戏—双缓冲绘制

“使用FLEX开发游戏”系列之二

写自Matthew Casperson Casperson

2008年10月31日出版

在本系列的第一部分,我们写出了初始的flex应用程序类。在第二部分,我们将添加状态和双缓冲绘制过程。

在本系列的第一部分,我们写出了初始的flex应用程序类。在第二部分,我们将添加状态和双缓冲绘制过程。

状态,相当不言自明,他们代表了一个程序能处于的不同状态。例如,购物车可能有一个代表浏览商店的状态,还有一个代表查看某个特殊项目的状态,我们的游戏也将有许多状态,其中包括主菜单,本身的游戏游玩,水平总结的结束语,可能还有一个高得分的呈现。

Flex包括状态的本地支持。状态被设计成从一个GUI(图形用户界面)向另一个GUI的在理念中的转换,他们有我们在不同状态之间转换所需要的功能,虽然状态不必一定有任何GUI 组件。修改应用程序的当前状态的属性将触发一个状态的改变,通过给与进入状态和退出状态事件有关的函数增加必须的开始和结束代码,我们能够更新内部的游戏状态以达到匹配。

双缓冲是一种常用的科技,用来消除因为直接画屏幕而产生的视觉割裂。它因为使用两个图像缓冲来绘制最终的图片而得名。一个缓冲位于内存(后台缓存),另一个被显示在屏幕上的缓冲(前台缓冲)

你可以把后台缓冲当做一种高速暂存存储器,被用来绘制最终的屏幕而创建的一个单独的元素。当一个帧一被画,它就被一个操作复制到前台缓冲。然后屏幕显示前台缓冲的内容。

那么就让我们看看在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="btn Start"

                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>

首先要注意的事是增加到mx:Application 元素的currentState(当前状态)属性。上面已经提到过,应用程序对象的当前状态属性定义了程序的当前状态。通过设置次属性为MainMenu(主菜单)我们可以得出程序以主菜单状态开始。

我们还增加了一个mx:states元素。这个元素通过子元素mx:State定义了程序能够处于的状态。我们定义了开始的两个状态:MainMenu(主菜单)和Game(游戏)。在主菜单状态,最终用户将看见游戏的开始界面,游戏状态代表了游戏运行它本身。

两个mx:State元素都有一个名字属性。这个属性是状态的名字,通过把应用程序对象的当前状态改到某个名字,我们能够转换到相应的某个状态。游戏状态还包括另外两个属性:enterState(进入状态)和 exitState(退出状态)。通过把函数和事件联系在一起,我们有机会把游戏内部逻辑手工同步到这个状态。就像你能看见的我们使用EnterGame(进入游戏)这个函数来开始GameObjectManager(稍后有此类的更多介绍),来设置内部标志inGame为真。inGame标志被用来在绘制循环中允许游戏画屏幕。ExitGame(退出游戏)函数仅仅将inGame设置为假,来显示GUI.

还记得我怎么提起在flex中状态被设计为理念上GUI的转换。主菜单状态显示这很容易。mx:AddChild元素被用来为状态增加一个GUI元素。在这种情况下,我们增加一个按钮,玩游戏者能够点击它进入到游戏里面。但是一旦我们离开了主菜单状态,flex将自动地移去这个按钮,而不用多余的代码或者任何努力。

为了让我们能够绘制屏幕我们增加了mx:Canvas(画布)元素。画布(或者更具体地说:它的画像属性)将在双缓冲绘制过程中起到前台缓冲的作用。后台缓冲存在在GameObjectManager类中。在enterFrame函数里我们调用了GameObjectManager的enterFrame函数,此函数让程序绘制后台缓冲。帧一被画出,我们就取后台缓冲,使用画布的图像属性的clear,beginBitmapFill,drawRect,endFill函数把后台缓冲画到画布上。

 

 

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 statci var instance:GameObjectManager = null;

        //the last frame time

        protected var lastFrame:Date;

        static public function get Instance():GameObjectManager

        {

            if(instacne == 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 Data();

        }

        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)对象负责管理组成最终游戏的各个元素,比如:敌人、游戏者和各种不同的背景元素,它还负责管理画这些元素的后台缓冲,如果你回想起前台缓冲是把它作为一个画布元素来实现的,这是因为一个画布能够被作为应用程序的一个孩子直接加到应用程序里是很方便的。后台缓冲是把它作为一个位图数据对象来实现的。这使得我们能够直接快速地复制作为最后图像的像素。

   clearColor属性指定了图像建立起来之前用来擦除后台缓冲用的颜色。最终整个后台缓冲将被游戏元素所覆盖,和这个颜色不同,但是现在这个颜色很重要,因为它将把最终的帧涂成一整块。值0xFF0043AB 代表深蓝色。最前面的两位16进制值(在0x之后的)代表了alpha:FF 表示不透明,00表示透明。随后的六位16进制值构成了红(00)绿(43)蓝(AB)组件。

   静态instance属性和Instance函数一起使用来实现单态设计模式。基本上我们在程序里总是只需要一个GameObjectManager对象存在(顾名思义)。通过参考GamaeObjectManager里的instance 属性,我们可以总是只有一个GameObjectManager生成。单态设计是一种相当普通的程序设计模式,当actionscript 缺少对私有构造器的支持它仍然可以作为一个有用的自我测试工具(只要你看见一个Instance属性,极有可能对象是单态设计模式。

   lastFrame属性仅仅存储了最后一帧被绘制的时间。通过保留时间轨迹,我们能够判断最后一帧和当前帧的相隔时间,这最终相反又允许我们依据这个时间来更新游戏元素。即使我们还没有任何游戏元素,我们仍然在enterFrame函数中以秒来计算帧之间的时间。当调用startup函数时,lastFrame时间被重置,这是因为程序不在游戏状态时GameObjectManager不能被更新。如果我们不去重置lastFrame,下一级的第一帧时间将和游戏者在菜单的各个级别之间花费的时间相等。游戏者能够在第一帧通过级别直接结束游戏,而这可以被很好地避免。(通过重置lastFrame)

   那么现在我们完成了什么呢?通过实现状态我们生成了一个菜单屏幕,游戏者能够从这里通过点击按钮进入游戏。“游戏”本身只是一个双缓冲的实现,这里还只是画了一个蓝色的背景。最后通过实现状态和绘制,我们能够做到一个有趣的事情:画屏幕。

   最终结果在http://flexfighters.sourceforge.net/flexfighter2.html请在以下链接下载源代码:https://sourceforge.net/project/showfiles.php?group_id=241490&package_id=293860&release_id=631382

  


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/literza/archive/2009/06/04/4241377.aspx