CocosCreator进阶实战第五部分:工具类与子弹射击


title: CocosCreator进阶实战第五部分:工具类与子弹射击
date: 2019-12-28 12:00:00

摘要

最终部分:工具类、子弹射击与 Boss 随机移动。

正文

版本说明

使用 CocosCreator 的 2.1.3 版本开发。 建议先下载完整项目工程,搭配文章“食用”!源码链接在文章最下方。

工具类

游戏中一些常用的方法我们一般都会封装起来,起名为 Util。这里我简单的封装了几个方法,比如打印、随机小数、随机角度并转向量。

export class Util {
    
    /** 是否开发模式 */
    static isDebug: boolean = true

    /** console.log封装,isDebug置为false跳过打印 */
    static log (...args: any[]): void {
        if (!this.isDebug) { return }
        for (let item of args) {
            console.log(item)
        }
    }
}

随机范围内小数

/**
 * 在 min 与 max 之间随机小数
 * @param {number} min 
 * @param {number} max 
 */
static randomNumber (min: number, max: number): number {
    return min + Math.random() * (max - min)
}

子弹的移动是靠方向向量,所以我们需要转化,通过 sin 与 cos

/**
 * 随机角度转化向量
 * @param minAngle 最小角度
 * @param maxAngle 最大角度
 */
static randomDir (minAngle: number, maxAngle: number): cc.Vec2 {
    let angle = this.randomNumber(minAngle, maxAngle)
    let rad = cc.misc.degreesToRadians(angle)
    return cc.v2(Math.cos(rad), Math.sin(rad))
}
子弹射击

通过一系列的准备,子弹的创建和射击变得很是简单

// 创建 R 型子弹,角度在 0-360 随机,速度指定为 800
this.bulletFactory.createBullet(BulletType.R, Util.randomDir(0, 360),  800)

子弹创建完毕后,我们设置它从 Boss 那里射出即可(this.enemy 就是 Boss 节点)

let bullet = this.bulletFactory.createBullet(BulletType.R, Util.randomDir(0, 360),  800)
bullet.setPosition(this.enemy.x, this.enemy.y)

需要注意的是第二种月牙子弹,也就是 M 型子弹,它是旋转射击出来的,我么需要为其指定一个角度变量,每隔一定时间自增 30 度,需要注意的是,Cocos 中的角度按照 x 轴正方向算的 0 度,我们图片向上,差 90 度,加上即可

this.typeMBulletAngle += 30
if (this.typeMBulletAngle >= 360) {
    this.typeMBulletAngle = 0
}
let rad = cc.misc.degreesToRadians(this.typeMBulletAngle)
let bullet: cc.Node = this.bulletFactory.createBullet(BulletType.M, cc.v2(Math.cos(rad), Math.sin(rad)), 650)
bullet.angle = this.typeMBulletAngle + 90
bullet.setPosition(this.enemy.x, this.enemy.y)
射击工厂

这里封装的射击函数 shoot() 采用了 if-else 分支判断,switch 也可

/** 简单射击工厂 */
shoot (type: BulletType): void {
    if (type === BulletType.R) {
        // ......
    } else if (type === BulletType.M) {
        this.typeMBulletAngle += 30
        if (this.typeMBulletAngle >= 360) {
            this.typeMBulletAngle = 0
        }
        // ......
    } else if (type === BulletType.F) {
        // 天女散花型,一次 12 个
        for (let i = 0; i <= 360 ; i += 30) {
            // ......
        }
    } else if (type === BulletType.B) {
        // duang~ 型
    }
}

简单的时间控制,注意用匿名函数写法,否则会被覆盖

let deltaTime: number = 5
let startTime: number = 4
// 匿名函数不会被同计时器覆盖
this.schedule(() => this.shoot(BulletType.R), 0.02, cc.macro.REPEAT_FOREVER, startTime)
this.schedule(() => this.shoot(BulletType.M), 0.06, cc.macro.REPEAT_FOREVER, startTime + 1 * deltaTime)
this.schedule(() => this.shoot(BulletType.F), 0.4, cc.macro.REPEAT_FOREVER, startTime + 2 * deltaTime)
this.schedule(() => this.shoot(BulletType.R), 0.02, cc.macro.REPEAT_FOREVER, startTime + 3 * deltaTime)
this.schedule(() => this.shoot(BulletType.B), 0.5, cc.macro.REPEAT_FOREVER, startTime + 4 * deltaTime)
this.schedule(() => this.shoot(BulletType.M), 0.06, cc.macro.REPEAT_FOREVER, startTime + 5 * deltaTime)
this.schedule(() => this.shoot(BulletType.R), 0.02, cc.macro.REPEAT_FOREVER, startTime + 6 * deltaTime)
this.schedule(() => this.shoot(BulletType.F), 0.4, cc.macro.REPEAT_FOREVER, startTime + 7 * deltaTime)
随机移动

我们的小飞机是在随机的移动的,怎么实现的呢?首先,小飞机是这样移动的:

update (dt: number): void {
    if (this.dir.x !== 0) {
        this.node.x += this.speed * this.dir.x * dt
    }
    if (this.dir.y !== 0) {
        this.node.y += this.speed * this.dir.y * dt
    }
}

显然,我们改变 this.dir 即可!封装一个方法

randomDir (): void {
    let dir = Util.randomDir(0, 360)
    this.dir.x = dir.x
    this.dir.y = dir.y
}

设置定时器

start (): void {
    // 4 秒后开始运动,每 5 秒随机新方向
    this.schedule(this.randomDir, 5, cc.macro.REPEAT_FOREVER, 4)
}

这样就实现了小飞机的随机移动,最后我们限定小飞机的移动范围,如图

对于这个项目,小飞机的 x 应该在 -300 到 300 之间,小飞机的 y 应该在 400 到 580 之间,所以 update 里面应该这样写

update (dt: number): void {
    if (this.dir.x !== 0) {
        this.node.x += this.speed * this.dir.x * dt
    }
    if (this.dir.y !== 0) {
        this.node.y += this.speed * this.dir.y * dt
    }
    // 边界回弹
    if (this.node.x < -300) this.dir.x = this.dir.x > 0 ? this.dir.x : -this.dir.x
    if (this.node.x > 300) this.dir.x = this.dir.x < 0 ? this.dir.x : -this.dir.x
    if (this.node.y > 580) this.dir.y = this.dir.y < 0 ? this.dir.y : -this.dir.y
    if (this.node.y < 400) this.dir.y = this.dir.y > 0 ? this.dir.y : -this.dir.y
}

结语

Alive 项目就此结束!代码本身没什么难度,主要是帮助大家更好的理解面向对象,以及设计模式的简单使用,希望大家有所收获!

O(∩_∩)O~~

源码地址

https://github.com/KuoKuo666/Alive

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

KUOKUO众享

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

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

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

打赏作者

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

抵扣说明:

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

余额充值