写过一篇 发表于 2024-11-27 16:14:38

cocos creator 3.8 打飞机Demo 9

简单的demo实现,没优化以及加上音频文件,没有开始结束暂停等逻辑。
首先2D状态下,担当的素材
https://i-blog.csdnimg.cn/direct/d79044aebb5142efa774fc08ea124382.png
1、首先实现背景的移动
https://i-blog.csdnimg.cn/direct/6deb554964fc4eeb98130dcfaffe42b7.png
根本逻辑如下 关于fixUpdate,可以写一个基类,然后继续它
    //固定帧计时
    private _now_time = 0;
    //固定帧时间
    private frameTime = 0.016;
   
    start() {
      this.gameBg1.setPosition(0, 0, 0);
      this.gameBg2.setPosition(0, this._maxRange, 0);
    }

    update(deltaTime: number) {
      this._now_time += deltaTime;
      while (this._now_time >= this.frameTime) {
            //迭代逻辑
            this.childUpdate(this.frameTime);
            this._now_time -= this.frameTime;
      }
    }

    childUpdate(deltaTime: number) {
      this.gameBg1.setPosition(0, this.gameBg1.position.y - this._moveSpeed * deltaTime, 0);
      this.gameBg2.setPosition(0, this.gameBg2.position.y - this._moveSpeed * deltaTime, 0);
      if (this.gameBg1.position.y <= -this._maxRange) {
            this.gameBg1.setPosition(0, this.gameBg2.position.y + this._maxRange, 0);
      } else if (this.gameBg2.position.y <= -this._maxRange) {
            this.gameBg2.setPosition(0, this.gameBg1.position.z + this._maxRange, 0);
      }
    } 2、创建角色小飞机,来一个脚本控制小飞机的移动
https://i-blog.csdnimg.cn/direct/48a7a0327e084964ba37352b6e0b01fb.png
3.x上
 Input该输入类管理全部的输入事件,包括:触摸、鼠标、加速计、游戏手柄、6DOF手柄、头戴显示器 和 键盘。
所以Node与Input的这连个监听事件,都可以利用
//玩家飞机

    @property(Node)

    userPlane: Node = null;



    protected onLoad(): void {

        this.userPlane.on(Node.EventType.TOUCH_START, this.onTouchStart, this);

        this.userPlane.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this);

        this.userPlane.on(Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);

        this.userPlane.on(Node.EventType.TOUCH_END, this.onTouchEnd, this);

        // input.on(Input.EventType.TOUCH_START, this.onTouchEventStart, this);

        // input.on(Input.EventType.TOUCH_MOVE, this.onTouchEventMove, this);

        // input.on(Input.EventType.TOUCH_CANCEL, this.onTouchEventCanel, this);

        // input.on(Input.EventType.TOUCH_END, this.onTouchEventEnd, this);

        this.userPlane.setPosition(v3(0, -300, 0));

    }

onTouchMove(event: EventTouch) {

        // 获取触点距离上一次事件移动的距离对象,对象包含 x 和 y 属性。

        const delta = event.getDelta();

        const position = this.userPlane.position;

        this.userPlane.setPosition(v3(position.x + delta.x, position.y + delta.y, position.z));

    }
[*]创建敌方小飞机,挂上脚本,设置预制体
https://i-blog.csdnimg.cn/direct/2d300696b16c4585995dc92dccff8516.png
//小飞机的移动速度

    _moveSpeed: number = 10;

    //背景移动的上线距离

    _maxRange: number = 740;//大于1/2的界面高度



    update(deltaTime: number) {

        const postion = this.node.position;

        //移动的距离

        const moveLength = postion.y - this._moveSpeed;

        this.node.setPosition(postion.x, moveLength, postion.z);

        if (moveLength <= -this._maxRange) {

            this.node.destroy();

        }

    }
[*]创建己方子弹,挂上脚本,设置预制体
//自方的移动速度

    _moveSpeed: number = 15;

    //子弹移动的上线距离

    _maxRange: number = 1344;



    update(deltaTime: number) {

        let position = this.node.position;

        this.node.setPosition(position.x, position.y + this._moveSpeed, position.z);

        position = this.node.position;

        if (position.y > this._maxRange) {

            this.node.destroy();

        }

    }
[*]创建敌方子弹,挂上脚本,设置预制体
//敌方的移动速度

    _moveSpeed: number = 15;

    //子弹移动的上线距离

    _maxRange: number = 1344/2;



    update(deltaTime: number) {

        let position = this.node.position;

        this.node.setPosition(position.x, position.y - this._moveSpeed, position.z);

        position = this.node.position;

        if (position.y < -this._maxRange) {

            this.node.destroy();

        }

    }
[*]创建一个空节点,放置生成的子弹的容器
https://i-blog.csdnimg.cn/direct/ac4cf77d36b34affb1782af840d543b6.png

[*]由于敌机上也要生成子弹,而且还是预制体,这个容器节点就没法挂载了,那就来一个控制类。GameCtrl或者GameManager名字本身好记就弄那个名字呗。
在这个类上写方法创建子弹,并引入,这样就会袒露个问题,引入的GameCtrl为空或者null,
两种方法
1>在GameCtrl 的onLoad中让它赋值this,window[“GameCtrl”] = this,然后在其他的脚本中调用它下面的方法。
2>找到这里节点上挂载的这个脚本,用一个方法在onLoad中,不一定是onLoad,总之就是提前传入:让这个类指向this,让脚本能够找到这个类。
createPlayer() {

        // const playerBullet: Node = instantiate(this.playerBullet);

        // const position = rootNode.position;

        // playerBullet.setParent(rootNode);

        // playerBullet.setPosition(position.x, position.y, position.z);

        let playerComp = this.userPlane.getComponent(PlayerCtrl);

        playerComp.showBullet(this);

    }

    showBullet(gameCtrl: GameCtrl, needShoot: boolean = false) {

        this.gameCtrl = gameCtrl;

        this.needShoot = needShoot;

    }
[*]该分组了,必要的地方加上碰撞器与刚体,这里我勾选了Is Trigger,没有效2D的Collider,创建的是3D项目,就这样吧。
https://i-blog.csdnimg.cn/direct/af7e94c1e45a470fabc776ae1eb31e75.png
https://i-blog.csdnimg.cn/direct/a55598baac8c496ba02f2cee387a3f1d.png碰撞判定
    protected onEnable(): void {

        const collider = this.node.getComponent(Collider);

        collider.on("onTriggerEnter", this.onTriggerEnter, this);

    }



    protected onDisable(): void {

        const collider = this.node.getComponent(Collider);

        collider.off("onTriggerEnter", this.onTriggerEnter, this);

}



    onTriggerEnter(event: ITriggerEvent) {

        const collisionGroup = event.otherCollider.getGroup();

        //己方小飞机

        if (collisionGroup == 1 << 1) {

            this.node.destroy();

        }

    }
[*]简单的一个demo写的差不多了,再来一个节点池NodePool
@ccclass('NodePoolManger')

export class NodePoolManger extends Component {

    //没有继承Component 需要静态的

    //在实际应用中需要实例化,走单例模式

    static _instance: NodePoolManger;

    static instance() {

        //没有就new一个,有就直接返回这个实例

        if (!this._instance) {

            this._instance = new NodePoolManger();

        }

        return this._instance;

    }

} 定义两个数据结构的接口
//定义一个数据结构map集合 字典

interface IDicPool {

    : NodePool;

}

//数据结构接口 key :value

interface IDicPrefab {

    : Prefab;

} 在定义两个对象
//两个容器对象 节点与预制
_dicPool: IDicPool = {};
//定义这个对象,根据名字来取对应的prefab
_dicPrefab: IDicPrefab = {}; 然后一个 get 一个put的实现

[*]替换
  createPlayerbullte(rootNode: any) {

        const playerBullet: Node = NodePoolManger.instance().getNode(this.playerBullet, this.bulletRoot);

        // const playerBullet: Node = instantiate(this.playerBullet);

        // playerBullet.setParent(this.bulletRoot);

        playerBullet.setPosition(rootNode.position.x, rootNode.position.y + 80, rootNode.position.z);

}



onTriggerEnter(event: ITriggerEvent) {

        const collisionGroup = event.otherCollider.getGroup();

        //己方小飞机

        if (collisionGroup == 1 << 1) {

            NodePoolManger.instance().putNode(this.node);

            // this.node.destroy();

        }

    } demo一会儿上传,新手可以看看
    //获取节点 //替换游戏中的instantiate
    getNode(prefab: Prefab, parent: Node) {
      // let name = prefab.name;
      let name = prefab.data.name;
      // console.log("get pool " + name);
      let node: Node = null;
      //先判断这种池子存在否
      this._dicPrefab = prefab;
      let pool = this._dicPool;
      //检查有没有这个池子
      if (pool) {
            //检查池子中有没有这个预制体
            if (pool.size() > 0) {
                node = pool.get();
            } else {
                //没有就实例化一个
                node = instantiate(prefab);
            }
      } else {
            //没有这种池子,就新建一个
            this._dicPool = new NodePool();
            node = instantiate(prefab);
      }
      node.parent = parent;
      //激活这个节点
      node.active = true;
      return node;
    }
    //缓存节点 //替换游戏中的node.destroy
    putNode(node: Node) {
      let name = node.name;
      // console.log("put pool " + name);
      //节点被回收,不能再作为场景里面的对象存在与场景中
      node.parent = null;
      //池子中有这种类型的
      if (this._dicPool) {
            this._dicPool.put(node);
      } else {
            //没有就创建再放进去
            this._dicPool = new NodePool();
            this._dicPool.put(node);
      }
    }

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: cocos creator 3.8 打飞机Demo 9