用Starling渲染Sprite

原文地址:http://bbs.9ria.com/thread-103583-1-1.html

用Starling渲染Sprite

本文中要研究的是如何通过Starling框架使用2D游戏中Stage3D(比如用户GPU),来给资源做动画。

我想我有必要说明一下怎么开始架构Starling,一个很明显的切入点就是如何用Starling以及GPU(通过Stage3D)绘制动画。幸 好,Starling 把这些必要的繁琐环节都封装起来在幕后为你完成,你可以通过它直接和Stage3D交互。使用Starling的另一个好处就是它接入了一个你所熟悉的 API,由于它紧紧遵循着相同的API,而此API用于指向传统Flash Display列表的时候。MovieClip,Image,Sprite,Button等等。

现在开始

下面看看要怎么开始用Starling添加内容和制作动画。首先,你创建好一个支持Starling的ActionScript项目后(如果你不知道要怎么做请查看这篇文章),第一件要做的就是创建一个Starling核心引擎的实例。

1  var _st:Starling = new Starling(AnimationExample, stage);
2 _st.start();

可 见创建Starling()实例时,你要给它提供两个参数(它确实需要额外的参数但是目前我们会先跳过)。第一个参数是当Starling运行的时候你要 实例化的根类,在这里是AnimationExample。第二个参数是你要附加到根类实例的存储单元,在这里我们只要指定stage实例就可以了。

以上都完成后,现在剩下的就是让Starling实际运行了,你可以已经知道要怎么做了。你只需要调用Starling实例的start()方法。由上面两行代码,你的游戏文档类已经完成了(至少有个示例了),它应该跟下面代码看起来很像:

 1  package
 2 {
 3         import flash.display.Sprite;
 4  
 5         import starling.core.Starling;
 6         import com.flashgen.examples.AnimationExample;
 7  
 8         public class Starling101 extends Sprite
 9         {
10                 public function Starling101()
11                 {
12                         var _st:Starling = new Starling(AnimationExample, stage);
13                         _st.start();
14                 }
15         }
16 } 

 

创建游戏文档类

你可能会发现我漏掉了根类AnimationExample的创建,这个我们传入到Starling()构造函数的类。由于我想覆盖Starling一个 特殊条件,就是说这个类必须要继承Starling的实现接口DisplayObject类。现在就很明了了,这个不是Flash的 DisplayObject类,它是一个同名的Starling实现接口。最常用的实现接口就是从Starling的Sprite类中扩展这个类——你可 能会将Starling的DisplayObject类一并扩展。这样你的基类AnimationExample如下:

 1  package com.flashgen.examples
 2 {
 3         import starling.display.Sprite;
 4  
 5         public class AnimationExample extends Sprite
 6         {
 7                 public function AnimationExample()
 8                 {
 9                         super();
10                 }
11         }
12 } 

 

现 在你要创建一个叫init()的方法。对于这个例子,你可以将绝大部分代码放在这里。没有将代码放到实际的类构造函数中,是因为我们想确保在其他东西进入 进程之前这个类已经放到舞台上了。而这样做,只需要在AnimationExample类构造函数中加入一个事件侦听,等到这个类完整的添加到舞台上才执 行。

1  public function AnimationExample()
2 {
3         super();
4  
5         addEventListener(Event.ADDED_TO_STAGE, init);
6 } 

 

需 要反复重申的是这个我们侦听的事件不是flash.events.Event实现接口,而是Starling的实现接口,比如 starling.events.Event。我知道对于确定类使用Starling的实现接口我有点啰嗦,但如果你碰巧用了Flash的实现接口可是会 报错的。

添加资源

与Flash相比,Starling跟平常使用的制作动画方式有点不一样,但是最主要的是它用了Texture Atlas和Sprite Sheet *来渲染可视内容和制作动画。

Texture哈?Sprite什么!?
Texture Atlas和Sprite Sheet非常相似,它们都以一个包含许多小图像的大图像为中心。但它们在主要包含的内容范围上是不一样的。

Sprite Sheet一般只包括一个单独Sprite类型的位图信息——比方说一个士兵——包括它所需要的所有动画帧。

Texture Atlas包含了一整个游戏中所有需要的位图信息,(或者如果这个游戏每个单独的关卡都特别庞大),包括Sprite、静态资源等等。它还倾向于利用一个文本文档(一般是XML),或“Atlas”,
来标出每个条目在大图像中的哪里。通过在文本文档中使用数据可以很容易的摘录你需要的条目;并且如果完成得比较迅速,你可以根据序列交换当前帧和下一帧,以此来制作动画。

 

我已经创建了一个Sprite Sheet,并且用app调用了TexturePacker关 联了XML文件。我不是想在这篇文章中追踪怎么使用app的细节——我会把这留到一篇专门的博文中。现在主要做的就是怎么让这两部分(PNG图表和XML 文档)相互关联。因为我早先提到了XML文档包含了一个对于图表中每个条目的引用,并给每个sprite提供了x,y,width,height属性:

1  <TextureAtlas imagePath="Bilbo-walk.png">
2     <SubTexture name="Bilbo0001" x="0" y="0" width="215" height="208" frameX="-33" frameY="0" frameWidth="295" frameHeight="212"/>
3     <SubTexture name="Bilbo0002" x="215" y="0" width="215" height="208" frameX="-33" frameY="0" frameWidth="295" frameHeight="212"/>
4     <SubTexture name="Bilbo0003" x="430" y="0" width="215" height="202" frameX="-33" frameY="-5" frameWidth="295" frameHeight="212"/>
5     <!-- Additional entries removed for brevity -->
6 </TextureAtlas> 

 

然 而,在继续之前,我们看看在游戏中你实际上是怎么引用这两个文件的。首先你要做的是用[Embed]元数据来嵌入这两个文件。不要忘记替XML文件设置正 确的mimeType 属性(mimeType=”application/octet-stream”)。如果你忘记在你的XML的嵌入代码中写这个,程序就会报错且不能编 译。而PNG的Sprite Sheet就不用设置mimeType属性了,你的代码现在看起来应该跟下面一样(显然你的资源路径会不一样):

 1  public class AnimationExample extends Sprite
 2 {
 3         [Embed(source="assets/spritesheets/Bilbo-walk.xml", mimeType="application/octet-stream")]
 4         private var AnimData:Class;
 5  
 6         [Embed(source="assets/spritesheets/Bilbo-walk.png")]
 7         private var AnimTexture:Class;
 8  
 9         public function AnimationExample()
10         {
11                 super();
12  
13                 addEventListener(Event.ADDED_TO_STAGE, init);
14         }
15  
16         protected function init(e:Event):void
17         {
18  
19         }                
20 } 

 

一旦你嵌入了你的Sprite资源,你需要为它们创建一个实际的引用。所以就要为这两个文件在init()方法中分别创建实例,这样你就要为Starling的Texture()类创建一个实例并给这个变量从Sprite Sheet传递数据:

 protected function init(e:Event):void
{
        var _t:Texture = Texture.fromBitmap(new AnimTexture());
} 

注 意这里使用了静态方法Texture.fromBitmap()来获取并指定PNG文件实例。Starling的Texture()类还有其他 “from…”方法,这在以后的文章里会研究到。创建一个XML文件实例非常简单,你只需要确保将XML实例转换成了XML()函数——这是因为我们使用 了普通的Class()类作为两个嵌入文件的数据类型,而且为了确保XML文件已经正确赋值也是需要强制转换的。

1  protected function init(e:Event):void
2 {
3         var _t:Texture = Texture.fromBitmap(new AnimTexture());
4         var _d:XML = XML(new AnimData());
5  
6 } 

 

现在我们要合并这两个变量来创建让Starling可以在场景中执行的部分了,你要创建一个Starling的TextureAtlas()实例,这样就创建了Sprite Sheet和XML数据文件的关联,其中XML文件包含了图表中每个Sprite的位置信息。

1  protected function init(e:Event):void
2 {
3         var _t:Texture = Texture.fromBitmap(new AnimTexture());
4         var _d:XML = XML(new AnimData());
5  
6         var _ta:TextureAtlas = new TextureAtlas(_t, _d);
7 } 

 

让它动起来

我们刚刚研究了怎么设置好Starling来进行渲染。现在看看要如何渲染画面你才能实际看到你的Sprite。就如我一直在本文中提到 的,Starling的实现接口是Flash一般的API类,其中一个就是MovieClip()类。然而,跟Flash同等对比,它的设置和用法稍微有 点不同(这应该也是你所想要的)。创建一个Starling的MovieClip()类实例:

1  protected function init(e:Event):void
2 {
3         var _t:Texture = Texture.fromBitmap(new AnimTexture());
4         var _d:XML = XML(new AnimData());
5  
6         var _ta:TextureAtlas = new TextureAtlas(_t, _d);
7  
8         var _mc:MovieClip = new MovieClip(_ta.getTextures("Bilbo"), 30);
9 } 

 

注意这里使用了TextureAtlas()实例并且调用了getTextures()方法来检索要跟MovieClip()实例放在一起的Sprite。可以看到getTextures()方法里的字符串是XML文件name属性的前缀:

1  <SubTexture name="Bilbo0001" x="0" y="0" width="215" height="208" frameX="-33" frameY="0" frameWidth="295" frameHeight="212"/>

 

这 提供了一个机制来获取包含在一个PNG中的元素,也关联了游戏视图的各个部分。还有第一个你可以在实例化的时候定义的可选择参数,就是你希望 MovieClip()渲染的帧频。在本例中设置为30fps,而这个帧频与主游戏的帧频是不同的。现在你要做的就是添加这个MovieClip()实例 到Starling显示列表中了,展示完整的代码,并进行测试。

 1  protected function init(e:Event):void
 2 {
 3         var _t:Texture = Texture.fromBitmap(new AnimTexture());
 4         var _d:XML = XML(new AnimData());
 5  
 6         var _ta:TextureAtlas = new TextureAtlas(_t, _d);
 7  
 8         var _mc:MovieClip = new MovieClip(_ta.getTextures("Bilbo"), 30);
 9  
10         addChild(_mc);
11 } 

呃,中断了?

如果你测试了而且Bilbo在画面中显示但却不动,而你不知道为什么,不要慌张,你没有错过任何东西——程序正如预期的运行。你 看,MovieClip()实例应该已经有了所有动起来的条件了,你只需要在每个渲染周期使用一个方法来更新帧就可以了。这样你可以使用 Juggler,Juggler(就如名称所指)窜改了动画帧,在每个周期都进行了更新。不用担心这个听起来有点陌生,一旦你使用这个方法几次后,你会发 现这平常不过了。

最简单的方式就是用Starling()实例来接入Juggler 。你只需要引用Starling()实例并添加MovieClip()实例给Juggler关联就可以了。

 1  protected function init(e:Event):void
 2 {
 3         var _t:Texture = Texture.fromBitmap(new AnimTexture());
 4         var _d:XML = XML(new AnimData());
 5  
 6         var _ta:TextureAtlas = new TextureAtlas(_t, _d);
 7  
 8         var _mc:MovieClip = new MovieClip(_ta.getTextures("Bilbo"), 30);
 9  
10         addChild(_mc);
11  
12         Starling.juggler.add(_mc);
13 } 

现在如果你保存文件并测试,Bilbo会如你所愿的动起来。

总结

在本文中你已经知道了要怎么开始使用Starling框架,也明白了用Flash的API制作动画的不同(只是稍微),你也看到了Starling是如何与Sprite和Texture交互的,还有使用这些资源类型时的常规实现接口的工作流程。

posted @ 2014-02-25 17:12  无名盗闪  阅读(329)  评论(0)    收藏  举报