先介绍一下SpriteSheetAs3,这是一个开源的用SpriteSheet Animation in AS3修改和优化后的库,有以下新功能:
1.减少内存的使用;
2.可读入sprite sheet的plist格式配置文件;
3.改为用图片名索引位图(小图)或动画帧;
4.支持旋转位图(小图)的sprite sheet;
5.可读入tiled地图。
以下来用TexturePacker为我们生成一个sprite sheet,在这里下载TexturePacker和小丑鱼动画帧,打开TexturePacker把所有小丑鱼图片加入到工程,如图所示:
注意Data Format一定要是cocos2d,Texture settings的其他选项最好和上图一致,texturefile和data file的路径由自己来定吧,然后点击public发布一个sprite sheet和有关sprite sheet所包含图片数据的plist文件。如果是免费版TexturePacker,点击public后,还要点continue,而且sprite sheet有两个图花了,这是免费版才会有的。
接下来是代码开发了,先下载SpriteSheetAs3,打开Flash Builder新建一个ActionScript项目,命名为testSpriteSheet,如下图核毕空:
点击"下一步",点"添加SWC",把SpriteSheetAs3里bin目录下的SpriteSheetAs3.swc文件添加到工程中,如下图:
点“完成”,把Clown_Normal.png和Clown_Normal.plist复制到testSpriteSheet/bin-debug/data/下(请手动创建目录),把以下内容复制到testSpriteSheet.as文件里:
//testSpriteSheet.as
package
{
import flash.display.Bitmap
import flash.display.DisplayObject
import flash.display.Sprite
import flash.display.StageAlign
import flash.display.StageScaleMode
import flash.events.Event
import flash.events.IOErrorEvent
import com.sprite_sheet.AnimSpriteSheet
import com.sprite_sheet.SpriteSheetFrame
import com.sprite_sheet.TextureCache
import com.sprite_sheet.SpriteFrameCache
import utils.Stats
import utils.loading.BigLoader
import utils.loading.BigLoadItem
[SWF (width="750", height="600")]
public class testSpriteSheet extends Sprite
{
private var mLoader:BigLoader//res loader
public function testSpriteSheet()
{
addEventListener(Event.ADDED_TO_STAGE, onAdded)
}
protected function onAdded(event:Event):void
{
stage.scaleMode = StageScaleMode.NO_SCALE
stage.frameRate= 60
//draw background
var appWidth:Number= 750
graphics.beginFill(0x434E8E)
graphics.drawRect(0,0, appWidth, 24)
graphics.endFill()
graphics.beginFill(0xf0f0f0)
graphics.drawRect(0,24, appWidth, 600)
graphics.endFill()
var st:DisplayObject= new Stats()
st.y= 20
addChild(st)
// load resources
mLoader= new BigLoader()
mLoader.add("data/Clown_Normal.png", "Clown_Normal.png")
mLoader.add("data/Clown_Normal.plist", "Clown_Normal.plist", 1, BigLoadItem.DATA)
mLoader.addEventListener(Event.COMPLETE, onAnimLoaded)
mLoader.addEventListener(IOErrorEvent.IO_ERROR, onLoadFailed)
mLoader.start()
}
private static const NUM_H:int = 6
protected function onAnimLoaded(event:Event):void
{
//add sprite sheet data file to SpriteFrameCache
SpriteFrameCache.Singleton().SetLoader(mLoader)
SpriteFrameCache.Singleton().AddSpriteFrames("Clown_Normal.plist")
//add sprite sheet file to TextureCache
TextureCache.Singleton().SetLoader(mLoader)
TextureCache.Singleton().addSpriteSheet("Clown_Normal.png")
for (var i:int = 0i <24i++)
{
//create clown fish anim
var anim: AnimSpriteSheet = createClownAnim()
addChild(anim)
//set fps
anim.mFps = 2 * (i + 1)
//set pos
var row: int = int(i/NUM_H)
anim.x= 20 + 100*(i%NUM_H) + row*36
anim.y= 150 + row*60
}
}
protected function createClownAnim(): AnimSpriteSheet
{
//00~09 frames
var bmps: Array = new Array()
var bmp: SpriteSheetFrame = null
for(var i:int = 0i <10i++)
{
bmp = SpriteFrameCache.Singleton().CreateSpriteSheetFrame("Clown_Normal0" + i + ".png")
bmps.push(bmp)
}
//10~ 23 frames
for(i = 10i <24i++)
{
bmp = SpriteFrameCache.Singleton().CreateSpriteSheetFrame("Clown_Normal" + i + ".png")
bmps.push(bmp)
}
var anim: AnimSpriteSheet = new AnimSpriteSheet(bmps)
anim.mFps = 30
anim.EnableShow(true)
anim.EnablePlay(true)
return anim
}
protected function onLoadFailed(event:IOErrorEvent):void
{
// if load file failed, will print the file name to console
trace("Cannot find file!")
trace(event.text)
}
}
}
最后运行一下程序,成功的话会看见有很多小丑鱼在游动,不过有些花图(我用的是免费版TexturePacker)
在cocos2d-x中可以用.plist格式的文件来保存数据,它是XML文件格式的一种,在cocos2d-x解析.plist方面相关的资料比较少,但本身也很简单,要解析.plist文件可以参考cocos2d-x类库中的CCSpriteFrameCache类和CCParticleSystem类,它主要是使用CCDictionary类来对.plist文件进行 *** 作。下面有一个.plist文件:
[html] view plaincopy
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"瞎宴闭>
<plist version="1.0">
<dict>
<key>level1</key>
<dict>
<key>bg_far_scene</key>
<dict>
<key>path</key>
<string>images/far_scene.png</string>
<key>pos</key>
<string>{358, 309}</string>
</dict>
<key>bg_near_scene</key>
<dict>
<key>path</key>
<string>images/near_scene.png</string>
<key>pos</key>
<string>{360, 100}</string>
</dict>
</dict>
</dict>
</plist>
读取.plist文件的代码如下:
[cpp] view plaincopy
const char* testPlistPath = "BSPlistDatas\\test.plist"
const char* fullPath = CCFileUtils::sharedFileUtils()->fullPathFromRelativeFile("test.plist", testPlistPath)
CCDictionary* plistDic = CCDictionary::createWithContentsOfFile(testPlistPath)
CCDictionary* levelDic = dynamic_cast<CCDictionary*>(plistDic->objectForKey("level1"))
CCDictionary* farScene = dynamic_cast<CCDictionary*>(levelDic->objectForKey("bg_far_scene"))
CCString* farScenePath = dynamic_cast<CCString*>(farScene->objectForKey("path"))
CCPoint point = CCPointFromString(farScene->valueForKey("pos")->getCString())
CCLog("path = %s", farScenePath->getCString())
CCLog("pos = %f, %f", point.x, point.y)
第一行是.plist文件的相对路径,通过CCFileUtils类获得文件中绝对路径后,使用CCDictionary::createWithContensOfFile(filePath)将文件中内容加载到CCDictionary数据结构的内存中,然后通过xxxForKey获得相应的key下的value。
这里需要注意的是,当在读取'pos'的时候,它的值一个{x, y}的字磨裂符串,这是.plist文件中祥州的数组存储规则,我们可以通过cocos2d-x提供函数api将这样的字符串转化为CCpoint对象。
[cpp] view plaincopy
CCPoint point = CCPointFromString(farScene->valueForKey("pos")->getCString())
上面这句话就是做了这样的一个转化的过程,同样的cocos2d-x还支持CCSize、CCRect的字符串的转化。他们转化的方法以及在.plist中对应的字符串格式如下:
CCPoint: CCPointFromString(){x, y}
CCSize:CCSizeFromString(){w, h}
CCRect: CCSizeFromString(){x, y, w, h}
这样我们2D游戏所初始化所需要的数据都基本上够用了,可以尝试将游戏的初始数据放在.plist中,然后修改调整数值就可以直接修改plist文件,而无需重新编译程序了,从而实现游戏数据和游戏逻辑的分离。
Cocos Creator 有一套统一的资源管理机制 ,在本篇教程,我们将介绍资源的分类
如何在 属性检查器 里设置资源
动态加载 Asset
动态加载 Raw Asset
资源的分类
目前的资源分成两种,一种叫做 Asset,一种叫做 Raw Asset。
Asset
Creator 提供了名为 "Asset" 的资源类型,cc.SpriteFrame, cc.AnimationClip, cc.Prefab 等资源都属于 Asset。Asset 的加载是统一并且自动化的,相互依赖的 Asset 能够被自动预加载。
例如,当引擎在加载场景时,会先自动加载场景关联到的资源,这些资源如果再关联其它资源,其它也会被先被加载,等加载全部完成后,场景加载才会结束。
因此只要你拿到了一个 Asset 对象,这个对象一定是已经加载结束的,可以直接通过对象上的属性访问到资源的所有数据。当你要在引擎中使用这些资源,引擎的 API 接收的都必须是一个加载好的 Asset 对象。
脚本中可以这样定义一个 Asset 属性:
// NewScript.js
cc.Class({
extends: cc.Component,
properties: {
spriteFrame: {
default: null,
type: cc.SpriteFrame
},
}
})
Raw Asset
为了兼容 Cocos2d 的一些既有 API,我们把保留原始资源文件扩展名资源叫做 "Raw Asset"。图片(cc.Texture2D),声音(cc.AudioClip),粒子(cc.ParticleAsset)等资源都是 Raw Asset。Raw Asset 在脚本里由一个 url 字符串来表示,当你要在引擎中使用 Raw Asset,只要把 url 传给引擎的 API,引擎内部会自动加载这个 url 对应的资源。
当你在脚本里声明一个类型是陵胡蚂 cc.Texture2D 的 Raw Asset,一开始可能会想这样定义:
cc.Class({
extends: cc.Component,
properties: {
textureURL: {
default: null,
type: cc.Texture2D
}
}
})
这样写的问题在于,在代码中 textureURL 实际上是一个字符串,而不是 cc.Texture2D 的实例。为了不混淆 type 的语义,在 CCClass 中声明 Raw Asset 的属性时,要用 url: cc.Texture2D 而不是 type: cc.Texture2D。
cc.Class({
extends: cc.Component,
properties: {
textureURL: {
default: "",
url: cc.Texture2D
}
}
})
如何在属性检查器里设置资源
不论是 Asset 还是 Raw Asset,只要在脚本中定义好类型,就能直接在 属性检查器 很方便地设尺埋置资源。假设我们有这样一个组件:
// NewScript.js
cc.Class({
extends: cc.Component,
properties: {
textureURL: {
default: "",
url: cc.Texture2D
},
spriteFrame: {
default: null,
type: cc.SpriteFrame
},
}
})
将它添加到场景后,属性检查器 里是这样的:
asset-in-properties-null
接下来我们从 资源做饥管理器 里面分别将一张贴图和一个 SpriteFrame 拖到 属性检查器 的对应属性中:
asset-in-properties-dnd
结果如下:
asset-in-properties-dnd
这样就能在脚本里直接拿到设置好的资源:
onLoad: function () {
var spriteFrame = this.spriteFrame
var textureURL = this.textureURL
spriteFrame.setTexture(textureURL)
}
在 属性检查器 里设置资源虽然很直观,但资源只能在场景里预先设好,没办法动态切换。如果需要动态切换,你需要看看下面的内容。
动态加载
所有需要通过脚本动态加载的资源,都必须放置在 resources 文件夹或它的子文件夹下。resources 需要在 assets 文件夹中手工创建,并且必须位于 assets 的根目录,就像这样:
asset-in-properties-null
这里的 image/image, prefab, anim, font 都是常见的 Asset,而 image, audio 则是常见的 Raw Asset。
resources 文件夹里面的资源,可以关联依赖到文件夹外部的其它资源,同样也可以被外部场景或资源引用到。项目构建时,除了已在 构建发布 面板勾选的场景外,resources 文件夹里面的所有资源,连同它们关联依赖的 resources 文件夹外部的资源,都会被导出。所以如果一份资源不需要由脚本直接动态加载,那么不用放在 resources 文件夹里。
动态加载 Asset
Creator 提供了 cc.loader.loadRes 这个 API 来专门加载那些位于 resources 目录下的 Asset。和 cc.loader.load 不同的是,loadRes 一次只能加载单个 Asset。调用时,你只要传入相对 resources 的路径即可,并且路径的结尾处不能包含文件扩展名。
// 加载 Prefab
cc.loader.loadRes("test assets/prefab", function (err, prefab) {
var newNode = cc.instantiate(prefab)
cc.director.getScene().addChild(newNode)
})
// 加载 AnimationClip
cc.loader.loadRes("test assets/anim", function (err, clip) {
myNode.getComponent(cc.Animation).addClip(clip, "anim")
})
// 加载 SpriteAtlas(图集),并且获取其中的一个 SpriteFrame
// 注意 atlas 资源文件(plist)通常会和一个同名的图片文件(png)放在一个目录下, 所以需要在第二个参数指定资源类型
cc.loader.loadRes("test assets/sheep", cc.SpriteAtlas, function (err, atlas) {
var frame = atlas.getSpriteFrame('sheep_down_0')
sprite.spriteFrame = frame
})
加载独立的 SpriteFrame
图片设置为 Sprite 后,将会在资源管理器中生成一个对应的 SpriteFrame。但如果直接加载 test assets/image,得到的类型将会是 cc.Texture2D。你必须指定第二个参数为资源的类型,才能加载到图片生成的 cc.SpriteFrame:
// 加载 SpriteFrame
cc.loader.loadRes("test assets/image", cc.SpriteFrame, function (err, spriteFrame) {
myNode.getComponent(cc.Sprite).spriteFrame = spriteFrame
})
如果指定了类型参数,就会在路径下查找指定类型的资源。当你在同一个路径下同时包含了多个重名资源(例如同时包含 player.clip 和 player.psd),或者需要获取“子资源”(例如获取 Texture2D 生成的 SpriteFrame),就需要声明类型。
资源释放
loadRes 加载进来的单个资源如果需要释放,可以调用 cc.loader.releaseRes,releaseRes 只能传入一个和 loadRes 相同的路径,不支持类型参数。
cc.loader.releaseRes("test assets/anim")
此外,你也可以使用 cc.loader.releaseAsset 来释放一个具体的 Asset 实例。
cc.loader.releaseAsset(spriteFrame)
动态加载 Raw Asset
Raw Asset 可以直接使用 url 从远程服务器上加载,也可以从项目中动态加载。对远程加载而言,原先 Cocos2d 的加载方式不变,使用 cc.loader.load 即可。对项目里的 Raw Asset,加载方式和 Asset 一样:
// 加载 Texture,不需要后缀名
cc.loader.loadRes("test assets/image", function (err, texture) {
...
})
cc.url.raw
Raw Asset 加载成功后,如果需要传给一些 url 形式的 API,还是需要给出完整路径才行。你需要用 cc.url.raw 进行一次 url 的转换:
// 原 url 会报错!文件找不到
var texture = cc.textureCache.addImage("resources/test assets/image.png")
// 用 cc.url.raw,此时需要声明 resources 目录和文件后缀名
var realUrl = cc.url.raw("resources/test assets/image.png")
var texture = cc.textureCache.addImage(realUrl)
资源批量加载
cc.loader.loadResAll 可以加载相同路径下的多个资源:
// 加载 test assets 目录下所有资源
cc.loader.loadResAll("test assets", function (err, assets) {
// ...
})
// 加载 sheep.plist 图集中的所有 SpriteFrame
cc.loader.loadResAll("test assets/sheep", cc.SpriteFrame, function (err, assets) {
// assets 是一个 SpriteFrame 数组,已经包含了图集中的所有 SpriteFrame。
// 而 loadRes('test assets/sheep', cc.SpriteAtlas, function (err, atlas) {...}) 获得的则是整个 SpriteAtlas 对象。
})
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)