`
wgcode
  • 浏览: 602634 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

AS3块传输技术呈现游戏元素

阅读更多

许多类型的游戏,用户体验都依赖于终端可拥有的屏幕像素和移动物体有多快。当让大量的DisplayObject对象动起来时,如MovieClip或Sprite对象,Adobe Flash Player可能在表现上会大大折扣。Flash Player必须遍历显示对象树并为每个基于向量的DisplayObject计算渲染输出,这样会消耗CPU周期成为真正的瓶颈,尤其是低端机。
     许多屏幕动画游戏都是预先载入一张位图,这种技术被称为blitting(块传输)。块传输虽不能解决所有性能问题,但它能使动画运行平滑,统一大多数机器上动画帧频。Blitting术语来自于BitBLT为Xerox Alto计算机日常中创建。BitBLT发音为“bit blit”,主张bit-block (image) transfer图像基于位块传输,是一种采用数张位图并合并成一张位图的技术。在Flash Player中复制位图像素到一张渲染图中比分别地渲染每个DisplayObject更为快速。
    在本文中,我描述了软件位块传输技术并提供示例代码,因此你可以在ActionScript中应用它。
要求
为了满足本文条件,你需要下列软件和文件。

Flash Builder 4 beta
Flash Player 9 以上版本
示例文件:actionscript_blitting.zip (ZIP, 185 KB)


预备知识
     本文假定你已熟悉Flash Builder 4 和 ActionScript 3项目工作的知识。
介绍sprite sheet
       一个游戏由许多图形元件组成,例如赛道上的车或森林中的一棵树。在本文中,这些元件都是位图。一组位图放在一个单独的图像文件中称为sprite sheet。例如,一个sprite sheet可能包含一个角色行走动画的所有帧。这个词衍生于sprite,在计算机图形世界中,指的是一张图像或一个大场景中集成的动画。虽然位块传输技术可以使用不同来源的位图数据,但在本文中重点放在sprite sheet。
  一个sprite sheet由什么构成?
     一个sprite sheet可以对不同大小的位图进行组合。将所有图形元素组装到一个大的图像文件中会减少加载时间(打开和读取一个包含100帧的较大文件比打开读取100个小文件更为快速)并提供压缩的好处。特别是sprite sheet持有同样大小形成一个序列的位图或围绕一个特定游戏元素动画。例如,本文中使用的sprite sheet有五列四行,每格40*40像素,每个都包含着一个brown collector褐色元素(见图1)。


设置ActionScript项目
    在你运行示例代码前,你将需要在Flash Builder 4按照以下步骤设置项目。
1.        下载并解压示例文件
2.        选择File > New > ActionScript Project来创建项目
3.        输入ActionScriptBlitting作为项目名称并点击Finish
4.        从示例文件中复制下列文件和文件到项目默认包中:ActionScriptBlittingPart1.as, ActionScriptBlittingPart2.as, ActionScriptBlittingPart3.as, ActionScriptBlittingPart4.as和spritesheets。Spritesheets文件夹中包含了用于 ActionScript示例的PNG文件。
5.        在Package Explorer中,右键点击ActionScriptBlitting项目在弹出菜单上选择Properties。
6.        在Properties属性对话框中点击ActionScript Applications。
7.        点击Add,选择ActionScriptBlittingPart1.as,并点击OK。
8.        将ActionScriptBlittingPart2.as,ActionScriptBlittingPart3.as, 和 ActionScriptBlittingPart4.as重复第7步。
9.        点击OK
现在Flash Builder 4中示例代码就设置好了,你就可以运行该示例。

用ActionScript嵌入一个sprite sheet
       在ActionScript中你可以通过使用Embed元数据标签嵌入图像。(更多信息请查看Embedding metadata with Flash)一旦它们被嵌入,你可创建类的实例并附加到显示列表,如ActionScriptBlittingPart1.as:

ActionScriptBlittingPart1.as
package
{
import flash.display.Sprite;
[SWF(width=480, height=320, frameRate=24, backgroundColor=0xE2E2E2)]
public class ActionScriptBlittingPart1 extends Sprite
{ 
public function ActionScriptBlittingPart1()
{
addChild(new BrownCollector());
}
[Embed(source="spritesheets/browncollector.png")]
public var BrownCollector:Class;
}
}
 要运行第一个示例,请参照下列步骤:
      在Package Explorer中,在ActionScriptBlittingPart1.as文件上点击右键选择Run Application。
      当浏览器打开时,你会看到所有单元格都有PNG图像(browncollector.png),效果见图1.
      关闭浏览器窗口。
Blitting a sprite sheet
     第二步,你将要用到Flash Player API的Bitmap 和 BitmapData,从sprite sheet复制一个单元格(或帧)到屏幕上,而这个操作可以通过BitmapData.copyPixels()方法来完成,复制输入位图数据的像素到正在制作的位图实例上。在ActionScript中纳入blitting,copyPixels()方法还提供参数来定义要复制输入位图的区域以及如何定义和合并alpha像素。


ActionScriptBlittingPart2.as
package
{
   import flash.display.Bitmap;
   import flash.display.BitmapData;
   import flash.display.Sprite;
   import flash.geom.Point;
   import flash.geom.Rectangle;
   [SWF(width=480, height=320, frameRate=24, backgroundColor=0xE2E2E2)]
   public class ActionScriptBlittingPart2 extends Sprite
   {
      public function ActionScriptBlittingPart2()
      {
         // Create input bitmap instance
        spritesheet = (new BrownCollector() as Bitmap).bitmapData;

         // Add a Bitmap to the display list that will copyPixels() to.
         canvas =  new BitmapData(480, 320, true, 0xFFFFFF);
         addChild(new Bitmap(canvas));
         rect = new Rectangle(0, 0, 40,40); // 1st Tile
         //** Section 1 ** //
         // rect = new Rectangle(40, 0, 40, 40); // 2nd Tile
         // rect = new Rectangle(80, 0, 40, 40); // 3rd Tile
         // ...
         // rect = new Rectangle(160, 120, 40, 40); // 20th Tile
          canvas.copyPixels(spritesheet, rect,  new Point(0, 0));
         //** END Section 1 **/
     
         /** Section 2 ** //
         for (var i:int = 0; i < 20; i++)
         {
            rect.x = (i % 5) * 40;
            rect.y = int(i / 5) * 40;
            canvas.copyPixels(spritesheet, rect, new Point(i*10, 0));
            // Section 3:
            // canvas.copyPixels(spritesheet, rect,
            // new Point(i*10, 0), null, null, true);
         }
         //** END Section 2 **/
      }
  
      [Embed(source="spritesheets/browncollector.png")]
      public var BrownCollector:Class;
      public var canvas:BitmapData; 
      public var spritesheet:BitmapData;
      public var rect:Rectangle;
   }
}
 在Package Explorer中的ActionScriptBlittingPart2.as文件上点击右键并选择Run Application。你将会看到来自sprite sheet的第一个单无格显示在浏览器中(见图2)。



图2 ActionScriptBlittingPart2输出(利用Section 1代码)


显示所有单元格
现在你绘制了1个单元格了,为什么不是绘制所有单元格呢?若要绘制所有,参照以下步骤:
1.        在Flash Builder 4中打开ActionScriptBlittingPart2.as
2.        找到标为“Section 1”的代码处并注释掉它。
3.        找到标为“Section 2”的代码处取消注释。
4.        保存文件
5.        再次运行ActionScriptBlittingPart2.as
Section 2的代码使用了循环来绘制每格较之前的单元格效果水平偏移10像素。



图3 ActionScriptBlittingPart2输出(利用Section 2代码)
    不过,看起来结果并不完全正确,而这正是因为BitmapData.copyPixels()的alpha参数导致的,最后三个参数(alphaBitmapData, alphaPoint, 和 mergeAlpha)提供了不同地处理透明区的方式。由于sprite sheet中的PNG图片已处理过alpha数据,就不再需要alphaBitMapData 或 alphaPoint了。你只需要设置最后一个参数来打开alpha合成,mergeAlpha为true。
确保改变:
1.        注释掉Section 2中调用copyPixels()处:

canvas.copyPixels(spritesheet, rect, new Point(i*10, 0));
复制代码


2.        取消注释Section 3中调用copyPixels()处:


        canvas.copyPixels(spritesheet, rect, new Point(i*10, 0), null, null, true);
复制代码


3.        保存该文件。
4.        再次运行ActionScriptBlittingPart2.as。你会看到图像有序地重叠(见图4)


 

图4 ActionScriptBlittingPart2输出(利用Section 3代码)
让sprite sheet动起来
     现在你已知道如何显示来自sprite sheet的位图数据,接下来就是让它动起来。ActionScriptBlittingPart3.as中的代码赋予brown collector图像活力,可将它移动到舞台上鼠标点击处。
在Flash Player中利用计时器创建一个平滑的动画
     基本思想是使用一个可以基于Flash Player帧的timer计时器,或两者结合的计时器。一个典型的方法是结合使用ENTER_FRAME事件和调用getTimer()来控制各种电脑环境中动画的速度。下面的代码摘录自ActionScriptBlittingPart3.as(行62):
/**
* Handles the timer
*/
private function enterFrameHandler(event:Event):void
{
tickPosition = int((getTimer() % 1000) / framePeriod);

if (tickLastPosition != tickPosition)
{
tickLastPosition = tickPosition;
canvas.lock();
canvas.fillRect(canvasClearRect, 0x000000);
render();
canvas.unlock();
}
}
 enterFrameHandler()方法处理ENTER_FRAME事件。该代码确定了SWF启动之后经过的秒数,这一数字除以framePeriod,期间游戏设计者想要呈现动画,如果这个值不同于上一次渲染帧的事件,清除画布上的内容,动画被重新渲染。
     在Flash Player中定时(有时描述为elastic race track)可以改变,触发ENTER_FRAME事件可以在不同的机器上有显著地变化。结合这个事件和定时检测可以使动画在一致频率时平滑,即使是一台机器运行速度远比SWF帧频快。同样如果该SWF帧频增加,动画帧频可以维持在一个一致较低的频率,使CPU能够处理其它逻辑而无需渲染每一帧。无论哪种方式,你都需要找出渲染一致性和CPU利用率之间的平衡。如果你把帧频设置过高,低端机器可能无法处理。
    当你运行ActionScriptBlittingPart3.as程序时,你会看到一个brown collector围绕着圆圈旋转。
Moving the animation
    Flash Player MouseEvent.MOUSE_UP 事件提供了鼠标在舞台上点击的x和y的坐标值。将鼠标点击处坐标一直作为collector的当前x和y位置,你可以在每次画布渲染时移动图像到不同的位置处。这给予了用户移动它的能力。下面的代码是从ActionScript类ActionScriptBlittingPart3.as(79行)摘录了如何用blitting来移动动画:
/**
*    Render any bitmap data.
*/
private function render():void
{       
   rect.x = (currentTile % 5) * 40;
   rect.y = int(currentTile / 5) * 40;
   collectorX += (destX-collectorX-20)/5;
   collectorY += (destY-collectorY-30)/5;
   canvas.copyPixels(spritesheet, rect,
   new Point(collectorX, collectorY), null, null, true);
   currentTile = ++currentTile % 20;
}

/**
*    Used to move the animation around.
*/
private function mouseUpHandler(event:MouseEvent):void
{
   destX = event.stageX;
   destY = event.stageY;
}
}
 mouseUpHandler()方法存储了鼠标点击处的x和y坐标值作为目标地址。之后的render()方法确定了一个在collector与目标位置之间非线性运动,记录点击的全局坐标作为新位置,然后将它提供给copyPixels()方法作为blitting的位置。
    如果动画运行时在舞台中点击,该collector会朝着点击位置处移动。
合并多张sprite sheet动画
     最后示例在一个单独的Stage上整合了多个sprite sheet。在上一个示例中,为了移动动画你需要存储位图数据放置的信息。当合并动画,你将需要保持更多位置的跟踪。除了位置,你可能需要维护并处理深度(它决定了当两个位图重叠时会显示哪一个),变化动画状态,不同的动画帧频,碰撞检测等等。
    在ActionScriptBlittingPart4.as中,collector深度最低。随机创建地彩色凝胶从屏幕顶部下降。如果一个凝胶碰撞到collector,将会运行第三种动画——凝胶在collector上熔化。
深度
    在Flash的中你可能曾创建过动画,如在舞台上放置多个对象。你可能还使用过mx.effects包来移动或旋转对象。如果对象重叠,其z- index(在显示列表中的深度)决定了对象叠放顺序。虽然位块传输,只有一个对象要显示:目标位置。由于正在处理渲染,那么你也将需要保持对象深度跟踪并确保一切都按正确的顺序进行复制。
    为了保持彩色凝胶从collector的顶部开始动画,你必须管理blitting的秩序。在ActionScriptBlittingPart4.as 中的render()方法,collector已经被混合(行110)后完成所有凝胶块传输(行138和144)
创建凝胶与其元数据
    每个彩色凝胶创建于enterFrameHandler()方法中。当一个彩色凝胶被创建,在createGel()方法中会设置其初始化属性包括一个随机x,y为0的位置,默认状态,meltFrame为零,一个唯一名称。该凝胶随后被保存到gels中,render()方法中会遍历这个 Dictionary实例。
/**
*    Create a gel
*/
private function createGel():void
{
   var gel:Object = new Object();
   gel.posX = ((Math.random() * 0xffffff) % 280) + 20
   gel.posY = 0;
   gel.state = "animate";
   gel.meltFrame = 0;
   gel.name = "gel" + gelCount++;
   gels[gel.name] = gel;
}
 凝胶的逻辑与渲染状态
render()方法移动彩色凝胶的逻辑并更改熔解状态。
/**
*    Render any bitmap data.
*/
private function render():void
{
   rect.x = (currentTile % 5) * 40;
   rect.y = int(currentTile / 5) * 40;
   collectorX += (destX-collectorX-20)/5;
   collectorY += (destY-collectorY-30)/5;
   canvas.copyPixels(spritesheetCollector, rect,
   new Point(collectorX, collectorY), null, null, true);
   // Render Gel at half the frame rate, to slow it down
   if (currentTile % 2 == 1)
   {
      rect.x = ((currentTile-1) % 5) * 40;
      rect.y = int((currentTile-1) / 5) * 40;
   }
   for each (var gel:Object in gels)
   {
      // Hit Check 5 px within Y and X
      if (Math.abs(gel.posY - collectorY + 6) < 14
        && Math.abs(gel.posX - collectorX) < 10)
      {
        gel.state = "melt";
      }
      if (gel.state == "melt")
      {
        // Clear out if done melting
        if (gel.meltFrame < 20)
           gel.meltFrame++;
        else
        {
           delete gels[gel.name];
           continue;
        }        
        rect.x = (gel.meltFrame % 5) * 40;
        rect.y = int(gel.meltFrame / 5) * 40;
        canvas.copyPixels(spritesheetGelMelt, rect, new Point(collectorX-1, collectorY-12), null, null, true);
        continue;
      }
      else
      {
        canvas.copyPixels(spritesheetGel, rect, new Point(gel.posX, gel.posY), null, null, true);
      }
     
      gel.posY += 3;
      if (gel.posY > 320)
      {
        delete gels[gel.name];
        continue;
      }
       
   }
  
   currentTile = ++currentTile % 20;
}
 凝胶动画是collector速度的一半,通过为奇数帧重置rect值为currentTile-1。接下来,在屏幕上代码循环所有彩色凝胶并检测 collector碰撞。如果发生碰撞它会更改状态为“melt”。在这种状态下,render()用彩色凝胶熔解sprite sheet并且其meltFrame总数为20帧时移除。当凝胶与collector的x和y位置发生碰撞时,会出现溶解动画,只要凝胶在移动就会紧随 collector。如果没有发生碰撞,凝胶向下移动3像素,当它的y坐标超出320时将会从舞台上移除。正如你所看到的,利用blitting你必须处理所有动画的逻辑。

分享到:
评论

相关推荐

    actionscript_blitting.zip

    利用AS3块传输技术呈现游戏元素:许多类型的游戏,用户体验都依赖于终端可拥有的屏幕像素和移动物体有多快。当让大量的DisplayObject对象动起来时,如MovieClip或Sprite对象,Adobe Flash Player可能在表现上会大大...

    as3helpcn.rar

    10. AS3中的XMLSchema验证:虽然AS3不直接支持XML Schema验证,但可以借助服务器端或第三方库进行XML文档的结构验证。 这份XML帮助手册详细介绍了ActionScript 3.0中XML的使用方法和技巧,对于AS3开发者来说,是一...

    Flash as 网站背景

    在构建网站时,Flash AS(ActionScript)曾是一种流行的手段,用于...这种技术虽然现在已被更现代的Web技术(如HTML5和CSS3)所取代,但在过去的网络环境中,Flash AS为网站设计带来了丰富的动态效果和创新的互动体验。

    flash as3.0 + xml + css

    在本项目中,AS3的主要作用是读取XML文件并处理数据,然后将其呈现在Flash舞台上。具体操作可能包括: 1. 加载XML:使用`XMLLoader`类或者`URLLoader`类加载XML文件,如`news_list.xml`。 2. 解析XML:加载完成后,...

    多媒体技术(张凌雯)课件第一章

    系统中的每一个部分都为多媒体的处理、存储、传输和呈现提供了必要的支持。 最后,本章还探讨了多媒体技术的应用与发展。从历史上的重要多媒体计算机系统说起,到多媒体技术在教育、娱乐、商业等不同领域的广泛运用...

    Adobe.Flash.Media.Server.3.开发者向导.简体中文版

    - **用户界面**:使用Adobe Flash或Flex开发,运行于Flash Player、AIR或Flash Lite 3之上,负责呈现UI元素,如播放控制按钮。 - **ActionScript代码**:客户端的逻辑处理和与服务器的通信通过ActionScript实现。FMS...

    ISAS的XML的文档

    XML,全称Extensible Markup Language,是一种用于标记数据的、自描述性的、灵活的文本格式。...XML的标准化和普遍接受性使其成为了信息技术领域的一个基石,对于学习和理解ISAS的学生来说,掌握XML的使用至关重要。

    我国新疆北部积雪中痕量元素的时空分布及污染评估.docx

    1. **痕量元素污染**:痕量元素,如Pb、Cr、As等有毒金属元素,由于不易降解,可以通过大气远距离传输并在积雪中积累,对环境和人体健康造成负面影响。这些元素主要来源于自然贡献和人类活动排放,特别是工业革命...

    ISAS XML

    XML的出现解决了这个问题,它提供了一种简单的方式来描述数据,关注数据本身以及数据的组织方式,而非数据的外观呈现。 XML的一个核心特点就是其可扩展性。与HTML不同,XML文档中的标签并非预定义的,而是由用户...

    通过xml生成flash报表

    标题中的“通过xml生成flash报表”指的是使用XML数据文件来驱动Adobe Flash(通常使用ActionScript 3,AS3)创建动态、交互式的报表和图表。Flash报表是一种视觉上吸引人的方式,可以有效地展示复杂的数据,而XML...

    关于XML的ISAS项目

    XML,全称为Extensible Markup Language,是一种可扩展的标记语言,旨在传输和存储结构化数据。它允许用户自定义标签和属性,以适应各种领域和应用场景的需求。XML的设计目标是促进数据的互操作性和自我描述性,使得...

    flash+xml简约的mp3播放器flash素材

    在IT行业中,多媒体元素的展示和交互经常需要用到各种播放器技术。本文将深入探讨"flash+xml简约的mp3播放器flash素材"这一主题,它是一款基于Flash和XML技术的MP3播放器,专为实现简单音乐播放而设计。尽管这款...

    基于DirectShow的局域网内音视频流的多机共享.pdf

    Filter主要分为三类:Source Filter(源过滤器)用于引入数据,Transform Filter(变换过滤器)处理数据,Renderer Filter(渲染过滤器)将数据呈现给用户。这些Filter通过Pin连接形成数据处理的链条。 **...

    XML绑定显示

    元素是XML的基本构建块,它们通过标签来定义,如 `&lt;element&gt;` 和 `&lt;/element&gt;`。属性则附加在元素上,提供额外的信息,例如 `&lt;element attr="value"&gt;`。在WinForms应用程序中,我们需要解析这些XML文件,以便将数据...

    FlV_player

    源码通常包括ActionScript文件,如在提供的文件列表中出现的`Mp3View.as`、`Mp3Model.as`和`Mp3Persenter.as`,它们可能分别代表视图、模型和呈现者(MVP模式)三个层面上的代码,这是一种常见的软件设计模式,用于...

    视频点播系统 综述

    - **前端展示层**:负责呈现视频列表、播放界面以及用户交互元素,通常采用HTML、CSS和JavaScript等前端技术实现。 - **后端服务层**:主要负责处理用户的请求,包括视频检索、播放控制等功能,通常使用ASP来开发。 ...

    xml-as-dynamic-html-table:读取XML并呈现为HTML表(动态)

    在IT行业中,XML(eXtensible Markup Language)是一种用于存储和传输数据的标准化格式,而HTML(HyperText Markup Language)则是用于创建网页内容的主要标记语言。本项目"xml-as-dynamic-html-table"专注于将XML...

    flash+xml迅雷影片广告特效

    Flash是一种广泛应用于网页设计、动画制作、游戏开发的平台,尤其在早期互联网时代,它在创建丰富的媒体内容方面起着重要作用。而XML则是一种数据存储和交换的标准,用于结构化数据的组织和传输。 【描述】:...

    SIMATICPCS7标准培训--OS编译.ppt

    在SIMATIC PCS7的界面中,你会看到相关的编译选项,选择相应的AS-OS连接,这是将程序和配置信息从AS传输到OS的关键步骤。 在编译过程中,系统会执行多个任务。包括更新变量,这是将控制逻辑中的变量映射到OS中,...

    读取xml配置文件的导航flash动画

    在IT行业中,XML(eXtensible Markup Language)是一种被广泛用于存储和传输数据的标记语言,因其结构清晰、易于解析而备受青睐。本案例中,“读取xml配置文件的导航flash动画”是一个利用Flash技术实现的交互式导航...

Global site tag (gtag.js) - Google Analytics