cocos控制玩家飞机发射子弹的小逻辑,以及开发思维

cocos游戏开发过程中的思考

一个游戏是由多个场景组成的,一个场景是由多个节点组成的,一个节点是由多个组件组成的。

确实是这么个道理,开始画面是一个场景,当用户点击了开始之后,切换到另外一个游戏中的场景。每个场景中都包含很多节点:飞机 / 子弹 / 背景等,每个节点又可以包含很多个字节点,就像div下面可以套很多别的div / span / li等节点。而每个节点上又可以存在多个组件:例如动画组件 / 碰撞器 / 刚体组件等。

但是要从一个前端思维中转换过来到游戏开发思维中,还是需要时间的。

发射子弹的思考

子弹是一直连续不断的产生的,所以需要动态生成子弹节点,并当子弹位置超过屏幕位置后,销毁子弹这个节点,所以需要先将子弹存储为一个预制体。在存储为预制体之前,需要先给子弹绑定一个ts脚本,用于控制子弹自动移动。而且子弹出生的位置在哪里呢?在飞机的机头位置处,所以还要先获取飞机机头的位置,然后初始化子弹的开始位置,随后就是子弹自己的脚本控制子弹移动了

子弹自动移动的脚本:

javascript 复制代码
import { _decorator, Component, Node } from 'cc'
const { ccclass, property } = _decorator

@ccclass('bullet')
export class bullet extends Component {
    // 子弹速度
    @property(Number)
    public speed: number = 100

    start() {}

    update(deltaTime: number) {
        // 子弹向上移动
        this.node.setPosition(
            this.node.position.x,
            this.node.position.y + this.speed * deltaTime,
            this.node.position.z
        )

        // 子弹超出屏幕范围后销毁
        if (this.node.position.y > 364) {
            this.node.destroy()
        }
    }
}

在玩家飞机的逻辑中,控制子弹的发射,并获取子弹父节点位置:

javascript 复制代码
import {
    _decorator,
    Component,
    EventKeyboard,
    EventTouch,
    Input,
    input,
    instantiate,
    KeyCode,
    Node,
    Prefab,
    Vec3,
} from 'cc'
const { ccclass, property } = _decorator

@ccclass('player')
export class player extends Component {
    // 子弹发射点(子弹的父节点)
    @property(Node)
    public bulletSpawnPoint: Node = null

    // 子弹预制体
    @property(Prefab)
    public bulletPrefab: Prefab = null

    // 子弹发射间隔
    @property(Number)
    public bulletInterval: number = 0.5

    // 子弹发射间隔计时器
    private bulletIntervalTimer: number = 0

    start() {
        input.on(Input.EventType.TOUCH_START, this.onTouchStart, this)
        input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this)
        input.on(Input.EventType.TOUCH_END, this.onTouchEnd, this)
        input.on(Input.EventType.TOUCH_CANCEL, this.onTouchCancel, this)
        // 按下空格键发射子弹
        input.on(Input.EventType.KEY_DOWN, this.onKeyDown, this)
        // 按下W键向上移动
        input.on(Input.EventType.KEY_PRESSING, this.onKeyDown, this)
        // 按下S键向下移动
        input.on(Input.EventType.KEY_PRESSING, this.onKeyDown, this)
        // 按下A键向左移动
        input.on(Input.EventType.KEY_PRESSING, this.onKeyDown, this)
        // 按下D键向右移动
        input.on(Input.EventType.KEY_PRESSING, this.onKeyDown, this)
    }

    onDestroy() {
        input.off(Input.EventType.TOUCH_START, this.onTouchStart, this)
        input.off(Input.EventType.TOUCH_MOVE, this.onTouchMove, this)
        input.off(Input.EventType.TOUCH_END, this.onTouchEnd, this)
        input.off(Input.EventType.TOUCH_CANCEL, this.onTouchCancel, this)
    }

    onTouchStart(event: EventTouch) {
        console.log('onTouchStart', event)
    }

    onTouchMove(event: EventTouch) {
        console.log('onTouchMove', event)
        const playerPositon = this.node.position
        // 限制玩家移动范围x (-230/230) y(-364/364)
        const x = Math.max(
            -230,
            Math.min(230, playerPositon.x + event.getDeltaX())
        )
        const y = Math.max(
            -364,
            Math.min(364, playerPositon.y + event.getDeltaY())
        )
        this.node.setPosition(x, y, 0)
    }

    onTouchEnd(event: EventTouch) {
        console.log('onTouchEnd', event)
    }

    onTouchCancel(event: EventTouch) {
        console.log('onTouchCancel', event)
    }

    onKeyDown(event: EventKeyboard) {
        console.log('onKeyDown', event)
        if (event.keyCode === KeyCode.SPACE) {
            this.fireBullet()
        }
        if (event.keyCode === KeyCode.KEY_W) {
            this.node.setPosition(
                this.node.position.x,
                this.node.position.y + 10,
                0
            )
        }
        if (event.keyCode === KeyCode.KEY_S) {
            this.node.setPosition(
                this.node.position.x,
                this.node.position.y - 10,
                0
            )
        }
        if (event.keyCode === KeyCode.KEY_A) {
            this.node.setPosition(
                this.node.position.x - 10,
                this.node.position.y,
                0
            )
        }
        if (event.keyCode === KeyCode.KEY_D) {
            this.node.setPosition(
                this.node.position.x + 10,
                this.node.position.y,
                0
            )
        }
    }

    // 发射子弹
    private fireBullet() {
        const bullet = instantiate(this.bulletPrefab)
        bullet.setParent(this.bulletSpawnPoint)
        bullet.setPosition(
            new Vec3(this.node.position.x, this.node.position.y + 10, 0)
        )
    }

    update(deltaTime: number) {}
}

当然这个还有优化的地方,比如当按下上下左右按键的时候,移动并不是很灵敏,需要优化,还有子弹不会自动发射以及发射间隔也需要优化,等下一篇文章讲解

相关推荐
麦麦大数据7 分钟前
D026 vue3+django 论文知识图谱推荐可视化系统 | vue3+vite前端|neo4j 图数据库
前端·django·vue3·知识图谱·推荐算法·论文文献·科研图谱
小肚肚肚肚肚哦13 分钟前
伪元素与普通元素的层级关系问题浅析
前端·css
梦想CAD控件1 小时前
网页CAD中组(Group)功能的二次开发
前端·javascript·github
讨厌吃蛋黄酥1 小时前
🔥 JavaScript异步之谜:单线程如何实现“同时”做多件事?99%的人都理解错了!
前端·javascript·面试
华仔啊1 小时前
别再纠结Pinia和Vuex了!一篇文章彻底搞懂区别与选择
前端·vue.js
徐同保1 小时前
Redux和@reduxjs/toolkit同时在Next.js项目中使用
开发语言·前端·javascript
~无忧花开~2 小时前
CSS学习笔记(二):CSS动画核心属性全解析
开发语言·前端·css·笔记·学习·css3·动画
渣哥2 小时前
Spring Boot 本质揭秘:约定优于配置 + 自动装配
javascript·后端·面试
颜酱2 小时前
了解 pnpm 的优势,然后将已有项目的 yarn 换成 pnpm
前端·javascript·前端工程化
海在掘金611272 小时前
从"鬼知道这对象有啥"到"一目了然" - TS接口的实战魔力
前端