Corona中文站

强大、易学的跨平台(iOS/Android)开发框架。QQ群1:74390406(满) 群2:221929599

导航

五分钟学会Corona(八) - Sprite高级动画
神马是Sprite Sheets?

Sprite sheet是把多个帧打包在一个文本图片中,来实现2D动画效果。这提供了对纹理内存更加高效的利用,在移动设备上内存是非常有限的,并且也可以最小化加载时间。

Corona支持两种sprite sheet:1、动画帧的大小和位置都一致;2、动画帧的大小和位置都不一致。在前一种情况,你只要向Corona提供在sprite sheet图片文件中每一帧的宽度和高度,就可以创建sprite sheet的新的内部表现形式。下面这张图片(来自 JungleScene 范例工程),是使用规格统一的帧的sprite sheet的一个例子。



在另一个例子中,在sprite sheet中每个帧的大小和位置,被放在另外的数据文件中被描述,这个文件可使用一些sprite sheet生成工具(例如 Zwoptex or TexturePacker)来导出。Corona让你很容易的从一个sprite sheet图片和相关文件来创建一个内部的sprite sheet对象。现在让我们看看关于如果用这两种sprite sheet工作的例子。下面这个sprite sheet(在 HorseAnimation 的范例工程中)就包含了不一致大小和位置的帧。



Corona也包含了采用多序列的复杂角色动画的构造器,并且优先使用基于时间轴而不是基于帧的序列回放方法,所以动画在更慢的设备上,也会保持一样的播放周期。基于时间轴的序列,允许你单独选择并调整每个序列的帧率,而不用把动画的速度锁定为应用程序的全局帧率。

同一个时间可能有超过一个sprite实例在stage上播放,也许周期和位置都不相同。一个sprite动画的行为看上去和其他任何Corona的display object一样--它可能被添加到一个组或被变换,甚至被用于一个Box2D物理对象。

JungleScene 的范例工程展示了使用两个不同的sprite sheet(包括大小一致的帧),来创建不同帧率的动画。sprite sheet源图片的例子,可以参看项目目录下的 “greenman.png” 和 “runningcat.png”两个文件。

HorseAnimation 范例工程展示了如何从一个lua数据描述文件和源图片来创建一个sprite sheet的例子,它的帧都是非一致大小和位置的。


小结

对每个动画序列,开发者都需要指定以下事项:

• 源图片 (the sprite sheet)

• 以下中的其一:

• 在sprite sheet中的每一帧的高度和宽度(一致大小的帧的sprite sheet)。

• 一个lua数据描述文件,描述了每一帧的大小,位置和其他属性(非一致大小帧的sprite sheet)。一般这是由一个sprite sheet打包工具来生成的。

• sprite帧的位置 -- 这可能是不连续的!


当绘制一个sprite动画的实例,开发者需要指定:

• 场景中的目标

• 可选的变换,例如旋转/伸缩

• 动画的长度(基于时间轴)

• 循环行为



Sprite API

下面这行代码,使 sprite的特性在 “sprite”名字空间下,变得有效:

require "sprite"


sprite.newSpriteSheet

sprite.newSpriteSheetFromData

这两个函数创建新的sprite sheets。

下面的代码,从包含大小一致的帧当中创建一个新的sprite sheet,但是并没有在显示列表中添加任何东西。

spriteSheet = sprite.newSpriteSheet("image.png", frameWidth, frameHeight)

这里,sprite sheet的帧数被假定为= floor(imageWidth/frameWidth) * floor(imageHeight/frameHeight)。它们被按原始顺序索引:

1 2 3

4 5 6

7 8 9


spriteSheet = sprite.newSpriteSheetFromData( "image.png", spriteData )


第二种形式是,第二个参数传入一个table,用来在源sprite sheet图片中描述帧大小和位置。


下面代码是使用一个sprite sheet描述文件(名叫test.lua)的例子。它定义了一个简单函数,名叫 getSpriteSheetData()。 它返回一个lua table, sprite sheet 中每一帧的大小,位置,和其他属性,都包含这个table里。


-- test.lua

module (...)



function getSpriteSheetData()



local sheet = {

frames = {

{

name = "01.png",

spriteColorRect = { x = 38, y = 38, width = 50, height = 50 },

textureRect = { x = 2, y = 70, width = 50, height = 50 },

spriteSourceSize = { width = 128, height = 128 },

spriteTrimmed = true,

textureRotated = false

},



{

name = "02.png",

spriteColorRect = { x = 38, y = 36, width = 50, height = 52 },

textureRect = { x = 2, y = 242, width = 50, height = 52 },

spriteSourceSize = { width = 128, height = 128 },

spriteTrimmed = true,

textureRotated = false

},

}

}

return sheet

end


下面代码是从源图像文件(“test.png”)和上面的数据文件(“test.lua”),来创建一个新的sprite sheet对象。


1

2

3

4

5

6

7
local sprite = require("sprite")

-- In this case, test.lua is exported from Zwoptex

local test = require("test.lua")

-- Method defined by test.lua that returns table data defining the sprites

local spriteData = test.getSpriteSheetData()

-- Load the sprite sheet in test.png using the sprite definitions from spriteData

local spriteSheet = sprite.newSpriteSheetFromData( "test.png", spriteData )


这两种情况下,创建一个新的sprite sheet对象,并不能实际导致任何东西被添加到显示列表中。为了做到这一点,你需要从你的sprite sheet对象再创建一个sprite(和可选的sprite集)。后面会解释这个概念。

Tip: 你也可以这样写:

local spriteSheet = sprite.newSpriteSheetFromData( "test.png", test.getSpriteSheetData() )


spriteSet = sprite.newSpriteSet(spriteSheet, startFrame, frameCount)

从一个sprite sheet来创建一个新的sprite集。因为一个单独的sprite sheet可能包含多个不相关的游戏角色的图片,一个“sprite集”定义了属于同一个游戏角色的帧的集合,在播放时分开放入不同的动画序列。例如,一个战斗中的游戏角色,可能有不同的动画序列,出拳和出脚,但是这可以被定义在同一个sprite集中。

startFrame 时sprite第一帧的索引数,使用前面 newSpriteSheet() 中定义的索引,frameCount是集里帧的总数。

一个sprite集,是一个lua table,包含一个给定角色的一个或多个动画序列的键。每个sprite集用一个名为“default”的初始序列创建,集中包含所有帧,所以你及可以立即用默认序列,也可以在集中进一步定义动画序列。

sprite.add( spriteSet, "startFlying", startFrame, frameCount, time, [loopCount])

用指定的一些帧,来添加一个名为“startFlying”的序列,到sprite集中。这个序列有 frameCount 个帧,并将播放 time 毫秒。你可以通过改变time参数,来分别控制每个序列的帧率。

可选参数 loopParam 控制循环行为:

• 一个为1或更大的值,用于设置动画序列将要循环的次数。当到达序列的最后一帧时,将会停止播放。

• loopParam为0时(默认值),意味着序列将会无限期循环。

• loopParam为-1时,意味着序列将“弹”回并且只有一次来回。 (1, 2, 3, 2, 1)。在我们3帧的例子里,这将会按照下面的顺序播放: 1, 2, 3, 2, 1, 2, 3, 2, 1 (...) 一直下去。



spriteSheet:dispose()

一个sprite sheet的销毁,并且释放其纹理内存。它内部也在所有的sprite实例上调用 removeSelf(),从stage上删除了它们。所有属于这个sprite sheet的sprite,序列,和集在调用完这个函数后,也将不再有效,并且当它们不再被你应用程序的lua代码引用时,就会被垃圾回收掉。

1

2

3

4
local sprite = require("sprite")

local spriteSheet = sprite.newSpriteSheet("test.png")

-- Later dispose of the sprite sheet and all of its associated sprites, sequences and sets.

spriteSheet:dispose()




si = sprite.newSprite( spriteSet )

创建一个sprite的新实例。一个sprite就是一个DisplayObject。Sprite在一个时间里播放一个动画序列。

si:prepare([sequence])

停止任何当前播放的动画序列,可选参数用来设置新的当前序列,并且也会移动到那个序列的第一帧。不管怎样,这都会重置循环计数。然而,这个函数并没有开始播放当前序列。

si:play()

播放动画序列,从当前帧开始。不重置循环。

si:pause()

停止动画,单帧保持在显示帧的最后一帧上。随后可以通过play()函数来恢复播放。

si:addEventListener("sprite", listener)

当sprite实例动画得到事件时,可以通知 listener。

传给listener的事件,有如下字段:

event.sprite激发这个事件的sprite;它的当前属性也可以通过这个event访问,例如 event.sprite.sequence。

event.phasesprite所处阶段为下面中的一个:

"end" - sprite已停止播放

"loop" - sprite循环 (从最后到第一,或反向)

"next" - sprite'的下一帧已被播放。

Also see "Custom Events" in the Corona API Reference.

Sprite 属性

animating = true/false. 只读.

currentFrame = frame # of animation. 读/写.

sequence = 当前播放序列的名字
<< 五分钟学会Corona(七) - 基本运动与变换五分钟学会Corona(九) - 音频系统 >>

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

最近发表

Powered By Z-Blog 1.8 Walle Build 100427 Copyright 2011-2015 BuildApp.Net. All Rights Reserved.