cc.loader.loadResDir 这个函数有一个回调参数,如果回调函数执行失败,则会一直尝试重新执行回调函数 let sp=this.getConponent(cc.Sprite)
sp.type = cc.Sprite.Type.SLICED
bib=sp.spriteFrame
bib.insetTop = 4
bib.insetBottom = 5
bib.insetLeft = 4
bib.insetRight = 5
this.NodeA.getComponent('jsA').funcA(),这时在funcA中this并不是之前的this,所以也就找不到this.abc。所以在jsA的开头let xxx =cc.Class({}),然后在start里设置xxx.ins=this,并在funcA中调用xxx.ins就可以等同于理想情况下的this把addChild的操作放到setColor后面就可以改变颜色了,先addChild再改变颜色就没有效果,用代码增加节点时,先设置完属性,再设置父节点 let color=[xxx, xxx, xxx]
let realPos = cc.v2(xxx, xxx)
let node = new cc.Node('');
node.setAnchorPoint(cc.v2(0, 0));
node.setContentSize(cc.size(16, 16));
node.setPosition(realPos);
node.color = cc.color(...color)
// 设置纯色图片
let texture = new cc.Texture2D;
let spriteFrame = new cc.SpriteFrame;
let u8a = new Uint8Array([255, 255, 255])
texture.initWithData(u8a, cc.Texture2D.PixelFormat.RGB888, 1, 1);
spriteFrame.setTexture(texture);
spriteFrame.setRect(cc.rect(0, 0, 16, 16));
node.addComponent(cc.Sprite).spriteFrame = spriteFrame;
node.setParent(parent);
语句1放到pos-1且语句2取消注释时调用createPrefab就会出问题(不显示,或只显示一部分),语句1放在pos-2且语句2注释就没问题 init(){
// cells 对象池
this.prefablPool = new Object()
let poolTypes = ['attack', 'move', 'wand'];
for (let i = 0; i < poolTypes.length; i++) {
const type = poolTypes[i];
if (this.cells[type] === null) {
continue;
}
this.prefablPool[type] = new cc.NodePool();
for (let i = 0; i < 40; ++i) {
let pbIns = cc.instantiate(this.cells[type]); // 创建节点
pbIns.pbType = type;
// pbIns.parent = this.node;// 语句2
this.prefablPool[type].put(pbIns); // 通过 put 接口放入对象池
}
}
}
// 对象池
createPrefab(type, pos) {
let pb = null;
if (this.prefablPool[type].size() > 0) { // 通过 size 接口判断对象池中是否有空闲的对象
pb = this.prefablPool[type].get();
} else { // 如果没有空闲对象,也就是对象池中备用对象不够时,我们就用 cc.instantiate 重新创建
pb = cc.instantiate(this.cells[type]);
pb.fpType = type;
// pos-1
}
// pos-2
pb.parent = this.node;// 语句1
pb.relativePos = pos;
let realPos = cc.v2((pos.x + 0.5) * this.tileSize.width, pos.y * this.tileSize.height)
pb.setPosition(realPos);
return pb
},
14.多个同类型节点的动画同步
syncPlay() {
let getSp = new Map([
['stay0', this.spriteStay[0]],
['stay1', this.spriteStay[1]],
['stay2', this.spriteStay[2]],
['stay3', this.spriteStay[2]],
['stay4', this.spriteStay[1]],
['stay5', this.spriteStay[0]],
['used0', this.spriteUsed[0]],
['used1', this.spriteUsed[1]],
['used2', this.spriteUsed[2]],
['used3', this.spriteUsed[2]],
['used4', this.spriteUsed[1]],
['used5', this.spriteUsed[0]],
]);
let sp = this.node.getComponent(cc.Sprite)
sp.spriteFrame = getSp.get(`${this.state}${this.curFrame}`);
},
update(dt) {
if (this.state != 'stay' && this.state != 'used') {
return;
}
let date = new Date();
let time = date.getTime();
let seconds = time % 1000;
let space = Math.ceil(1000 / 6);
let calcCurFrame = Math.floor(seconds / space);
if (calcCurFrame === this.curFrame) {
return;
}
if (this.curFrame != -1) {
if (calcCurFrame != (this.curFrame + 1) % 6) {
this.errTimes += 1;
cc.log(`errTimes+1:${this.errTimes}, curFrame:${this.curFrame}, calcCurFrame:${calcCurFrame}`);
// 这里并不做错误处理,因为每一帧都是同步的,只不过在某个时刻不连贯
}
}
this.curFrame = calcCurFrame;
this.syncPlay();
},
15.跟5有关系。let xxx =cc.Class({}),xxx.ins=this这时就相当于静态变量,如果这个class被创建多次,那么xxx.ins总指向最后一次创建的对象,而不是指向自己。想要避免this调用的问题,就使用箭头函数
16.更改z序。假设cn获取到4,那么将节点1setSiblingIndex设置完后,节点1getSiblingIndex获取到的是3,如果节点2再调用setSiblingIndex,那么节点1的SiblingIndex会变成了2,节点2的SiblingIndex会变成3
let cn = this.armyLayer.children.length;
cc.log(`${cn}`);//输出4
this.arrowsLayer.setSiblingIndex(cn);
cc.log(`${this.arrowsLayer.getSiblingIndex()}`);//输出3
army.node.setSiblingIndex(cn);
cc.log(`${army.node.getSiblingIndex()}, ${this.arrowsLayer.getSiblingIndex()}`);//输出3,2
17._randerFlag of null,有同名函数导致的
18.ctor会在new一个对象的时候调用。先避免使用吧,有些奇怪的问题,感觉跟cc.instantiate有关,暂时搞不懂,以后去详细了解一下机制
19.labeloutline在浏览器和模拟器中的表现不一样,在浏览器中表现正常,在模拟器中几乎不明显(设置多大都一样)
20.js中如果有这么一个调用obj.obj1.getObj2().obj3.obj4,如何保证obj,obj1,obj3,obj4以及函数getObj2()不为空呢?除了挨个判断和trycatch之外
21.widget挂件总是会调整自身位置(如果有设置的话),比如一个设置了顶部0px对齐的layout节点(锚点(0, 0)),在往layout里添加节点后,节点尺寸发生变化,widget就发挥作用了,会调整节点位置。
22.如果从dashboard中导入项目时没反应,有可能是asset和project.json出了问题。
其中project.json的格式应该为
{
"engine": "cocos-creator-js",
"packages": "packages",
"name": "catGame",
"id": "78e261cf-b0ad-488a-a2bb-507a69d02a41",
"version": "2.4.3",
"isNew": false
}
里面的id可以任意修改,只要不和现有id重复即可。如果文件形式跟这个不一样,那就是出错了。
如果打开修改该文件后的项目失败,出现xxx uuid xxx之类的提示,则把这个版本的编辑器删掉重新安装
23.某个挂载着cc.Widget的节点,在更新updateAlignment后,其(挂载了cc.Widget的)子节点并不会更新,需要手动更新
properties: {
map: {
default: null,
type: cc.Node,
},
cursor: {
default: null,
type: cc.Node,
},
},
-- 调用cc.node类型的属性,访问时直接用
this.map.x
或
this.map.position.x
-- 不需要多加个node
this.map.node.x (错误)
-- 获取窗口size
let s=cc.winSize
s.width and s.height
// 结论,键值判定应该跟变量的地址有关,匿名对象的地址拿不到(如果能拿到可以试一下,取出这个值)
case1:
let ta = { x: 0, y: 0 }
let test = new Map([
[ta, 'value'],
])
let val = test.get(ta);
cc.log(`val=${val}`)
// 输出`val=value`
case2:
// let ta = { x: 0, y: 0 }
let test = new Map([
[{ x: 0, y: 0 }, 'value'],
])
let val = test.get({ x: 0, y: 0 });
cc.log(`val=${val}`)
// 输出`val=undefined`
case3:
let ta = { x: 0, y: 0 }
let test = new Map([
[{ x: 0, y: 0 }, 'value'],
])
let val = test.get(ta);
cc.log(`val=${val}`)
// 输出`val=undefined`
let CellsPF = cc.Class({
name: 'CellsPF',
properties: {
attack: {
type: cc.Prefab,
default: null,
},
move: {
type: cc.Prefab,
default: null,
},
wand: {
// 杖
type: cc.Prefab,
default: null,
},
}
});
cc.Class({
extends: cc.Component,
properties: {
cells: {
type: CellsPF,
default: function() { return new CellsPF() },
// 设置合法的值,参考https://docs.cocos.com/creator/manual/zh/scripting/reference/class.html#deferred-definition
// 另外不能用箭头表达式
},
},
});
1.在层级管理器中编辑好节点,然后拖入资源管理器,并删除层级管理器中的节点
2.在脚本中引用
...
moveCell: {
default: null,
type: cc.Prefab
},
...
var map = this.map
var node = cc.instantiate(this.moveCell);
node.parent = map;
node.setPosition(216, 240);
3.在cretor面板中,将prefab拖入对应的脚本
目录结构
-- assets
-- resources
-- sword
-- sword_stay1.png
-- sword_stay2.png
-- sword_stay3.png
1.用cc.loader
cc.loader.loadRes("sword/sword_stay1", cc.SpriteFrame, function(err, spriteFrame) {
// self.node.getComponent(cc.Sprite).
sp.spriteFrame = spriteFrame;
})
2.用cc.url.raw,用这个方法加载的图片能做的操作有限,比如无法获取图片宽高,无法翻转图片,若需要使用这些功能,请使用cc.loader
sp.spriteFrame = new cc.SpriteFrame(cc.url.raw("resources/sword/sword_stay1.png"));
3.cc.resources.load(creator 2.3.1 用不了,会报错invoking function failed,暂时没找到原因)// 版本不对
let that = this
let oriSize = cc.size(32, 32)
let scale = 3
let desSize = that.sizeMultiplication(oriSize, scale)
let heroAnchor = cc.v2(0.5, 0)
let defPos = cc.v2(desSize.width * 2.5 / 2, desSize.height * 0)
let stayAniSpeed = 1.5
let heroName = ""
let spritePath = "q1/q_05"
var node = new cc.Node(heroName);
node.width = desSize.width
node.height = desSize.height
node.setAnchorPoint(heroAnchor)
node.setPosition(defPos)
var sp = node.addComponent(cc.Sprite);
sp.type = cc.Sprite.Type.SIMPLE
sp.sizeMode = cc.Sprite.SizeMode.CUSTOM;
sp.trim = false
node.parent = this.herosLayout;
// 绑定动画
var animation = node.addComponent(cc.Animation);
/* 添加SpriteFrame到frames数组 */
var frames = [];
frames[0] = new cc.SpriteFrame(cc.url.raw('resources/sword/sword_stay1.png'));
frames[1] = new cc.SpriteFrame(cc.url.raw('resources/sword/sword_stay2.png'));
frames[2] = new cc.SpriteFrame(cc.url.raw('resources/sword/sword_stay3.png'));
var clip = cc.AnimationClip.createWithSpriteFrames(frames, 3);
clip.name = 'anim_boom';
clip.wrapMode = cc.WrapMode.PingPongReverse;//乒乓反转
clip.speed = stayAniSpeed // 倍速播放,默认值为1,数值越大播放速度越快,0停止播放,负值也可以,效果等同于其绝对值(1==-1)
animation.addClip(clip);
animation.play('anim_boom');
// 以pos为原点,oStep为步长,画直径为((2*tStep+1)*oStep)的方块圆
let getMoveRange = function(pos, oStep, tStep) {
let ap = []
for (let i = 0; i < tStep * 2 + 1; i++) {
for (let j = 0; j < tStep * 2 + 1; j++) {
if (Math.abs(i - tStep) > Math.abs(Math.abs(j - tStep) - tStep)) {
continue
}
ap.push({ x: pos.x - (tStep - i) * oStep, y: pos.y + (tStep - j) * oStep })
}
}
return ap
}
/* 横坐标为i,纵坐标为j,tStep为3
* 0 1 2 3 4 5 6
0 *
1 * * *
2 * * * * *
3 * * * * * * *
4 * * * * *
5 * * *
6 *
-- 当Math.abs(i - tStep)后横坐标就变为
* 3 2 1 0 1 2 3
0 *
1 * * *
2 * * * * *
3 * * * * * * *
4 * * * * *
5 * * *
6 *
-- 当Math.abs(j - tStep)后纵坐标就变为
* 3 2 1 0 1 2 3
3 *
2 * * *
1 * * * * *
0 * * * * * * *
1 * * * * *
2 * * *
3 *
-- 当Math.abs(Math.abs(j - tStep) - tStep)后纵坐标就变为
* 3 2 1 0 1 2 3
0 *
1 * * *
2 * * * * *
3 * * * * * * *
2 * * * * *
1 * * *
0 *
*/
1.打开[option]->[font settings],设置一下size就行
2.[option]->[export option]
设置width和height,比(导入的资源)总尺寸稍大一点
[bit depth] -- 32
A -- outline
R -- glyph
G -- glyph
B -- glyph
[font descriptor] -- text
textures -- png
3.[edit]->[open image manager]->[image]->[import image]->选择一张图片(一个数字一张图片)->填写id(就是对应的ASCII码)
4.主界面右边的选项一个都不要勾上
5.[option]->[visualize]可以预览,如果width和height设置的太小就不能预览
6.[option]->[save bitmap font as]保存成fnt文件(还会附带一个文件,类型取决于textures设置)
7.将生成的fnt文件和png文件一起拖入creator
8.设置label属性,把[use system font]取消选中,然后拖动bf文件到font选项上
// 首先需要注意的就是,保存的tmx文件要和原图放在同一个文件夹中,到时候一起拖到creator里,如果没放在一起则会提示找不到文件,这时可以用文本编辑器打开tmx文件,修改里面的路径(是相对路径)
1. 准备好地图块,可以是一整张地图
2. 新建一个地图,设置地图宽高和块宽高
3. 然后在[地图]-[新图块]-[浏览],选择那张准备好的地图,名字可以不填,会自动设为同名,要保持名字一致。设置块宽高
4. 工具栏有图章刷,地形刷,填充,橡皮擦。选择图章刷,然后在图块那里左键点选或拖动图块,选择好后就可以在作画了
5. 添加图层,可以将不同的图块放在不同的图层用以区分
6. 地形
7. 保存为tmx文件,将图片和该文件拖入creator资源管理器中
...
var sp = node.addComponent(cc.Sprite);
sp.type = cc.Sprite.Type.SIMPLE
sp.sizeMode = cc.Sprite.SizeMode.RAW;
// sp.sizeMode = cc.Sprite.SizeMode.CUSTOM;
sp.trim = false
...
let animation = node.addComponent(cc.Animation);
// asstes是一个数组序列帧动画需要的所有spriteframe资源
// enums.Ca是一个map,包含从name到index的映射
for (let ani = 0; ani < assets.length; ani++) {
const an = assets[ani];
let info = an.name.match(/([a-z]+|\d+)/g)
let clipInd = (info[0] + '').toUpperCase()
let clip = clips[enums.Ca[clipInd]]
if (!('frames' in clip)) {
clip.frames = new Array(clip.sample)
}
let frameInd = parseInt(info[1]) - 1
// !!!!!!!!
// how to modify an's prop to make it
clip.frames[frameInd] = an
}
// clips是一个数组,里面存放着每个动画所需要的信息,包括frames,sample,type,wrapMode,speed
for (let iteInd = 0; iteInd < clips.length; iteInd++) {
let ite = clips[iteInd]
let clip = cc.AnimationClip.createWithSpriteFrames(ite.frames, ite.sample);
clip.name = ite.type;
clip.wrapMode = ite.wrapMode;
clip.speed = ite.speed; // 倍速播放,默认值为1,数值越大播放速度越快,0停止播放,负值也可以,效果等同于其绝对值(1==-1)
animation.addClip(clip);
}
这样设置完后,节点尺寸就可以随着序列帧图片的尺寸不同而改变
但是我想将原图先放大n倍
是否能直接修改图片资源的orisize,使其可以作用于raw属性
~将sprite的sizeMode设置为raw后,节点大小会随着序列帧图片的尺寸不同而改变。但是序列帧的原始尺寸不是我想要的尺寸,我需要先将这个尺寸放大n倍,然后再设置为动画。~
解决方法:
node.on(cc.Node.EventType.SIZE_CHANGED, node.sizeChange, this); node.setContentSize = (size) => {
cc.log(`set size, ${arguments.length}, ${size}`)
node.width = size.width * dc
node.height = size.height * dc
}
4.有一份原图,现在需要放大x倍后作为九宫格使用
5.有一组序列帧图片,每个图片尺寸可能一样也可能不一样,现在需要放大x倍且SizeMode设置为RAW。覆盖node的setContentSize方法