当前位置: 首页 > article >正文

cocos creator 3.8 合成大西瓜Demo 11

界面上的Node节点: 背景 警戒线 三面墙 初始位置节点 水果容器

先分组吧,墙 地板 水果

创建预制体 先挂一个脚本 刚体碰撞器先弄上再说

import { _decorator, Component, Node } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('FruitData')
export class FruitData extends Component {
   //水果的Id 区分哪一种水果的
   fruitId: number = 0;
   //水果的碰撞次数 主要记录水果的状态用的
   contactNum: number = 0;
   //是否合成
   isSynthesis: boolean = false;
}

再建一个脚本,开始折腾走起

    @property({ type: Node, displayName: "水果生成的位置" })
    fruitStart: Node = null;//大小随便,位置合理就行,不行就大小[0,0]
    @property({ type: Node, displayName: "水果的父节点" })
    fruitRoot: Node = null;//水果容器
    @property({ type: [Prefab], displayName: "水果的预制体" })
    fruitPrefabs: Prefab[] = [];//一堆水果的预制体
    //存储临时节点,方便计算用
    currentFruit: Node = null;
    @property({ type: Node, displayName: "警告" })
    WarnningLine: Node = null;

开始游戏了

    start() {
        //创建一个随机水果,前两前三的
        this.createRadomFruit();
        //加上触摸监听 看api好像input比node监听使用范围广
        input.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
        input.on(Input.EventType.TOUCH_END, this.onTouchEnd, this);
    }

创建水果了

    createRadomFruit() {
        const fruitId: number = Math.floor(Math.random() * 3);
        const fruitNode: Node = instantiate(this.fruitPrefabs[fruitId]);
        fruitNode.setPosition(this.fruitStart.position);
        //禁用刚体,用来监听移动事件后再开启
        fruitNode.getComponent(RigidBody2D).enabled = false;
        fruitNode.getComponent(RigidBody2D).gravityScale = 2;
        //赋值
        fruitNode.getComponent(FruitData).fruitId = fruitId;
        fruitNode.getComponent(FruitData).contactNum = 0;
        //监听碰撞
        const collider2D: Collider2D = fruitNode.getComponent(Collider2D);
        collider2D.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
        fruitNode.setParent(this.fruitRoot);
        //用一个临时的Node来存储这个节点,方便操作
        this.currentFruit = fruitNode;
    }

两个监听

    //收到点击事件后,水果位置平移
    onTouchStart(event: EventTouch) {
        //放置连续点击
        if (!this.currentFruit) return;
        //可以看看这个https://blog.csdn.net/weixin_44053279/article/details/129568612
        //获取 UI 坐标系下的触点位置
        const touchPos = event.getUILocation();
        //记住 是父节点 可以搜一下坐标空间转换
        const parentPos = this.fruitRoot.getComponent(UITransform).convertToNodeSpaceAR(v3(touchPos.x, touchPos.y, 0));
        //这是个节点位置 position现在是个静态的 拿不到.x
        const fruitPos = this.currentFruit.getPosition();
        fruitPos.x = parentPos.x;
        // 防止穿透,还是用tween动画吧
        // this.currentFruit.setPosition(fruitPos);
        tween(this.currentFruit)
            .to(.3, { position: fruitPos })
            .start();
    }

    onTouchEnd(event: EventTouch) {
        //放置连续点击
        if (!this.currentFruit) return;
        this.currentFruit.getComponent(RigidBody2D).enabled = true;
        this.currentFruit = null;
        //延时一下 生成下一个
        this.scheduleOnce(this.createRadomFruit, 2);
        //用来检测是否超过预期位置没
        this.scheduleOnce(this.checkGameOver, 2);
    }

碰撞检测

    //3.8 .d.ts中没给监听的参数
    //https://forum.cocos.org/t/topic/158425
    onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
        const selfFruitData = selfCollider.getComponent(FruitData);
        const otherFruitData = otherCollider.getComponent(FruitData);
        if (otherCollider.group === Math.pow(2, 1)) {
            selfCollider.getComponent(FruitData).contactNum += 1;
            otherCollider.getComponent(FruitData).contactNum += 1;
        }
        if (otherCollider.group === Math.pow(2, 3)) {
            selfCollider.getComponent(FruitData).contactNum += 1;
        }
        if (otherCollider.group !== Math.pow(2, 1)) return;
        //Id相同 未合成 否则也返回
        if (selfFruitData.fruitId !== otherFruitData.fruitId) return;
        if (selfFruitData.isSynthesis || otherFruitData.isSynthesis) return;
        selfFruitData.isSynthesis = true;
        otherFruitData.isSynthesis = true;
        //合成后的新水果
        const synthesisFruitId = selfFruitData.fruitId + 1;
        const synthesisFruitPos = selfCollider.node.position;
        //https://blog.csdn.net/loveyoulouyou/article/details/127583198
        this.scheduleOnce(() => {
            otherCollider.getComponent(RigidBody2D).enabled = false;
            selfCollider.getComponent(RigidBody2D).enabled = false;
            tween(otherCollider.node)
                .to(.2, { position: synthesisFruitPos })
                .to(.2, { scale: new Vec3(1.2, 1.2, 1) })
                .parallel()
                .call(() => {
                    //碰撞后立即实例化会报错,给一个延时器,tween动画都可以
                    this.createSynthesisFruit(synthesisFruitId, synthesisFruitPos);
                })
                .call(() => {
                    selfCollider.node.destroy();
                    otherCollider.node.destroy();
                })
                .start();
        }, 0.1);
    };

 合成的逻辑


    createSynthesisFruit(synthesisFruitId: number, synthesisFruitPos: Vec3) {
        const SynthesisNode: Node = instantiate(this.fruitPrefabs[synthesisFruitId]);
        //刚体碰撞 回弹可能造成穿透效果
        synthesisFruitPos.y += 10;
        SynthesisNode.setPosition(synthesisFruitPos);
        SynthesisNode.getComponent(RigidBody2D).enabled = false;
        SynthesisNode.getComponent(FruitData).contactNum = 0;
        SynthesisNode.getComponent(RigidBody2D).gravityScale = 2;
        //赋值
        SynthesisNode.getComponent(FruitData).fruitId = synthesisFruitId;
        //监听碰撞
        SynthesisNode.getComponent(Collider2D).on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
        SynthesisNode.setParent(this.fruitRoot);
        this.scheduleOnce(() => {
            //立即改变刚体状态也会报错,给一个延时
            SynthesisNode.getComponent(RigidBody2D).enabled = true;
            SynthesisNode.getComponent(FruitData).contactNum += 1;
            if (synthesisFruitId === this.fruitPrefabs.length - 1) {
                // if (synthesisFruitId === 3) {
                console.log("=====================胜利了=====================");
                this.reStartGame();
            }
        }, .1);
    }

检测是否要结束游戏

    //遍历所有水果,比较高度
    checkGameOver() {
        const warnningLinePos = this.WarnningLine.getPosition();
        for (let i = 0; i < this.fruitRoot.children.length; i++) {
            const element = this.fruitRoot.children[i];
            //水果没下落呢
            if (element.getComponent(FruitData).contactNum === 0) continue;
            if (element.getPosition().y >= warnningLinePos.y - 300) {
                console.log("=====================游戏警告=====================");
            }
            if (element.getPosition().y >= warnningLinePos.y) {
                console.log("=====================游戏结束=====================");
                break;
            }
        }
    }

重新开始

    //重新开始
    reStartGame() {
        this.fruitRoot.removeAllChildren();
        this.createRadomFruit();
    }

就这样了,没写其它的逻辑,刚体有点乱,不要立即改变一些东西,总之就是要么用计时器,要么tween一下。


http://www.kler.cn/a/414224.html

相关文章:

  • 山峰数(hill)
  • Python中的23种设计模式:详细分类与总结
  • 阿里云ECS服务器监控报警配置
  • python的openpyxl库设置表格样式:字体/边框/对齐/颜色等
  • Airsim安装问题:This project was made with a different version of the Unreal Engine.
  • React第七节 组件三大属性之 refs 的用法注意事项
  • 卷积神经网络:图像特征提取与分类的全面指南
  • AIGC时代:如何快速搞定Spring Boot+Vue全栈开发
  • C#基础41-45
  • 栩熙酷科技,抖音电商优势凸显
  • 【k8s深入理解之 Scheme 补充-7】理解无版本资源、有版本资源、元数据信息等联系和区别
  • AI的魔力:如何为开源软件注入智慧,开启无限可能
  • C#并行使用及性能对比
  • 【云原生系列】迁移云上需要考虑哪些问题
  • 数据分析:转录组数据分析方法汇总(差异分析,PCA,聚类分析和功能富集分析)
  • Eclipse 创建 Java 接口
  • Unity3D ngui和ugui区别与优缺点详解
  • linux高级系统编程之进程
  • 无人机反制技术多方法实现详解
  • GitHub仓库的README添加视频播放链接和压缩视频网站推荐
  • 【MATLAB源码-第224期】基于matlab的快跳频系统仿真采用4FSK,模拟了单音干扰,宽带干扰以及部分频带干扰,输出误码率曲线以及各节点图像。
  • C++基本:const成员函数与非Const成员函数的调用
  • WPF+MVVM案例实战与特效(三十)- 封装一个系统日志显示控件
  • 串口在系统framework 中的应用
  • c++ 拓扑排序
  • C语言编码规范