0%

CVP认证学习笔记--(何小成)027--纹理缓存的管理

概念

本节内容主要讲解两个知识点,纹理缓存的管理和cocos的场景加载动画。纹理缓存管理可以通过cc.TextureCache来进行管理,而场景加载动画则在源码中的/frameworks/cocos2d-html5/cocos2d/core/scenes/CCLoaderScene.js中,在CCLoaderScene中定义了场景加载的相关方法。

API

cc.TextureCache的使用API在官网的文档地址是:http://www.cocos.com/doc/jsdoc/symbols/cc.textureCache.html
其主要API如下:

1
2
3
4
5
6
addImage(path);// 添加一个纹理到缓存
dumpCachedTextureInfo();// 把当前TextureCache的内容输出到cc.log,它会计算每个贴图的大小和贴图总共占用的内存
getTextureForKey(textureKeyName);// 返回创建好的贴图。如果贴图不存在,返回空。
removeAllTextures();// 清空加载贴图的字典,如果你收到“内存警告”时请调用此方法短期来看:释放某些资源,防止app出现闪退,在中期:会分配更多的资源,长远来看:没有什么区别
removeTexture(texture);// 从缓存中删除指定的贴图
removeTextureForKey(textureKeyName);// 从缓存中根据给定的key删除贴图textureForKey(textureKeyName);// 返回创建好的贴图。如果贴图不存在,返回空。

loading场景

cocos本身的loading场景在/frameworks/cocos2d-html5/cocos2d/core/scenes/CCLoaderScene.js中,而如果我们想要自己实现loading场景,要么在这个类的基础上直接改,要么写一个自己的loading场景,然后在main.js中把加载系统的loading场景改为加载我们自己的loading场景,仔细研究这个CCLoaderScene,其实发现它也没有做多么伟大的事情,其实也就是比普通的场景多做一件事而已,那就是加载资源,通过init的函数,加载一些变量,如loading文本,百分数的进度等,然后调用一个定时任务,定期更新进度文本,定时任务中通过调用cc.loader函数检查资源加载的进度,加载完成之后,再进入主场景。

作业

本节作业:
本节作业要求
// 本节课介绍了loading 的原理和系统源码
// 并深入介绍了cc.textureCache的核心用法
// 作业要求
// 实现一个自定义 loading效果(如果需要图片可以通过提交项目方式完成)
// 当loading 完成之后
// 清除loading界面的所有纹理
我在代码中实现了自建loading场景,写在了app.js中,并在loading场景中添加了一个移动的npc来模拟加载进度条,并且npc的纹理通过textureCache来管理,进度条加载完之后,通过textureCache移除场景中所有的纹理(其实只有npc的纹理)
作业代码实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
var HelloWorldLayer = cc.Layer.extend({
sprite:null,
ctor:function () {
//////////////////////////////
// 1. super init first
this._super();
//这时候,在src/resource.js中定义的图片数组都已经保存到了
//cc.TextureCache中,因此我们可以直接从这里获取纹理
cc.textureCache.addImage("res/32636-2.png");
var texture1=cc.textureCache.getTextureForKey("res/32636-2.png");
cc.textureCache.dumpCachedTextureInfo();
var sp=new cc.Sprite(texture1);
this.addChild(sp);
sp.setPosition(cc.winSize.width/2,cc.winSize.height/2);
// 本节课介绍了loading 的原理和系统源码
// 并深入介绍了cc.textureCache的核心用法
// 作业要求
// 实现一个自定义 loading效果(如果需要图片可以通过提交项目方式完成)
// 当loading 完成之后
// 清除loading界面的所有纹理
return true;
}
});

var HelloWorldScene = cc.Scene.extend({
onEnter:function () {
this._super();
var layer = new HelloWorldLayer();
this.addChild(layer);
}
});

// 自定义loading界面
var MyLoadScene = cc.Scene.extend({
_interval : null,
_label : null,
_npc:null,
_className:"LoaderScene",
cb: null,
target: null,
npc:null,
/**
* Contructor of cc.LoaderScene
* @returns {boolean}
*/
init : function(){
var self = this;

//logo
var logoWidth = 160;
var logoHeight = 200;

// bg
var bgLayer = self._bgLayer = new cc.LayerColor(cc.color(32, 255, 32, 255));
self.addChild(bgLayer, 0);

//image move to CCSceneFile.js
var fontSize = 24, lblHeight = -logoHeight / 2 + 100;
if(cc._loaderImage){//这个图片在Base64Image中保存,我们可以替换
//loading logo
cc.loader.loadImg(cc._loaderImage, {isCrossOrigin : false }, function(err, img){
logoWidth = img.width;
logoHeight = img.height;
self._initStage(img, cc.visibleRect.center);
});
fontSize = 14;
lblHeight = -logoHeight / 2 - 10;
}
//loading percent 加载进度
var label = self._label = new cc.LabelTTF("Loading... 0%", "Arial", fontSize);
label.setPosition(cc.pAdd(cc.visibleRect.center, cc.p(0, lblHeight)));
label.setColor(cc.color(180, 180, 180));
bgLayer.addChild(this._label, 10);
// 自定义npc
cc.textureCache.addImage("res/32636-2.png");
cc.textureCache.dumpCachedTextureInfo();
cc.log("loading界面添加纹理32636-2");
var npcTexture = cc.textureCache.getTextureForKey("res/32636-2.png");
var npc = self._npc = new cc.Sprite(npcTexture);
npc.setPosition(npc.width/2,150);
npc.setScale(0.5);
this._bgLayer.addChild(this._npc,10);
return true;
},
_initStage: function (img, centerPos) {
var self = this;
var texture2d = self._texture2d = new cc.Texture2D();
texture2d.initWithElement(img);
texture2d.handleLoadedTexture();
var logo = self._logo = new cc.Sprite(texture2d);
logo.setScale(cc.contentScaleFactor());
logo.x = centerPos.x;
logo.y = centerPos.y;
self._bgLayer.addChild(logo, 10);
},
/**
* custom onEnter
*/
onEnter: function () {
var self = this;
cc.Node.prototype.onEnter.call(self);
self.schedule(self._startLoading, 0.3);
},
/**
* custom onExit
*/
onExit: function () {
cc.Node.prototype.onExit.call(this);
var tmpStr = "Loading... 100%";
this._label.setString(tmpStr);
// 清理缓存
cc.textureCache.removeAllTextures();
cc.textureCache.dumpCachedTextureInfo();
cc.log("loading界面结束,清理纹理缓存");
},

/**
* init with resources
* @param {Array} resources
* @param {Function|String} cb
* @param {Object} target
*/
initWithResources: function (resources, cb, target) {
if(cc.isString(resources))
resources = [resources];
this.resources = resources || [];
this.cb = cb;
this.target = target;
},

_startLoading: function () {
var self = this;
self.unschedule(self._startLoading);
var res = self.resources;
cc.loader.load(res,
function (result, count, loadedCount) {
var percent = (loadedCount / count * 100) | 0;
percent = Math.min(percent, 100);
self._label.setString("Loading... " + percent + "%");
self._npc.setPositionX(self._npc.width/2+cc.winSize.width*(percent/100));
cc.log("loading界面npc走到了"+percent+",横坐标"+(self._npc.width/2+cc.winSize.width*(percent/100))+"");
}, function () {
if (self.cb)
self.cb.call(self.target);
});
},

_updateTransform: function(){
this._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
this._bgLayer._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
this._label._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
this._logo._renderCmd.setDirtyFlag(cc.Node._dirtyFlags.transformDirty);
}
});

MyLoadScene.preload = function(resources, cb, target){
var _cc = cc;
if(!_cc.loaderScene) {
_cc.loaderScene = new MyLoadScene();
_cc.loaderScene.init();
cc.eventManager.addCustomListener(cc.Director.EVENT_PROJECTION_CHANGED, function(){
_cc.loaderScene._updateTransform();
});
}
//调用initWithResources来实现纹理加载
_cc.loaderScene.initWithResources(resources, cb, target);
cc.director.runScene(_cc.loaderScene);
return _cc.loaderScene;
};

其中main.js加载场景的代码修改如下:

1
2
3
4
5
6
7
//load resources
// cc.LoaderScene.preload(g_resources, function () {
// cc.director.runScene(new HelloWorldScene());
// }, this);
MyLoadScene.preload(g_resources, function () {
cc.director.runScene(new HelloWorldScene());
}, this);

最终效果

http://www.cocoscvp.com/usercode/2016_05_20/55df2e8d114fce1f48d1151065951e865d56b92c/

大爷赏点儿呗.

欢迎关注我的其它发布渠道