前面的那些内容,在第一次理解的时候, 可能很多地方比较模糊。随着看的文档内容,有些东西会慢慢清晰起来。
节点(Node)
我目前理解节点,是将其认为是iOS中的view。当前节点中的子节点,就相当于世view下的子view。
比如在脚本中,获取当前的节点:通过Demo中来操作认识。
1、通过编辑器 新建一个Hello World
的模版Demo。
2、新建一个HelloWorld
的TypeScript脚本,将其拖入到Canvas
节点的属性检查器中。
3、在脚本中编写代码。
start() {
let curNode = this.node; // 当前节点
let nodes = curNode.children; // 当前节点的子节点
let parentNode = curNode.parent; // 其父节点
console.log(nodes);
console.log(parentNode);
}
运行起来之后,查看打印信息(快捷键:F12
)
从打印的名字上来看,就是当前节点Canvas
下的所有节点。
4、当前HelloWorld
脚本是挂载在Canvas
上,把其从Canvas
删掉,加载到其他的节点上。
挂载到其他的节点
此时 重新运行,查看打印信息,发现打印的是空数组,因为main Camera
下没有子节点。
添加Button
预制件的方式
制作一个预制件:
新增一个button,
将其重命名为:CustomButtom
,其中的lable不需要,可以删除。
选中按钮的背景层级。将需要的图片拖入到其Sprite Frame
中。
在assets
的下一级新增一个文件夹并命名为resources
,【注意】:名称必须为这个,这相当于系统固定指定的一个文件名称。加载的预制件必须放在这个目录下。
将刚才制作的按钮拖到这个目录或其子文件夹下,,并在层级中删除刚才制作的CustomButton
,将预制件改名为:CustomButton_prefab
方便区分名称
编写脚本:
在上一篇的最后,我们根据官方步骤写了一个简单的游戏。,我们在这个游戏的基础上编写脚本。
通过新建一个脚本的方式来写CustomButtonTS.ts
。
在类中添加一个方法
addButtonTOCenter() {
let self = this; // 因为在下面这个加载毁掉中,this会发生变化, 所以在此之前,要先保存这个this
// 参数: 预制件的路径从resources开始 asset 强转成cc.Prefab ,方便下面调用不报错
cc.resources.load('GamePrefab/CustomButton_prefab', cc.Prefab, (err, asset:cc.Prefab) => {
// 实例化预制体按钮
let buttonNode = cc.instantiate(asset);
buttonNode.position = cc.v3(0, 0); // 设置 位置
self.node.addChild(buttonNode); // 加入到节点
// 直接加载到当前场景的Canvas节点上
//var scene = cc.director.getScene();
//buttonNode.parent = scene.getChildByName('Canvas');
});
}
将脚本挂载到一个节点 并调用
1、添加组件
在这个Demo中,我将其挂载到分数label下作为其组件
2、调用
在Game
脚本中,在合适的时机调用,这里就直接在star中调用,也就是game一加载,就显示这个自定义的按钮。
start () {
// this.scoreDisplay.getComponent('CustomButtonTS').addButtonTOCenter();
let scoreLabel = this.scoreDisplay; // 当前的score节点 , 因为将自定义的按钮挂载到score下
let comp = scoreLabel.getComponent('CustomButtonTS'); // 获取score节点下的 CustomButtonTS组件
comp.addButtonTOCenter(); // 调用这个组件的方法
},
这样我们就像自定义个按钮加到了score上面。
预制件的其他方式
上面的代码中,预制件是通过代码加载的。这里做一下调整。通过属性挂载的方式。
1、在脚本CustomButtonTS.ts
中添加一个属性用来关联预制件
// @property(cc.Prefab)
// buttonPrefab: cc.Prefab = null;
@property({
type: cc.Prefab,
displayName: '关联的预制件按钮',
tooltip: '将之前制作的预制件拖到这里进行关联',
})
customPrefab: cc.Prefab = null;
2、刚才将这个脚本挂载到Score下,查看Score下的这个脚本组件,并将按钮的预制件与这个属性进行关联
3、调整按钮的加载方法
// 加载预制件资源的方式
// addButtonTOCenter() {
// let self = this; // 因为在下面这个加载回调中,this会发生变化, 所以在此之前,要先保存这个this
// // 参数: 预制件的路径从resources开始 asset 强转成cc.Prefab ,方便下面调用不报错
// cc.resources.load('GamePrefab/playButton_prefab', cc.Prefab, (err, asset: cc.Prefab) => {
// // 实例化预制体按钮
// let buttonNode = cc.instantiate(asset);
// buttonNode.position = cc.v3(0, 0); // 设置 位置
// self.node.addChild(buttonNode); // 加入到节点
// // debugger
// });
// }
// 属性已关联 直接实例化
addButtonTOCenter() {
// 实例化预制体
let buttonNode = cc.instantiate(this.customPrefab);
buttonNode.position = cc.v3(0, 0); // 设置 位置
this.node.addChild(buttonNode);
// 直接加载到当前场景的Canvas节点上
//var scene = cc.director.getScene();
//buttonNode.parent = scene.getChildByName('Canvas');
}
为预制件按钮添加事件
1、双击打开之前的按钮预制件
2、更改按钮的事件数量。
3、将节点拖入到第一个参数
4、编写脚本
因为这个脚本需要挂载到这个按钮预制件上, 一般来说,需要单独为这个预制件写一个脚本,比如之前的CustomButtonTS
脚本,这个脚本已经被加入Scrore上,作为其组件.
如果再挂载到这个预制件上,那么这个脚本的生命周期的方法将被调用2次,可能会引起不必要的问题。
新建一个脚本CustomButtonActivityTS
并编写代码:
const { ccclass, property } = cc._decorator;
@ccclass
export default class CustomButtonActivityTS extends cc.Component {
start() {
}
// 定义一个方法clickActivity
clickActivity() {
console.log('按钮点击了');
}
}
5、将新建的这个脚本挂载到按钮预制件上
6、第二个参数选择刚才挂载的脚本组件参数含义
7、第三个参数选择按钮执行的方法
纯代码加载一个Button
还在在刚才的脚本,注释掉其他的代码,只保留这个方法即可
注意
:动态加载的图片 要放在resources
目录或其子目录
addButtonTOCenter() {
let buttonNode = new cc.Node; // 创建一个节点(Node)
let buttonComponent = buttonNode.addComponent(cc.Button); // 节点上加一个button的组件
// 设置节点的位置和大小
buttonNode.setPosition(cc.v2(100, 0));
buttonNode.setContentSize(cc.size(100, 40));
// 添加图片组件
let imageNode = new cc.Node;
let imageComponent = imageNode.addComponent(cc.Sprite);
// imageComponent.spriteFrame =
imageNode.parent = buttonNode;
cc.resources.load("Image/icon2", cc.SpriteFrame, function (err, spriteFrame:cc.SpriteFrame) {
if (err) {
console.error('Failed to load image:', err);
return;
}
imageComponent.spriteFrame = spriteFrame;
});
// 添加label组件
let labelNode = new cc.Node;
let labelCompoment = labelNode.addComponent(cc.Label);
labelCompoment.string = '按钮';
labelNode.parent = buttonNode;
// 将button节点加入到父节点
// this.node.parent.addChild(buttonNode);
buttonNode.parent = this.node.parent;
}
代码为按钮添加事件
简易方法
最简单的方式:这种方式有局限性 就是没有EventData的参数传递。官方解释
// 添加按钮点击事件
buttonComponent.node.on('click', this.buttomActivity, this);
buttomActivity(button) {
console.log('按钮被点击了');
}
第一个参数:type: string
: 是一个字符串类型,不过有进行枚举定义官方文档
this.node.on(cc.Node.EventType.TOUCH_START, this.memberFunction, this); // if "this" is component and the "memberFunction" declared in CCClass. node.on(cc.Node.EventType.TOUCH_START, callback, this); node.on(cc.Node.EventType.TOUCH_MOVE, callback, this); node.on(cc.Node.EventType.TOUCH_END, callback, this); node.on(cc.Node.EventType.TOUCH_CANCEL, callback, this); node.on(cc.Node.EventType.ANCHOR_CHANGED, callback); node.on(cc.Node.EventType.COLOR_CHANGED, callback);
完整方法
addButtomActivity(buttonComponent: cc.Button) {
var clickEventHandler = new cc.Component.EventHandler(); // 创建一个event组件
clickEventHandler.target = this.node; // 事件的回调所在节点 ---- 我这里就是在自己 this.node
clickEventHandler.component = 'CodeCustomButtonTS'; // 事件的回调所在脚本的名字。
clickEventHandler.handler = 'callback'; // 方法名
clickEventHandler.customEventData = '需要传递的信息'; // eventData 传递参数
buttonComponent.clickEvents.push(clickEventHandler);
}
callback(event, customEventData) {
// 这里 event 是一个 Event 对象,你可以通过 event.target 取到事件的发送节点
var node = event.target;
var button = node.getComponent(cc.Button);
// 这里的 customEventData 参数就等于你之前设置的 "foobar"
console.log(customEventData);
}
参数:
target
: 事件的回调所在节点
component
: 组件(脚本)的文件名, 也就是需要回调的方法在哪个脚本
handler
: 回调的方法名
customEventData
: 额外传递的参数