You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Cocos触摸事件处理方法及Cocos Creator 1.9触摸进出事件实现疑问

嘿,我来帮你搞定这两个Cocos开发里的常见问题:

1. 如何处理Cocos中的触摸事件?

在Cocos Creator里,触摸事件处理主要有两种常用思路,按需选择就行:

  • 节点级事件监听:直接给需要响应触摸的节点绑定事件,这种方式只会对当前节点生效,不会干扰其他元素。比如给按钮加触摸反馈:

    // 获取目标节点
    const targetBtn = this.node.getChildByName("CustomButton");
    // 注册触摸开始事件
    targetBtn.on(cc.Node.EventType.TOUCH_START, (event) => {
        console.log("触摸开始啦!");
        // 给个按钮缩放的反馈
        targetBtn.scale = 0.95;
    }, this);
    // 注册触摸结束事件
    targetBtn.on(cc.Node.EventType.TOUCH_END, (event) => {
        console.log("触摸结束啦!");
        targetBtn.scale = 1.0;
    }, this);
    

    常用的触摸事件类型还有TOUCH_MOVE(触摸移动)、TOUCH_CANCEL(触摸被打断)。

  • 全局触摸事件监听:如果需要监听整个屏幕的触摸行为(不管点在哪个节点上),就用全局事件:

    // 监听全局触摸开始
    cc.systemEvent.on(cc.SystemEvent.EventTouch.START, (event) => {
        console.log("全局触摸触发,坐标:", event.getLocation());
    }, this);
    

2. 在Cocos Creator 1.9中是否可以处理触摸进入或触摸离开事件?

没错,Cocos Creator 1.9版本的原生触摸体系里确实没有直接提供TOUCH_ENTERTOUCH_LEAVE这类事件——这是2.x及以后版本才新增的节点触摸类型。

你用TOUCH_MOVE模拟没成功,大概率是没处理好坐标转换或者碰撞检测逻辑。这里给你一个可行的模拟方案:

  1. 先给目标节点加上碰撞组件(比如cc.Collider2D,根据节点类型选对应碰撞体),确保碰撞区域准确覆盖需要检测的范围;
  2. 在脚本里维护一个状态变量,记录触摸是否在节点范围内:
    properties: {
        targetNode: cc.Node, // 需要检测触摸进入/离开的节点
    },
    isTouchInside: false, // 标记当前触摸是否在节点内
    
    onLoad() {
        // 监听全局触摸移动、结束和取消事件
        cc.systemEvent.on(cc.SystemEvent.EventTouch.MOVE, this.onTouchMove, this);
        cc.systemEvent.on(cc.SystemEvent.EventTouch.END, this.resetTouchState, this);
        cc.systemEvent.on(cc.SystemEvent.EventTouch.CANCEL, this.resetTouchState, this);
    },
    
    onTouchMove(event) {
        // 将屏幕触摸坐标转换为节点本地坐标
        const localPos = this.targetNode.convertToNodeSpaceAR(event.getLocation());
        // 获取碰撞组件,检测坐标是否在节点范围内
        const collider = this.targetNode.getComponent(cc.Collider2D);
        if (collider) {
            const isInside = collider.bounds.contains(localPos);
            if (isInside && !this.isTouchInside) {
                // 触发触摸进入逻辑
                console.log("触摸进入节点!");
                this.isTouchInside = true;
                this.targetNode.color = cc.Color.RED; // 示例:节点变红
            } else if (!isInside && this.isTouchInside) {
                // 触发触摸离开逻辑
                console.log("触摸离开节点!");
                this.isTouchInside = false;
                this.targetNode.color = cc.Color.WHITE; // 示例:恢复原色
            }
        }
    },
    
    resetTouchState() {
        // 触摸结束后重置状态
        if (this.isTouchInside) {
            this.isTouchInside = false;
            this.targetNode.color = cc.Color.WHITE;
        }
    },
    
    onDestroy() {
        // 记得移除事件监听,避免内存泄漏
        cc.systemEvent.off(cc.SystemEvent.EventTouch.MOVE, this.onTouchMove, this);
        cc.systemEvent.off(cc.SystemEvent.EventTouch.END, this.resetTouchState, this);
        cc.systemEvent.off(cc.SystemEvent.EventTouch.CANCEL, this.resetTouchState, this);
    }
    
    要是你的节点会动态缩放/旋转,记得同步更新碰撞体,不然检测会不准。如果不想用碰撞组件,也可以通过节点的getContentSize()和锚点计算本地坐标是否在节点范围内,但碰撞组件的方式对复杂形状的节点更准确。

内容的提问来源于stack exchange,提问作者lazlo barragan

火山引擎 最新活动