Cocos Creator(6)---代码添加按钮

742 阅读6分钟

前面的那些内容,在第一次理解的时候, 可能很多地方比较模糊。随着看的文档内容,有些东西会慢慢清晰起来。

官网内容

节点(Node)

我目前理解节点,是将其认为是iOS中的view。当前节点中的子节点,就相当于世view下的子view。

比如在脚本中,获取当前的节点:通过Demo中来操作认识。

1、通过编辑器 新建一个Hello World的模版Demo。

image.png

2、新建一个HelloWorld的TypeScript脚本,将其拖入到Canvas节点的属性检查器中。 image.png

3、在脚本中编写代码。

    start() {

        let curNode = this.node;            // 当前节点
        let nodes = curNode.children;       // 当前节点的子节点
        let parentNode = curNode.parent;    // 其父节点
        console.log(nodes);
        console.log(parentNode);

    }

运行起来之后,查看打印信息(快捷键:F12

image.png

从打印的名字上来看,就是当前节点Canvas下的所有节点。

4、当前HelloWorld脚本是挂载在Canvas上,把其从Canvas删掉,加载到其他的节点上。

image.png

挂载到其他的节点

image.png

此时 重新运行,查看打印信息,发现打印的是空数组,因为main Camera下没有子节点。

添加Button

预制件的方式

制作一个预制件:

新增一个button,

image.png

将其重命名为:CustomButtom,其中的lable不需要,可以删除。
选中按钮的背景层级。将需要的图片拖入到其Sprite Frame中。

image.png

assets的下一级新增一个文件夹并命名为resources,【注意】:名称必须为这个,这相当于系统固定指定的一个文件名称。加载的预制件必须放在这个目录下。

将刚才制作的按钮拖到这个目录或其子文件夹下,,并在层级中删除刚才制作的CustomButton,将预制件改名为:CustomButton_prefab方便区分名称

image.png

编写脚本:

上一篇的最后,我们根据官方步骤写了一个简单的游戏。,我们在这个游戏的基础上编写脚本。

通过新建一个脚本的方式来写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下作为其组件

image.png

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下的这个脚本组件,并将按钮的预制件与这个属性进行关联

image.png

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、将节点拖入到第一个参数

image.png

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、第三个参数选择按钮执行的方法

image.png

image.png

纯代码加载一个Button

还在在刚才的脚本,注释掉其他的代码,只保留这个方法即可

注意:动态加载的图片 要放在resources目录或其子目录

图片动态加载成SpriteFrame的方法


    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 : 额外传递的参数