cocos做飞机大战笔记【开始、游戏中,游戏结束界面】


UI界面

创建开始前的场景

首先要将左上角的3D切成2D,然后创建一个Widget组件重命名为gameStart(因为需要适配),然后在下面添加logo与文字label调整到相对应的位置

在这里插入图片描述

创建游戏中的界面

没啥复杂操作,我直接仍图了
在这里插入图片描述
在这里插入图片描述

游戏结束的场景

gameOver节点要阻止事件穿透
在这里插入图片描述

这里先举个例子其他按这个思路来就行
在这里插入图片描述
效果如下
在这里插入图片描述
然后将这三个节点隐藏
在这里插入图片描述

脚本编写

1. 脚本中接受上面三个节点

在这里插入图片描述
然后将节点挂入
在这里插入图片描述

2. 按钮绑定点击事件

先写好方法
在这里插入图片描述
将方法绑入节点

3. 绑定游戏分数

在这里插入图片描述
引擎中绑定分数组件
在这里插入图片描述

3. 游戏结束逻辑

在这里插入图片描述
引擎中挂载
在这里插入图片描述

4. 设置血量

先定义三个状态,玩家飞机血量上限,死亡状态,当前血量
在这里插入图片描述
由于GameManager要调用SelfPlane中的方法,所以要把这里类型改成SelfPlane,并将之前设置位置的地方都做修改
在这里插入图片描述
然后判断玩家是否死亡
在这里插入图片描述
在这里插入图片描述

完整代码

  • UIMain.ts

import { _decorator, Component, Node, systemEvent, SystemEvent, Touch, EventTouch, Vec2 } from 'cc';
import { GameManager } from '../framework/GameManager';
const { ccclass, property } = _decorator;


@ccclass('UIMain')
export class UIMain extends Component {
    @property
    public planeSpeed = 1;//飞机移动速度

    @property(Node)
    public playerPlane: Node = null;

    //gameManager的引用
    @property(GameManager)
    public gameManager: GameManager = null;

    @property(Node)
    public gameStart: Node = null;//游戏开始2D UI
    @property(Node)
    public game: Node = null;//游戏中2D UI
    @property(Node)
    public gameOver: Node = null;//游戏结束2D UI

    start() {
        this.node.on(SystemEvent.EventType.TOUCH_START, this._touchStart, this);
        this.node.on(SystemEvent.EventType.TOUCH_MOVE, this._touchMove, this);
        this.node.on(SystemEvent.EventType.TOUCH_END, this._touchEnd, this);
        //初始化游戏开始页面展示
        this.gameStart.active = true;
    }

    // update (deltaTime: number) {
    //     // [4]
    // }
    /**
     * 再来一局的按钮点击事件
     */
    public reStart() {
        this.gameOver.active = false;
        this.game.active = false;
        this.gameManager.gameReStart();
    }
    /**
      * 回到主页的按钮点击事件
      */
    public returnMain() {
        this.gameOver.active = false;
        this.gameStart.active = true;
        this.gameManager.returnMain();
    }
    /**
     * 触摸开始 子弹发射
     * @param touch 
     * @param event 
     */
    _touchStart(touch: Touch, event: EventTouch) {
        //判断第一次触摸屏幕的时候游戏是否开始
        if (this.gameManager.isGameStart) {
            this.gameManager.isShooting(true);
        } else {
            //游戏开始切换游戏状态
            this.gameStart.active = false;
            this.game.active = true;
            this.gameManager.gameStart();
        }
    }
    /**
     * 触摸中
     * @param touch 
     * @param event 
     */
    _touchMove(touch: Touch, event: EventTouch) {
        //判断游戏状态
        if (!this.gameManager.isGameStart) {
            return;
        }

        //获取当前触点值与上一次触点值之间的差值 
        const delta = touch.getDelta();
        //获取当前位置
        let pos = this.playerPlane.position;
        //移动位置z与x移动 y轴不变 
        /**
         * 乘0.01是因为每移动一段距离移动的都是单位,但是在操作屏幕触点的时候操作的其实是像素,两者之间不能转换,所以只能预估一下大概的移动距离 */
        this.playerPlane.setPosition(pos.x + 0.01 * this.planeSpeed * delta.x, pos.y, pos.z - 0.01 * this.planeSpeed * delta.y);
    }
    /**
         * 触摸结束 子弹取消发射
         * @param touch 
         * @param event 
         */
    _touchEnd(touch: Touch, event: EventTouch) {
        //判断游戏状态
        if (!this.gameManager.isGameStart) {
            return;
        }

        this.gameManager.isShooting(false);
    }
}


  • SelfPlane.ts

import { _decorator, Component, Node, Collider, ITriggerEvent } from 'cc';
import { Constant } from '../framework/Constant';
const { ccclass, property } = _decorator;

@ccclass('SelfPlane')
export class SelfPlane extends Component {
    public lifeValue = 5;//玩家飞机血量上限
    public isDie = false;//是否死亡

    private _currLife = 0;//当前飞机血量


    //监听事件
    onEnable() {
        const collider = this.getComponent(Collider);//获取碰撞组件
        collider.on('onTriggerEnter', this._onTriggerEnter, this);//碰撞到了立马处理逻辑
    }

    //取消事件
    onDisable() {
        const collider = this.getComponent(Collider);//获取碰撞组件
        collider.off('onTriggerEnter', this._onTriggerEnter, this);
    }

    public init() {
        this._currLife = this.lifeValue;//重置飞机血量
        this.isDie = false;
    }
    // update (deltaTime: number) {
    //     // [4]
    // }

    private _onTriggerEnter(event: ITriggerEvent) {
        const collisionGroup = event.otherCollider.getGroup();//获取分组
        if (collisionGroup === Constant.CollisionType.ENEMY_PLANE || collisionGroup === Constant.CollisionType.ENEMY_BULLET) {//敌方飞机或者敌方子弹判断掉血
            this._currLife--;//掉血
            if (this._currLife <= 0) {//判断当前血量是不是小于0
                this.isDie = true;
                console.log('self plane is die');
            }
        }
    }

}


  • GameManager.ts

import { _decorator, Component, Node, Prefab, instantiate, math, Vec3, BoxCollider, macro, Label } from 'cc';
import { Bullet } from '../bullet/Bullet';
import { BulletProp } from '../bullet/BulletProp';
import { EnemyPlane } from '../plane/EnemyPlane';
import { SelfPlane } from '../plane/SelfPlane';
import { Constant } from './Constant';
const { ccclass, property } = _decorator;


@ccclass('GameManager')
export class GameManager extends Component {
    // 关联玩家飞机
    @property(SelfPlane)
    public playerPlane: SelfPlane = null;
    // 关联所有子弹
    @property(Prefab)
    public bullet01: Prefab = null;
    @property(Prefab)
    public bullet02: Prefab = null;
    @property(Prefab)
    public bullet03: Prefab = null;
    @property(Prefab)
    public bullet04: Prefab = null;
    @property(Prefab)
    public bullet05: Prefab = null;
    // 射击周期
    @property
    public shootTime = 0.3;
    // 子弹移动速度
    @property
    public bulletSpeed = 1;

    /** 关联敌机 */
    @property(Prefab)
    public enemy01: Prefab = null;
    @property(Prefab)
    public enemy02: Prefab = null;
    @property
    public createEnemtTime = 1;//创建敌机时间
    @property
    public enemy1Speed = 0.5;//敌机1速度
    @property
    public enemy2Speed = 0.7;//敌机2速度

    //子弹管理节点
    @property(Node)
    public bulletRoot: Node = null;

    // prop 定义道具属性
    @property(Prefab)
    public bulletPropM: Prefab = null;
    @property(Prefab)
    public bulletPropH: Prefab = null;
    @property(Prefab)
    public bulletPropS: Prefab = null;
    @property
    public bulletPropSpeed = 0.3;//道具速度

    @property(Node)
    public gamePage: Node = null;//游戏界面
    @property(Node)
    public gameOverPage: Node = null;//游戏结束界面
    @property(Label)
    public gameOverScore: Label = null;//游戏结算分数
    @property(Label)
    public gameScore: Label = null;//游戏分数组件

    public isGameStart = false;//游戏是否开始

    private _currShootTime = 0;
    // 是否触摸屏幕
    private _isShooting = false;
    private _currCreateEnemyTime = 0//当前创建的敌机时间
    private _combinationInterval = Constant.Combination.PLAN1//组合间隔状态
    private _bulletType = Constant.BulletPropType.BULLET_M;//子弹类型
    private _score = 0;//分数

    start() {
        this._init();
    }

    update(deltaTime: number) {
        //判断游戏是否开始
        if (!this.isGameStart) {
            return;
        }
        //判断玩家是否死亡
        if (this.playerPlane.isDie) {
            this.gameOver();
            return;
        }
        // 这步加时间是为了发射子弹
        this._currShootTime += deltaTime;

        // 判断是触摸状态 并且射击时间大于我们的周期 发射子弹
        if (this._isShooting && this._currShootTime > this.shootTime) {
            /**
           * 根据吃道具类型来产生子弹
           */
            if (this._bulletType === Constant.BulletPropType.BULLET_H) {
                this.createPlayerBulletH();
            } else if (this._bulletType === Constant.BulletPropType.BULLET_S) {
                this.createPlayerBulletS();
            } else {
                this.createPlayerBulletM();
            }
            this._currShootTime = 0;
        }

        this._currCreateEnemyTime += deltaTime
        //判断组合方式
        if (this._combinationInterval == Constant.Combination.PLAN1) {
            //只创建单一的飞机 0-10秒飞机创建
            if (this._currCreateEnemyTime > this.createEnemtTime) {//普通飞机创建
                this.createEnemyPlane()
                this._currCreateEnemyTime = 0
            }

        } else if (this._combinationInterval == Constant.Combination.PLAN2) {
            // 10-20秒飞机创建
            if (this._currCreateEnemyTime > this.createEnemtTime * 0.9) {//0.9飞机组合间隔
                const randomCombination = math.randomRangeInt(1, 3)//随机1,2飞机
                if (randomCombination === Constant.Combination.PLAN2) {
                    this.createCombination1()
                } else {
                    this.createEnemyPlane()
                }

                this._currCreateEnemyTime = 0
            }
        } else {
            //20+ 飞机创建
            if (this._currCreateEnemyTime > this.createEnemtTime * 0.8) {//0.8飞机组合间隔
                const randomCombination = math.randomRangeInt(1, 4)//随机1,2,3飞机
                if (randomCombination === Constant.Combination.PLAN2) {
                    this.createCombination1()
                } else if (randomCombination === Constant.Combination.PLAN3) {
                    this.createCombination2()
                } else {
                    this.createEnemyPlane()
                }

                this._currCreateEnemyTime = 0
            }
        }
    }

    /**
    * 返回主界面逻辑,数据重置
    */
    public returnMain() {
        this._currShootTime = 0;
        this._currCreateEnemyTime = 0;
        this._combinationInterval = Constant.Combination.PLAN1;
        this._bulletType = Constant.BulletPropType.BULLET_M;
        this.playerPlane.node.setPosition(0, 0, 15);
        this._score = 0;
    }
    /**
     * 游戏开始页面数据重置
     */
    public gameStart() {
        this.isGameStart = true;
        this._changePlanMode();//开启定时器
        this._score = 0;
        this.gameScore.string = this._score.toString();
    }
    /**
     * 游戏再次开始
     */
    public gameReStart() {
        this.isGameStart = true;
        this._currShootTime = 0;
        this._currCreateEnemyTime = 0;
        this._combinationInterval = Constant.Combination.PLAN1;
        this._bulletType = Constant.BulletPropType.BULLET_M;
        this.playerPlane.node.setPosition(0, 0, 15);
        this._score = 0;
        this.gameScore.string = this._score.toString();
    }
    /**
     * 游戏结束
     */
    public gameOver() {
        this.isGameStart = false;
        this.gamePage.active = false;
        this.gameOverPage.active = true;
        this.gameOverScore.string = this._score.toString();
        this._isShooting = false;
        this.unschedule(this._modeChanged);//取消定时器
        this.playerPlane.init();//这里注意游戏结束要初始化
        this._destroyAll();
    }
    /**
     * 加分
     */
    public addScore() {
        this._score++;
        this.gameScore.string = this._score.toString();
    }

    /**
     * 创建子弹
     */
    public createPlayerBulletM() {
        // 子弹实例化
        const bullet = instantiate(this.bullet01);
        // 将子弹放在子弹管理节点下面
        bullet.setParent(this.bulletRoot);
        // 获取飞机位置
        const pos = this.playerPlane.node.position;
        // 设置子弹位置
        bullet.setPosition(pos.x, pos.y, pos.z - 7);
        // 设置子弹速度
        const bulletComp = bullet.getComponent(Bullet);
        bulletComp.show(this.bulletSpeed, false)
    }
    /**
     * H形状子弹创建
     */
    public createPlayerBulletH() {
        const pos = this.playerPlane.node.position;
        // left
        const bullet1 = instantiate(this.bullet03);
        bullet1.setParent(this.bulletRoot);
        bullet1.setPosition(pos.x - 2.5, pos.y, pos.z - 7);
        const bulletComp1 = bullet1.getComponent(Bullet);
        bulletComp1.show(this.bulletSpeed, false);

        // right
        const bullet2 = instantiate(this.bullet03);
        bullet2.setParent(this.bulletRoot);
        bullet2.setPosition(pos.x + 2.5, pos.y, pos.z - 7);
        const bulletComp2 = bullet2.getComponent(Bullet);
        bulletComp2.show(this.bulletSpeed, false);
    }
    /**
     * S型子弹创建
     */
    public createPlayerBulletS() {
        const pos = this.playerPlane.node.position;
        // middle
        const bullet = instantiate(this.bullet05);
        bullet.setParent(this.bulletRoot);
        bullet.setPosition(pos.x, pos.y, pos.z - 7);
        const bulletComp = bullet.getComponent(Bullet);
        bulletComp.show(this.bulletSpeed, false);

        // left
        const bullet1 = instantiate(this.bullet05);
        bullet1.setParent(this.bulletRoot);
        bullet1.setPosition(pos.x - 4, pos.y, pos.z - 7);
        const bulletComp1 = bullet1.getComponent(Bullet);
        bulletComp1.show(this.bulletSpeed, false, Constant.Direction.LEFT);

        // right
        const bullet2 = instantiate(this.bullet05);
        bullet2.setParent(this.bulletRoot);
        bullet2.setPosition(pos.x + 4, pos.y, pos.z - 7);
        const bulletComp2 = bullet2.getComponent(Bullet);
        bulletComp2.show(this.bulletSpeed, false, Constant.Direction.RIGHT);
    }

    /**
     * 创建敌机子弹
     * @param targetPos 敌机子弹位置
     */
    public createEnemyBullet(targetPos: Vec3) {
        // 子弹实例化
        const bullet = instantiate(this.bullet01);
        // 将子弹放在子弹管理节点下面
        bullet.setParent(this.bulletRoot);
        // 设置子弹位置
        bullet.setPosition(targetPos.x, targetPos.y, targetPos.z + 6);
        // 设置子弹速度
        const bulletComp = bullet.getComponent(Bullet);
        bulletComp.show(1, true)

        /**
         * 敌机子弹分组
         */
        const colliderComp = bullet.getComponent(BoxCollider);
        colliderComp.setGroup(Constant.CollisionType.ENEMY_BULLET);
        colliderComp.setMask(Constant.CollisionType.SELF_PLANE);//设置掩码
    }
    /**
     * 创建敌机
     *
     */
    public createEnemyPlane() {
        // 两架飞机随机选一(1,2)
        const whichEnemy = math.randomRangeInt(1, 3)
        let prefab: Prefab = null
        let speed = 0
        // 创建敌机1或2
        if (whichEnemy == Constant.EnemyType.TYPE1) {
            prefab = this.enemy01
            speed = this.enemy1Speed
        } else {
            prefab = this.enemy02
            speed = this.enemy2Speed
        }

        // 预制实例化
        const enemy = instantiate(prefab)
        console.log(enemy);

        enemy.setParent(this.node)
        const enemyComp = enemy.getComponent(EnemyPlane)
        enemyComp.show(this, speed, true)//单架敌机需要发射子弹

        // 设置飞机位置 
        const randomPos = math.randomRangeInt(-25, 26)
        enemy.setPosition(randomPos, 0, -50)
    }
    /**
     * 组合1创建 横向排列 z轴50,x轴从-20开始
     *
     */
    public createCombination1() {
        const enemyArray = new Array<Node>(5)//飞机数组
        for (let i = 0; i < enemyArray.length; i++) {
            // 敌机资源实例化
            enemyArray[i] = instantiate(this.enemy01)
            const element = enemyArray[i]
            element.parent = this.node
            element.setPosition(-20 + i * 10, 0, -50)//-20起始左位置,10飞机间隔,其实创建位置
            //设置飞机速度
            const enemyComp = element.getComponent(EnemyPlane)
            enemyComp.show(this, this.enemy1Speed, false)//组合飞机不需要发射子弹
        }
    }
    /**
     * 组合2创建 V字排列
     *
     */
    public createCombination2() {
        const enemyArray = new Array<Node>(7)//飞机数组
        // 位置数组
        const combinationPos = [
            -21, 0, -60,
            -14, 0, -55,
            -7, 0, -50,
            0, 0, -45,
            7, 0, -50,
            14, 0, -55,
            21, 0, -60
        ]

        for (let i = 0; i < enemyArray.length; i++) {
            // 敌机资源实例化
            enemyArray[i] = instantiate(this.enemy02)
            const element = enemyArray[i]
            element.parent = this.node
            const startIndex = i * 3//因为位置数组有7个 但是位置有3×7 21个  所以每架飞机位置偏移是3
            element.setPosition(combinationPos[startIndex], combinationPos[startIndex + 1], combinationPos[startIndex + 2])
            //设置飞机速度
            const enemyComp = element.getComponent(EnemyPlane)
            enemyComp.show(this, this.enemy2Speed, false)//组合飞机不需要发射子弹
        }
    }
    /**
     * 创建子弹道具
     * 随机1~3是根据然后创建相对应的道具
     */
    public createBulletProp() {
        const randomProp = math.randomRangeInt(1, 4);
        let prefab: Prefab = null;
        if (randomProp === Constant.BulletPropType.BULLET_H) {
            prefab = this.bulletPropH;
        } else if (randomProp === Constant.BulletPropType.BULLET_S) {
            prefab = this.bulletPropS;
        } else {
            prefab = this.bulletPropM;
        }
        //实例化道具
        const prop = instantiate(prefab);
        prop.setParent(this.node);
        prop.setPosition(15, 0, -50);
        const propComp = prop.getComponent(BulletProp);
        propComp.show(this, -this.bulletPropSpeed);
    }

    /**
     * 触摸状态设置
     * @param value  true/false
     */
    public isShooting(value: boolean) {
        this._isShooting = value;
    }
    /**
     * 改变子弹类型
     * @param type  类型
     */
    public changeBulletType(type: number) {
        this._bulletType = type;
    }
    /**
     * 默认发射子弹
     */
    private _init() {
        this._currShootTime = this.shootTime;
        this.playerPlane.init();
        // this._changePlanMode();
    }

    /**
     * 设计定时器 
     */
    private _changePlanMode() {
        /**
         * 每10秒改变一次状态,,根据状态就能决定采用什么组合
         */
        this.schedule(this._modeChanged, 10, macro.REPEAT_FOREVER);//组件自带定时器(回调函数,间隔时间,重复次数,延迟时间)
    }

    /**
     * 改变组合状态
     */
    private _modeChanged() {
        this._combinationInterval++
        this.createBulletProp();//创建子弹道具
    }

    /**
     * 销毁所有的飞机与子弹
     */
    private _destroyAll() {
        let children = this.node.children;
        let length = children.length;
        let i = 0;
        for (i = length - 1; i >= 0; i--) {
            const child = children[i];
            child.destroy();
        }

        children = this.bulletRoot.children;
        length = children.length;
        for (i = length - 1; i >= 0; i--) {
            const child = children[i];
            child.destroy();
        }
    }
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值