天天看點

使用FLEX和Actionscript開發FLASH 遊戲-位圖動畫

使用FLEX和Actionscript開發FLASH 遊戲-位圖動畫

   在第六部分我們增加了碰撞檢測。在第七部分我們将增加動畫來允許我們包含一些好的爆炸效果。  

在第六部分我們介紹了碰撞檢測,它讓我們能擊毀螢幕上的敵機。但是敵機隻是消失了,這個效果有點令人不滿意。在這篇論文中我們将增加動畫,這讓我們增加了一些漂亮的爆炸效果。

   如果Flash有個著名的地方,那它就是動畫。Flex确實允許你使用同樣的基于動畫的矢量圖,這是Flash著名之處,然而對于我們的遊戲我們将使用基于動畫的曆史相當悠久的幀。這麼做有兩個原因。第一是基于動畫的幀更容易實作,更加适合我們做的遊戲的風格。第二個是我不是一個美術家,不得不用我能在網絡中找到的免費的材料,這裡我找到了基于幀的材料。

   上面的圖像說明了我所說的基于動畫的幀的含義。這是一連串的幀,按照順序來示範,以生成一個動畫。你還在學校時在你的教科書的頁角畫過一些小的動畫麼?那是相同的概念。

   要實作動畫我們首先需要給GraphicsResource類一些改變。現在讓我們看看。

GraphicsResource.as

package

{

    import flash.display.*;

    public class GraphicsResource

    {

        public var bitmap:BitmapData=null;

        public var bitmapAlpha:BitmapData=null;

        public var frames:int=1;

        public var fps:Number=0;

        public function GraphicsResource(image:DisplayObject,frames:int=0,fps:Number=0)

        {

            bitmap=createBitmapData(image);

            bitmapAlpha=createAplhaBitmapData(image);

            this.frames=frames;

            this.fps=fps;

        }

        protected function createBitmapData(image:DisplayObject):BitmapData

        {

            var bitmap:BitmapData=new BitmapData(image.width,image.height);

            bitmap.draw(image);

            return bitmap;

        }

        protected function createAlphaBitmapData(image:DisplayObject):BitmapData

        {

            var bitmap:BitmapData=new BitmapData(image.width,image.height);

            bitmap.draw(image,null,null,flash.display.BlendMode.ALPHA);

            return bitmap;

        }

    }

}

   這裡做的改變相當簡單。我們增加了兩個屬性:frames和fps。Frames屬性是在GraphicsResource中儲存的動畫圖像有多少幀的一個數目。使用上面得一個爆炸的例子,frames應該被設定為7。Fps屬性定義了動畫在每秒中顯示的幀數。

   GameObject類不知道動畫。如果你使用上面的圖像來初始化一個GameObject,整個圖像将被顯示在螢幕上,而不是一個動畫序列。為了産生動畫我們需要生成一個新的類:AnimatedGameObject。現在讓我們看看它的代碼。

AnimatedGameObject.as

package

{

       import flash.display.*;

       import flash.geom.*;

       import mx.collections.*;

       public class AnimatedGameObject extends GameObject

       {

              static public var pool:ResourcePool = new ResourcePool(NewAnimatedGameObject);

              protected var frameTime:Number = 0;

              protected var currentFrame:int = 0;

              protected var frameWidth:int = 0;

              protected var playOnce:Boolean = false;

              static public function NewAnimatedGameObject():AnimatedGameObject

              {

                     return new     AnimatedGameObject();

              }

              public function AnimatedGameObject()

              {

              }

              public function startupAnimatedGameObject(graphics:GraphicsResource, position:Point, z:int = 0, playOnce:Boolean = false):void

              {                  

                     this.playOnce = playOnce;                  

                     this.frameWidth = graphics.bitmap.width / graphics.frames;

                     startupGameObject(graphics, position, z);

              }

              override public function enterFrame(dt:Number):void

              {

                     if (inuse)

                     {

                            frameTime += dt;

                            if (graphics.fps != -1)

                            {

                                   while (frameTime > 1/graphics.fps)

                                   {

                                          frameTime -= 1/graphics.fps;

                                          currentFrame = (currentFrame + 1) % graphics.frames;

                                          if (currentFrame == 0 && playOnce)

                                          {

                                                 shutdown();

                                                 break;

                                          }

                                   }

                            }

                     }

              }

              override public function copyToBackBuffer(db:BitmapData):void

              {

                     if (inuse)

                     {

                            var drawRect:Rectangle = new Rectangle(currentFrame * frameWidth, 0, frameWidth, graphics.bitmap.height);

                            db.copyPixels(graphics.bitmap, drawRect, position, graphics.bitmapAlpha, new Point(drawRect.x, 0), true);

                     }

              }

              override protected function setupCollision():void

              {

                     collisionArea = new Rectangle(0, 0, frameWidth, graphics.bitmap.height);

              }

       }

}

   就像其它任何遊戲資源一樣,AnimatedGameObject類是從GameObject類繼承來的。為了顯示一個動畫我們覆寫了GameObjects類的三種函數:enterFrame,copyToBackBuffer和setupCollision。

   在enterFrame函數裡AnimatedGameObject保留了一個軌迹來儲存上一幀被示範後過了多久時間。一旦這個時間超過了在GraphicsResource中fps定義的值AnimatedGameObject就移到下一幀。這裡也有一個playOnce屬性,如果設定為真那麼一個完整的動畫被顯示後将觸發AnimatedGameObject來移除自身。這對于生成特效(比如爆炸)是很有用的,因為顯示一次就消失了。它将讓你作為一個編碼者能在遊戲中生成一種初始化後就不用幹預的對象來清除它自身。

   copyToBackBuffer僅僅在GameObject類的同一代碼上做了小小的改動來讓它僅僅拷貝graphics屬性引用的圖形的一部分。這部分同目前的幀有關系,是當我們在螢幕上示範一個動畫時從左到右的顯示的一幀。

   最後我們覆寫了setupCollision函數來定義collisionArea,它是動畫中一幀的大小,而不是整個圖檔的大小。

   這裡其餘的代碼(比如資源池和開始/結束函數)在前面章節已經讨論過,它們在此處的應用還是一樣。

   我們也需要給ResourceManager做些改變來适應動畫需要的特别的資訊。現在讓我們看看它的代碼。

ResourceManager.as

package

{

       import flash.display.*;

       public final class ResourceManager

       {

              [Embed(source="/media/brownplane.png")]

              public static var BrownPlane:Class;

              public static var BrownPlaneGraphics:GraphicsResource = new GraphicsResource(new BrownPlane(), 3, 20);

              [Embed(source="/media/smallgreenplane.png")]

              public static var SmallGreenPlane:Class;

              public static var SmallGreenPlaneGraphics:GraphicsResource = new GraphicsResource(new SmallGreenPlane(), 3, 20);

              [Embed(source="/media/smallblueplane.png")]

              public static var SmallBluePlane:Class;

              public static var SmallBluePlaneGraphics:GraphicsResource = new GraphicsResource(new SmallBluePlane(), 3, 20);

              [Embed(source="/media/smallwhiteplane.png")]

              public static var SmallWhitePlane:Class;

              public static var SmallWhitePlaneGraphics:GraphicsResource = new GraphicsResource(new SmallWhitePlane(), 3, 20);

              [Embed(source="/media/bigexplosion.png")]

              public static var BigExplosion:Class;

              public static var BigExplosionGraphics:GraphicsResource = new GraphicsResource(new BigExplosion(), 7, 20);

              [Embed(source="/media/smallisland.png")]

              public static var SmallIsland:Class;

              public static var SmallIslandGraphics:GraphicsResource = new GraphicsResource(new SmallIsland());

              [Embed(source="/media/bigisland.png")]

              public static var BigIsland:Class;

              public static var BigIslandGraphics:GraphicsResource = new GraphicsResource(new BigIsland());

              [Embed(source="/media/volcanoisland.png")]

              public static var VolcanoIsland:Class;

              public static var VolcanoIslandGraphics:GraphicsResource = new GraphicsResource(new VolcanoIsland());

              [Embed(source="/media/twobullets.png")]

              public static var TwoBullets:Class;

              public static var TwoBulletsGraphics:GraphicsResource = new GraphicsResource(new TwoBullets());

              [Embed(source="/media/cloud.png")]

              public static var Cloud:Class;

              public static var CloudGraphics:GraphicsResource = new GraphicsResource(new Cloud());

       }

}

就如你所見的我們所做的隻是在将顯示動畫的那些圖像的GraphicsResource構造器中增加幀和幀速率的值。

最後一步是改變将産生動畫的遊戲元素,這些元素現在繼承AnimatedGameObject類而不是GameObject類,當我們在擊毀一架飛機時産生爆炸動畫。

   Player和Enemy類都将被動畫化,兩個在擊毀時都将産生爆炸。這兩個類的需改變的代碼都一樣,是以我僅僅列出新的Enemy類。你可以下載下傳本論文結尾處的源代碼,看看Player類做了哪些改變。

本文來自CSDN部落格,轉載請标明出處:http://blog.csdn.net/literza/archive/2009/06/05/4241599.aspx

繼續閱讀