Cocos Creator 3.0 基础——事件系统

这篇博客详细介绍了游戏开发中不同类型的交互事件处理,包括触摸事件(TOUCH_START, TOUCH_MOVE, TOUCH_END, TOUCH_CANCEL)、键盘事件(KEY_DOWN, KEY_UP)以及3D和2D碰撞事件。通过示例代码展示了如何监听和响应这些事件,实现角色控制和物体碰撞检测,为游戏增加交互性和响应性。
摘要由CSDN通过智能技术生成

触摸事件

触摸事件指的是用户手指触摸时候的事件

  • TOUCH_START:当手指触点落在目标节点区域内时。
  • TOUCH_MOVE:当手指在屏幕上移动时。
  • TOUCH_END:当手指在目标节点区域内离开屏幕时。
  • TOUCH_CANCEL:当手指在目标节点区域外离开屏幕时。
//绑定事件
this.node.on(SystemEvent.EventType.TOUCH_START, this._touchStart, this);
this.node.on(SystemEvent.EventType.TOUCH_END, this._touchEnd, this);
this.node.on(SystemEvent.EventType.TOUCH_MOVE, this._touchMove, this);
this.node.on(SystemEvent.EventType.TOUCH_CANCEL, this._touchCancel, this);
//解除事件
this.node.off(SystemEvent.EventType.TOUCH_START, this._touchStart, this);
this.node.off(SystemEvent.EventType.TOUCH_END, this._touchEnd, this);
this.node.off(SystemEvent.EventType.TOUCH_MOVE, this._touchMove, this);
this.node.off(SystemEvent.EventType.TOUCH_CANCEL, this._touchCancel, this);
//事件回调
_touchMove(touch: Touch, event: EventTouch) {}
_touchStart(touch: Touch, event: EventTouch) {}
_touchEnd(touch: Touch, event: EventTouch) {}
_touchCancel(touch: Touch, event: EventTouch) {}

键盘事件

键盘事件指的是用户在键盘上输入的事件,他可以同时按下多个键盘,并要完成多个事件的响应

  • SystemEventType.KEY_DOWN:键盘按下
  • SystemEventType.KEY_UP:键盘释放
//绑定事件
systemEvent.on(SystemEventType.KEY_DOWN, this.onKeyDown, this);
systemEvent.on(SystemEventType.KEY_UP, this.onKeyUp, this);
//解除事件
systemEvent.off(SystemEventType.KEY_DOWN, this.onKeyDown, this);
systemEvent.off(SystemEventType.KEY_UP, this.onKeyUp, this);
//事件回调
onKeyDown(event: EventKeyboard) {}
onKeyUp(event: EventKeyboard) {}

监听键盘wasd,控制人物往前后左右运动

export class CubeCtrl extends Component {

    body: RigidBody = null

    keyMask = 0

    speed = 50

    start() {
        this.body = this.node.getComponent(RigidBody)
        systemEvent.on(SystemEventType.KEY_DOWN, this.onKeyDown, this);
        systemEvent.on(SystemEventType.KEY_UP, this.onKeyUp, this);
    }

    onKeyDown(event: EventKeyboard) {
        switch (event.keyCode) {
            case macro.KEY.a:
                this.keyMask |= (1 << 0)
                break;
            case macro.KEY.s:
                this.keyMask |= (1 << 1)
                break;
            case macro.KEY.w:
                this.keyMask |= (1 << 2)
                break;
            case macro.KEY.d:
                this.keyMask |= (1 << 3)
                break;
            case macro.KEY.space:
                this.keyMask |= (1 << 4)
                break;
        }
    }

    onKeyUp(event: EventKeyboard) {
        switch (event.keyCode) {
            case macro.KEY.a:
                this.keyMask &= ~(1 << 0)
                break;
            case macro.KEY.s:
                this.keyMask &= ~(1 << 1)
                break;
            case macro.KEY.w:
                this.keyMask &= ~(1 << 2)
                break;
            case macro.KEY.d:
                this.keyMask &= ~(1 << 3)
                break;
            case macro.KEY.space:
                this.keyMask &= ~(1 << 4)
                break;
        }
    }

    update(deltaTime: number) {
        if (this.keyMask & (1 << 0)) {
            var pos = this.node.getPosition()
            this.body.applyForce(v3(this.speed, 0, 0))
        }
        if (this.keyMask & (1 << 3)) {
            var pos = this.node.getPosition()
            this.body.applyForce(v3(-this.speed, 0, 0))
        }
        if (this.keyMask & (1 << 1)) {
            var pos = this.node.getPosition()
            this.body.applyForce(v3(0, 0, -this.speed))
        }
        if (this.keyMask & (1 << 2)) {
            var pos = this.node.getPosition()
            this.body.applyForce(v3(0, 0, this.speed))
        }
        if (this.keyMask & (1 << 4)) {
            var pos = this.node.getPosition()
            this.body.applyForce(v3(0, this.speed, 0))
        }
    }
}

触发事件

触发事件属于两个物体触碰后触发,其事件触发的前提

  • 需要配置物理系统分组
  • 需要有刚体组件才可触发
  • 需要刚体组件勾选IsTrigger选项才可触发

触发事件类型

  • onTriggerEnter:触发开始
  • onTriggerStay:触发保持
  • onTriggerExit:触发结束
//绑定事件
onEnable() {
    const collision = this.getComponent(Collider)
    collision.on('onTriggerEnter', this._onTriggerEnter, this);
    collision.on('onTriggerStay', this._onTriggerStay, this);
    collision.on('onTriggerExit', this._onTriggerExit, this);
}
//解除事件
onDisable() {
    const collision = this.getComponent(Collider)
    collision.off('onTriggerEnter', this._onTriggerEnter, this);
    collision.off('onTriggerStay', this._onTriggerStay, this);
    collision.off('onTriggerExit', this._onTriggerExit, this);
}
//触发事件掩码
public static CollisionT = {
   SELF_PLANE: 1 << 1,
   ENEMY_PLANE: 1 << 2,
   SELF_BULLET: 1 << 3,
   ENEMY_BULLET: 1 << 4
}
//触发事件回调,通过掩码判断是哪个物体
_onTriggerEnter(event: ITriggerEvent) {
   const group = event.otherCollider.getGroup()
   const name = event.selfCollider.node.name
   if (group === Constants.CollisionT.ENEMY_BULLET || group === Constants.CollisionT.ENEMY_PLANE) {
       
   }
}

2D碰撞事件

组件要使用Collider2D类型,2D事件有全局的监听

// 注册全局碰撞回调函数
if (PhysicsSystem2D.instance) {
    PhysicsSystem2D.instance.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
    PhysicsSystem2D.instance.on(Contact2DType.END_CONTACT, this.onEndContact, this);
    PhysicsSystem2D.instance.on(Contact2DType.PRE_SOLVE, this.onPreSolve, this);
    PhysicsSystem2D.instance.on(Contact2DType.POST_SOLVE, this.onPostSolve, this);
}

2D事件有组件的监听

//绑定事件
onEnable() {
    // 注册单个碰撞体的回调函数
    let collider = this.getComponent(Collider2D);
    if (collider) {
        collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
        collider.on(Contact2DType.END_CONTACT, this.onEndContact, this);
        collider.on(Contact2DType.PRE_SOLVE, this.onPreSolve, this);
        collider.on(Contact2DType.POST_SOLVE, this.onPostSolve, this);
    }

}
//解除事件
onDisable() {
    let collider = this.getComponent(Collider2D);
    if (collider) {
        collider.off(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
        collider.off(Contact2DType.END_CONTACT, this.onEndContact, this);
        collider.off(Contact2DType.PRE_SOLVE, this.onPreSolve, this);
        collider.off(Contact2DType.POST_SOLVE, this.onPostSolve, this);
    }
}
//触发事件回调
onBeginContact (selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
    // 只在两个碰撞体开始接触时被调用一次
    console.log('onBeginContact');
}
onEndContact (selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
    // 只在两个碰撞体结束接触时被调用一次
    console.log('onEndContact');
}
onPreSolve (selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
    // 每次将要处理碰撞体接触逻辑时被调用
    console.log('onPreSolve');
}
onPostSolve (selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
    // 每次处理完碰撞体接触逻辑时被调用
    console.log('onPostSolve');
}

3D碰撞事件

碰撞事件属于两个物体碰撞后触发,其事件触发的前提

  • 需要配置物理系统分组
  • 需要有刚体组件才可触发
  • 静态类型的刚体之间不会产生碰撞数据

触发事件类型

  • onCollisionEnter:碰撞开始
  • onCollisionStay:碰撞保持
  • onCollisionExit:碰撞结束
//绑定事件
onEnable() {
    const collision = this.getComponent(Collider)
    collision.on('onCollisionEnter', this._onCollisionEnter, this);
    collision.on('onCollisionStay', this._onCollisionStay, this);
    collision.on('onCollisionExit', this._onCollisionExit, this);
}
//解除事件
onDisable() {
    const collision = this.getComponent(Collider)
    collision.off('onCollisionEnter', this._onCollisionEnter, this);
    collision.off('onCollisionStay', this._onCollisionStay, this);
    collision.off('onCollisionExit', this._onCollisionExit, this);
}
//触发事件掩码
public static CollisionT = {
   SELF_PLANE: 1 << 1,
   ENEMY_PLANE: 1 << 2,
   SELF_BULLET: 1 << 3,
   ENEMY_BULLET: 1 << 4
}
//触发事件回调,通过掩码判断是哪个物体
_onCollisionEnter(event: ICollisionEvent) {
   const group = event.otherCollider.getGroup()
   const name = event.selfCollider.node.name
   if (group === Constants.CollisionT.ENEMY_BULLET || group === Constants.CollisionT.ENEMY_PLANE) {
       
   }
}

3D模型点击事件

3D模型需要创建射线去射到碰撞体上,才能实现点击物体,物体上需要有Collision组件才行

@property({ type: Camera, tooltip: '主相机' })
public mainCamera: Camera | null = null;

@property({ type: Node, tooltip: '待触摸物体' })
public node_touch_1: Node | null = null;

private _ray: geometry.Ray = new geometry.Ray();

onLoad() {
    systemEvent.on(SystemEventType.TOUCH_START, this.onTouchStart, this);
}

onDestory() {
    systemEvent.off(SystemEventType.TOUCH_START, this.onTouchStart, this);
}

onTouchStart(touch: Touch, event: EventTouch) {
    // 基于摄像机 画射线
    this.mainCamera?.screenPointToRay(event.getLocation().x, event.getLocation().y, this._ray);
    // 基于物理碰撞器的射线检测
    // 当点击 node_touch_1 时,控制台打印 “node_touch_1”
    if (PhysicsSystem.instance.raycast(this._ray)) {
        const r = PhysicsSystem.instance.raycastResults;
        for (let index = 0; index < r.length; index++) {
            const element = r[index];
            console.log('当前点击: ' + element.collider.node.uuid);
            if (element.collider.node.uuid == this.node_touch_1?.uuid) {
            
            }
        }
    }
}
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

许英俊潇洒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值