欢迎入群学习交流:535098339
各路大神弄的资料
// 1.动态加载资源
//第一个参数是resource下的文件名,不加后缀.function里第二个参数是资源类型
// 加载 Prefab
cc.loader.loadRes("test assets/prefab", function (err, prefab) {
let 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");
anim.play('anim'); //播放动画
});
// 加载 SpriteAtlas(图集),并且获取其中的一个 SpriteFrame
// 注意 atlas 资源文件(plist)通常会和一个同名的图片文件(png)放在一个目录下, 所以需要在第二个参数指定资源类型
cc.loader.loadRes("test assets/sheep", cc.SpriteAtlas, function (err, atlas) {
let frame = atlas.getSpriteFrame('sheep_down_0');
sprite.spriteFrame = frame;
});
// 加载 SpriteFrame
cc.loader.loadRes("test assets/image", cc.SpriteFrame, function (err, spriteFrame) {
myNode.getComponent(cc.Sprite).spriteFrame = spriteFrame;
});
// 加载 SpriteFrame第二种方式
//这个方法与上一个方法不同的是直接改图片的纹理,但凡是场景用到的test.png,一定会变成一样的.如果要批量改一个预制体的图片的话建议用上一个
sprite.spriteFrame.setTexture(cc.url.raw('res/test.png'));
//9.加载json
let url = cc.url.raw('resources/HeroDefault.json')
cc.loader.load(url, function (err, res) {
cc.log('load[' + url + '], err[' + err + '] result: ' + JSON.stringify(res));
});
// http://blog.csdn.net/alpha_xiao/article/details/52102252 这个比官网的详细,有示意图,新手可以看
// http://sunmoon-x.com/cocoscreator%E8%B5%84%E6%BA%90%E5%8A%A0%E8%BD%BD1-3-1%E7%89%88%E6%9C%AC/ 这个可以更深入的了解加载资源.
//加载播放声音
cc.audioEngine.play(cc.url.raw("resources/sounds/test.mp3" + url), false,1);
//加载网络图片
setSpriteFrame_sprite_url: function (sprite, url) { //设置网络图片
//加载https图片失败用下面方法.
// let url_http=url.replace('https','http')
cc.loader.load({
url: url,
type: 'png'
}, function (err, texture) {
if (err) {
console.log('加载图片失败' + err)
return;
}
sprite.spriteFrame = new cc.SpriteFrame(texture);
//sprite.spriteFrame.setTexture(texture) 希望你放弃setTexture这种方法,贼坑!
});
},
// 2.顺序执行动作.
let moveTime = 0.2;
let x = 0;
let y = -32;
let action = cc.moveBy(moveTime, x, y); //向下移动32像素
let finished = cc.callFunc(function (target, score) {
cc.log('回调发生')
}, this, 100)
let myAction = cc.sequence(action, finished);
// 3. 官方示例碰撞检测 点击刚体触发事件
cc.Class({
extends: cc.Component,
properties: {
collider: {
default: null,
type: cc.PolygonCollider
},
title: {
default: null,
type: cc.Label
}
},
// use this for initialization
onLoad: function () {
cc.director.getCollisionManager().enabled = true;
cc.director.getCollisionManager().enabledDebugDraw = true;
this.title.string = 'normal';
cc.eventManager.addListener({
event: cc.EventListener.TOUCH_ONE_BY_ONE,
onTouchBegan: (touch, event) => {
let touchLoc = touch.getLocation();
if(cc.Intersection.pointInPolygon(touchLoc,this.collider.world.points)){
this.title.string = 'Hit';
} else {
this.title.string = 'Not hit';
}
return true;
},
}, this.node);
},
});
// 4.自定义类 把类作为一个对象的属性,比如二维数组的实现
let Item = cc.Class({
name: 'Item',
properties: {
id: 0,
itemName: '',
itemPrice: 0,
iconSF: cc.SpriteFrame
}
});
cc.Class({
extends: cc.Component,
properties: {
items: {
default: [],
type: Item
}
},
});
//5.得到一个节点
this._player = this.node.getChildByName('player');
this._player = cc.find('Canvas/player')
//6.设置颜色
this.node.color = cc.Color.RED; //默认是WHITE.
//7.导入外部脚本
let cfg = 1;
module.exports = cfg; //这两句是cfg.js 在other.js里获取cfg的值用: let cfg=require('cfg');
//module.exports 是一个空对象,也可以像下面那样来获得cfg
module.exports = {
getCfg: function () {
return cfg;
},
}
//8.用本地数据库保存设置,游戏存档之类的.
if (JSON.parse(cc.sys.localStorage.getItem('config')) !== undefined) {
let config = JSON.parse(cc.sys.localStorage.getItem('config'));
}
cc.sys.localStorage.setItem('config', JSON.stringify(config));
//9.音频默认是使用 webAudio 的方式加载并播放的,只有在不支持的浏览器才会使用 dom 元素加载播放。
cc.loader.load(cc.url.raw('resources/background.mp3'), callback);
//10.长按实现人物持续移动
const self=this;
this.node.on(cc.Node.EventType.TOUCH_START, function (event) {
this.cb = function () {
cc.log("长按")
};
self.scheduleOnce(this.cb, 0.15);
}, this.node);
this.node.on(cc.Node.EventType.TOUCH_END, function (event) {
self.unschedule(this.cb);
}, this.node);
//11 本地存储图片,用原生
loadNative = function (url, callback) {
let dirpath = jsb.fileUtils.getWritablePath() + 'img/';
let filepath = dirpath + MD5(url) + '.png';
function loadEnd() {
cc.loader.load(filepath, function (err, tex) {
if (err) {
cc.error(err);
} else {
let spriteFrame = new cc.SpriteFrame(tex);
if (spriteFrame) {
spriteFrame.retain();
callback(spriteFrame);
}
}
});
}
if (jsb.fileUtils.isFileExist(filepath)) {
cc.log('Remote is find' + filepath);
loadEnd();
return;
}
let saveFile = function (data) {
if (typeof data !== 'undefined') {
if (!jsb.fileUtils.isDirectoryExist(dirpath)) {
jsb.fileUtils.createDirectory(dirpath);
}
if (jsb.fileUtils.writeDataToFile(new Uint8Array(data), filepath)) {
cc.log('Remote write file succeed.');
loadEnd();
} else {
cc.log('Remote write file failed.');
}
} else {
cc.log('Remote download file failed.');
}
};
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
cc.log("xhr.readyState " + xhr.readyState);
cc.log("xhr.status " + xhr.status);
if (xhr.readyState === 4) {
if (xhr.status === 200) {
xhr.responseType = 'arraybuffer';
saveFile(xhr.response);
} else {
saveFile(null);
}
}
}.bind(this);
xhr.open("GET", url, true);
xhr.send();
};
// 设置适配模式
cc.view.setOrientation(cc.macro.ORIENTATION_PORTRAIT);
cc.view.setDesignResolutionSize(750, 1334, 0);
//然后场景里的节点加上widget适配.
//后台监听函数
cc.game.on(cc.game.EVENT_HIDE, function(event){
cc.log("切换后台",event);
});
cc.game.on(cc.game.EVENT_SHOW, function(event){
cc.log("切换前台",event);
});
//得到java的变量
var id = jsb.reflection.callStaticMethod("org/cocos2dx/javascript/JsbService", "getUidToken", "()Ljava/lang/String;");
var result = jsb.reflection.callStaticMethod("org/cocos2dx/javascript/JsbService", "getBatteryPercent", "()I");
jsb.reflection.callStaticMethod("org/cocos2dx/javascript/JsbService", "wxShareUrl", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V", url, title, desc, type);
//取消node的所有监听
this.node.targetOff(this.node);
//取消计时器的所有监听
this.unscheduleAllCallbacks();
//--->>> 动作,类似c2dx api 基本无变化
var mTo = cc.moveBy(1,-100, -200);
var mAction = cc.repeatForever(cc.sequence(cc.moveBy(1,-100, -200),mTo.reverse(),cc.delayTime(0.5),cc.callFunc(function(action,data){
console.log("action callback:"+data.himi);
},this,{tx:100,himi:"i'm action callback and bring data"})));
mySprite.node.runAction(mAction);
//暂停动作
mySprite.node.stopAction(mAction);
//
顺便提一下cocos creator里是通过设置 节点的 active 属性,来控制可见性的,
setPosition等方法只能修改本节点,不能修改附属的子节点,但是可以通过给父节点加动作runAction(cc.MoveTo(...)),来变相达到想要的效果
动作系统:https://blog.csdn.net/likendsl/article/details/53413050
//按钮全局添加音效事件
cc.Component.EventHandler._emitEvents = cc.Component.EventHandler.emitEvents;
cc.Component.EventHandler.emitEvents = function (clickEvents, event) {
if (event instanceof cc.Event.EventTouch) {
if (event.type == "touchend") {
cc.ss.sound.playEffect("buttonclick.mp3")
}
}
cc.Component.EventHandler._emitEvents.apply(this, arguments);
};
//设置场景全局加速
cc.director.getScheduler().setTimeScale(1.5);
cc.director.getPhysicsManager().enabledAccumulator = true;
cc.director.getPhysicsManager().FIXED_TIME_STEP = 1 / 20
某大神关于性能优化的一些见解https://forum.cocos.com/t/topic/75032/2
不清楚你用的版本是否可以使用渲染组件了。
可以的话,鱼如果可以用instance来渲染,理论上可以大幅度地减少drawcall。
骨骼动画的定制我也不太清除引擎组的进度。但是以我最近在写的骨骼动画来说,减少动画K帧的数目,应该可以减少找插值的关键帧的时间,但这个不一定是瓶颈。
有一个很值得注意的地方,不开启碰撞检测的时候,还有30ms,但是加上碰撞检测,达到了几百ms,有理由怀疑瓶颈在 碰撞检测 上,或者说,由于碰撞后逻辑导致的 骨骼动画显示,消失,导致提交的cmdbuffer需要不断重新创建,骨骼动画不断调用构造函数,析构函数的开销
至于解决方案:
前者好说,用上 场景管理树 :hlbvh, quat-tree, 应该都有现成的,感兴趣可以去看看bullet物理引擎的官方文档,里面碰撞检测管线的描述很详细,这可以减少碰撞检测的开销,但是不好说减少多少,毕竟场景也没多少物体。
后者呢,老生常谈,用 对象池 吧。如果开销瓶颈不是动画,而是创建和析构上,那么回收骨骼动画的时候,最好不要将骨骼动画的节点从节点树上拿下来,而是 将骨骼动画移动到屏幕外(移动到场景外,会破坏场景管理树的结构,需要重新创建,所以记得profile一下性能瓶颈,究竟是碰撞是瓶颈,还是渲染是瓶颈,得出结论后,再决定是否要移动骨骼动画到场景外,这是一环套一环的) ,然后可以进行一下尝试:
1.将节点的active设置为false
2.将节点的动画停掉,
3.将节点的透明度设置为0
并且这几个方案都尝试一下吧。哪一个真正能提高性能,我最近也在写游戏引擎,个人愚见,这个和引擎开发者,做出的 设计取舍 有关。最好去问问做这一块的引擎开发者