微信飞机大战小游戏编写分享教程(初篇)如何制作?

2026-05-27 12:201阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计3860个文字,预计阅读时间需要16分钟。

微信飞机大战小游戏编写分享教程(初篇)如何制作?

1. 下载游戏引擎 + 我选择的游戏引擎是 Cocos Creator,官网地址:链接。您可直接点击下载免费获得这款引擎软件,建议下载最新稳定版本。本文撰写时,适合制作 2D 小游戏的最新版本。

1. 下载游戏引擎

游戏引擎我选择的是 cocos creator,官网地址:链接

您可以直接点击下载免费获得这款引擎软件,建议下载最新的稳定版本,写这篇文章的时候,适合写 2D 小游戏的最新版本貌似是:V2.4.8

一般我们会先下载一个 DASHBOARD,可以理解成一个 cocos 的盒子,用于放各种游戏工具。

然后从 DASHBOARD 中下载相应版本的 cocos creator。

2. 创建游戏项目

安装完毕后,我们进入大盘界面:

点击 new 创建一个新的 empty 游戏工程:

看到上面这个界面后,就意味着咱们的开发环境已经搭建好了,可以开始开发小游戏咯!

3. 创建游戏画布

首先我们把游戏资源导入到我们的游戏工程中,游戏资源地址:

然后查看背景图片的大小,资源里的背景图大小是:640 x 1136

于是我们设置画布的大小为 640 x 1136

4. 设置游戏背景

为了减少加载图片所带来的性能损耗,我们把所有的资源合到一张图片中(cocos 能够自动识别这些图片),合图工具用的是:TexturePacker,官方下载地址链接

简单的使用方法如下:

  1. 打开图片目录,把所有的图片拖拽到 TexurePacker 中

  1. 保存

制作完 plist 文件后,我们新建一个叫 plist 的文件夹存放 plist 文件,后续我们使用图片都通过 plist 获取。

然后我们把背景图片 bg 拖拽到节点树上:

为了制作一个轮播的背景,我们需要两张背景图,假设为 A 和 B(想让背景图片动起来,我们必须保证画布中永远有背景)。详细解释参见:链接

首先我们创建一个控制游戏逻辑的 TypeScript 脚本:

然后把脚本文件关联到画布中:

关联到画布后,咱们编写脚本,控制背景图片轮播,首先需要定义两个节点(我们只使用背景图片的坐标属性,因此定义为节点类型就足够了):

@property(cc.Node) bg1: cc.Node = null; @property(cc.Node) bg2: cc.Node = null;

定义完成后记得到画布中进行绑定:

绑定后我们编写轮播的代码:

// 在游戏加载的时候定义背景图片的位置 protected onLoad() { this.bg1.y = 0 this.bg2.y = this.bg1.y + this.bg2.height } update (dt) { // 背景图片的移动速度 this.bg1.y -= 10; this.bg2.y -= 10; // 背景图片轮播逻辑(没明白可以看视频哦) if(this.bg1.y <= -this.bg1.height){ // 当一张背景移动到屏幕外面后,立马补到另一张背景图片的后面 this.bg1.y = this.bg2.y + this.bg1.height } if(this.bg2.y <= -this.bg2.height){ this.bg2.y = this.bg1.y + this.bg2.height } }

编写完成后,咱们就有了轮播的背景图。

5. 添加开始游戏标语

首先我们把游戏标语添加到节点树中,选择一个合适的位置:

为了提示玩家点击屏幕开始游戏,我们在这个节点下添加一个 label 节点用于显示文字:

为了模仿微信飞机大战的展示效果,我们给这行 点击屏幕开始游戏 的文字添加一个上下晃动的动画效果,这里用到了 cocos 的 animation 功能:

  1. 首先我们创建一个动画资源
  2. 将动画资源绑定到 点击屏幕开始游戏 所在的节点上
  3. 然后设置关键帧,给每个关键帧设定恰当的角度,比如说第一帧的角度为 0,第二帧的角度为 15,第三帧的角度为 0,第四帧为 -15,第五帧为 0。

连起来播放后大概就成了这样:

6. 编写游戏准备、游戏中、游戏暂停三个状态

虽然我们编写好了一个轮播的背景,有了动态的效果,但我们希望在游戏刚开始的时候背景是不动的,等玩家进入游戏后背景再动起来,让小飞机有飞翔的效果。

首先我们定义一个判断背景图片是否在动的变量

isBgMove = false

然后把移动背景的代码封装到一个方法里,在 update 方法中通过判断 isBgMove 变量控制背景是否移动:

update (dt) { if(this.isBgMove){ this.moveBg() } } moveBg(){ // 让背景图片动起来 this.bg1.y -= 10; this.bg2.y -= 10; if(this.bg1.y <= -this.bg1.height){ this.bg1.y = this.bg2.y + this.bg1.height } if(this.bg2.y <= -this.bg2.height){ this.bg2.y = this.bg1.y + this.bg2.height } }

有了控制背景轮播的开关后,我们编写游戏准备、游戏中、游戏暂停三个状态。

首先我们把上面定义的 shoot_copyright 节点改个名字,改成游戏准备节点 status_ready;

然后依次创建两个空节点 status_playing 和 status_pause:

然后在游戏开始页面创建一个暂停按钮:

为暂停按钮创建一个点击事件,我们编写一个通用处理点击事件的方法,通过控制台进行调试:

clickButton(sender, str){ if(str == "pause"){ console.log("点击了暂停按钮") } }

然后编写暂停页面:

  1. 首先添加一个暂停的背景图,设置透明度遮盖原有的游戏背景
  2. 添加三个按钮,设置好按钮的样式以及显示内容
  3. 为暂停背景设置一个 BlockInputEvents,屏蔽调下层节点

然后编写这三个页面的显隐关系,大概的逻辑是:

  1. 玩家进入游戏后显示一个静态的背景,当点击屏幕后隐藏调游戏准备界面,进入游戏开始界面
  2. 玩家可以在游戏界面点击暂停按钮,点击暂停按钮后由游戏开始界面进入游戏暂停界面
  3. 在游戏暂停界面有三个按钮,点击继续游戏会回到游戏开始界面,点击重新开始也会回到游戏开始界面,点击回到主页会回到游戏准备界面

以上的逻辑可以通过统一的按键点击方法进行处理:

clickButton(sender, str){ if(str == "pause"){ // 点击暂停后显示暂停页面 this.pause.active = true }else if(str == "continue"){ // 点击继续游戏后隐藏暂停页面 this.pause.active = false }else if(str == "restart"){ // 点击重新开始后隐藏暂停页面 this.pause.active = false }else if(str == "backHome"){ // 点击回到主页隐藏暂停界面,停止游戏,停止背景移动 this.pause.active = false this.playing.active = false this.isBgMove = false this.ready.active = true } }

实现效果大概是这样的:

7. 编写游戏主角我方飞机

编写好了游戏场景切换功能后,我们开始编写我们的游戏主角。

首先添加一个节点,为它设置一张图片(Sprite 属性),然后制作一个小动画:

然后编写飞机跟随手指(鼠标)移动的逻辑,简单来说就是要注册一个触摸移动的监听事件:

setTouch() { // .... this.node.on("touchmove", (event) => { // 获取飞机的位置 let hero_pos = this.hero.getPosition() // 获取手指(鼠标)距离上一次事件移动相对于左下角的距离对象 let move_pos = event.getDelta() // 飞机的位置加上移动的相对位置得到飞机的最新位置 this.hero.setPosition(cc.v2(hero_pos.x + move_pos.x, hero_pos.y + move_pos.y)) }, this); //... }

大概的效果是酱紫的:

8. 让飞机可以发射子弹

由于子弹是会重复利用的资源,我们这里采用预制体资源,首先我们在节点树中创建一个子弹节点,然后给子弹配一个脚本:

在每一帧中改变子弹的 y 值,让子弹有发射的效果。

update(dt) { this.node.y += 10 }

配置好脚本后,我们把子弹节点拖拽到资源管理器中,使其变成一个预制体,然后编写主逻辑脚本,先定义一个预制体:

// 子弹 @property(cc.Prefab) pre_bullet: cc.Prefab

然后尝试在每次鼠标点击结束(触摸手指离开屏幕)的时候生成一颗子弹:

setTouch() { this.node.on("touchend", (event) => { //...... // 生成一颗子弹 let bullet = cc.instantiate(this.pre_bullet) // 把子弹挂在到节点树上 bullet.parent = this.node // 获取飞机主角的位置 let pos = this.hero.getPosition() // 设置子弹的初始位置为飞机头 bullet.setPosition(cc.v2(pos.x, pos.y + this.hero.height / 2)) }, this); }

这样一来飞机就可以发射子弹了:

9. 对象池与单例

现在虽然能不停地发射子弹了,但是一直创建子弹实例不进行删除可不行,如果游戏时间久了游戏会越来越卡。

我们使用 cocos 提供的对象池对子弹进行缓存,先编写一个生成子弹的方法:

createBullet() { // 创建子弹的方法 let bullet = null // 生成子弹的时候先到对象池中取 if (this.bulletPool.size() > 0) { // 如果对象池中有子弹对象则直接使用 bullet = this.bulletPool.get() } else { // 如果对象池没有子弹了,就创建一颗新的子弹 bullet = cc.instantiate(this.pre_bullet) } // 获取子弹后挂在跟节点下 bullet.parent = this.node // 获取飞机的位置 let pos = this.hero.getPosition() // 设置子弹的初始位置 bullet.setPosition(cc.v2(pos.x, pos.y + this.hero.height / 2)) }

然后编写子弹消亡的逻辑,目前一共有三个场景可以回收子弹:

  1. 重新开始游戏
  2. 回到主页
  3. 子弹超出画布范围

// 回收单颗子弹 bulletKilled(bullet) { // 回收子弹的方法 bullet.setPosition(cc.v2(0, 0)) this.bulletPool.put(bullet) } // 回收全部子弹 removeBullets() { let children = this.node.children for (let i = children.length - 1; i >= 0; i--) { let bullet = children[i].getComponent("bullet") if (bullet) { this.bulletKilled(children[i]) } } }

阿菌在开发的时候比较困扰的问题是,我给子弹单独创建一个脚本后,怎么在子弹脚本中引用主逻辑类中的方法呢?

通过在 cocos 论坛搜索,大佬给出的答案是使用单例,单例的简单使用模版如下:

@ccclass export default class Singleton extends cc.Component { // 单例 public static instance: Singleton = null onLoad() { // 初始化单例 if (Singleton.instance == null) { Singleton.instance = this } else { this.destroy() return }

通过上面的代码,把主逻辑对象导出,在子弹脚本中可以这么使用:

微信飞机大战小游戏编写分享教程(初篇)如何制作?

const {ccclass, property} = cc._decorator; // 导入主逻辑类 import Singleton from "./main"; @ccclass export default class NewClass extends cc.Component { update(dt) { this.node.y += 15 if(this.node.y > 590){ // 使用主逻辑单例对象 Singleton.instance.bulletKilled(this.node) } } } 10. 添加敌机

添加敌机的逻辑和添加子弹的逻辑相似:

  1. 在节点树中创建一个敌机节点
  2. 创建敌机的脚本,并关联给敌机节点
  3. 把敌机节点制作成 PerFab
  4. 在主逻辑中编写敌机对象池、敌机创建、敌机销毁的方法

createEnemy1() { // 创建敌机1的方法 let enemy1 = null if (this.enemy1Pool.size() > 0) { enemy1 = this.enemy1Pool.get() } else { enemy1 = cc.instantiate(this.pre_enemy_1) } enemy1.parent = this.node enemy1.setPosition(cc.v2(0, 590)) } enemy1Killed(enemy1){ this.enemy1Pool.put(enemy1) } removeEnemy1s() { let children = this.node.children for (let i = children.length - 1; i >= 0; i--) { let enemy1 = children[i].getComponent("enemy1") if (enemy1) { this.bulletKilled(children[i]) } } }

在敌机脚本中设置敌机移动后,得到的效果大概是这样子的:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jujgCh49-1647963420444)(s21.aconvert.com/convert/p3r68-cdx67/6d7lo-6fcx8.gif)]

11. 子弹与敌机碰撞

有了敌机之后,我们让我方飞机发射的子弹可以击中敌机。

首先我们给敌机和子弹添加碰撞组件(记得给子弹和敌机添加分组):

然后到项目设置中设置敌机和子弹可以碰撞:

接下来编辑敌机死亡的帧动画(还要编辑一个敌机正常状态的动画):

然后在主逻辑中开启碰撞:

// 开启碰撞检测系统,未开启时无法检测 cc.director.getCollisionManager().enabled = true;

开启碰撞后,给子弹编写处理碰撞的方法:

onCollisionEnter(other, self) { if (self.tag == 1) { // 普通子弹命中了普通敌机 Singleton.instance.bulletKilled(this.node) } if (other.tag == 2){ // 击中的是普通敌机 let enemy = other.getComponent("enemy_1") if(enemy && !enemy.isDie){ enemy.hit() } } }

给敌机添加被击中后的处理逻辑:

hit(){ // 击中后状态设置为死亡 this.isDie = true // 播放帧动画 let anim = this.getComponent(cc.Animation) anim.play('enemy_1_die') } over(){ // 帧动画播放完后把敌机放回对象池中,等待下一次出现 Singleton.instance.enemy1Killed(this.node) }

记得给敌机的出生坐标设置一个随机值

//... enemy1.parent = this.node let randomX = 295 - 590 * Math.random() enemy1.setPosition(cc.v2(randomX, 590)) //...

得到的效果是这样的:

好了,上集就先到这,努力更新下集中......

游戏资源地址:
链接:pan.baidu.com/s/1rL82cUYMnxgZQ3xkff5RGw
提取码:r10d

学习参考:链接

本文共计3860个文字,预计阅读时间需要16分钟。

微信飞机大战小游戏编写分享教程(初篇)如何制作?

1. 下载游戏引擎 + 我选择的游戏引擎是 Cocos Creator,官网地址:链接。您可直接点击下载免费获得这款引擎软件,建议下载最新稳定版本。本文撰写时,适合制作 2D 小游戏的最新版本。

1. 下载游戏引擎

游戏引擎我选择的是 cocos creator,官网地址:链接

您可以直接点击下载免费获得这款引擎软件,建议下载最新的稳定版本,写这篇文章的时候,适合写 2D 小游戏的最新版本貌似是:V2.4.8

一般我们会先下载一个 DASHBOARD,可以理解成一个 cocos 的盒子,用于放各种游戏工具。

然后从 DASHBOARD 中下载相应版本的 cocos creator。

2. 创建游戏项目

安装完毕后,我们进入大盘界面:

点击 new 创建一个新的 empty 游戏工程:

看到上面这个界面后,就意味着咱们的开发环境已经搭建好了,可以开始开发小游戏咯!

3. 创建游戏画布

首先我们把游戏资源导入到我们的游戏工程中,游戏资源地址:

然后查看背景图片的大小,资源里的背景图大小是:640 x 1136

于是我们设置画布的大小为 640 x 1136

4. 设置游戏背景

为了减少加载图片所带来的性能损耗,我们把所有的资源合到一张图片中(cocos 能够自动识别这些图片),合图工具用的是:TexturePacker,官方下载地址链接

简单的使用方法如下:

  1. 打开图片目录,把所有的图片拖拽到 TexurePacker 中

  1. 保存

制作完 plist 文件后,我们新建一个叫 plist 的文件夹存放 plist 文件,后续我们使用图片都通过 plist 获取。

然后我们把背景图片 bg 拖拽到节点树上:

为了制作一个轮播的背景,我们需要两张背景图,假设为 A 和 B(想让背景图片动起来,我们必须保证画布中永远有背景)。详细解释参见:链接

首先我们创建一个控制游戏逻辑的 TypeScript 脚本:

然后把脚本文件关联到画布中:

关联到画布后,咱们编写脚本,控制背景图片轮播,首先需要定义两个节点(我们只使用背景图片的坐标属性,因此定义为节点类型就足够了):

@property(cc.Node) bg1: cc.Node = null; @property(cc.Node) bg2: cc.Node = null;

定义完成后记得到画布中进行绑定:

绑定后我们编写轮播的代码:

// 在游戏加载的时候定义背景图片的位置 protected onLoad() { this.bg1.y = 0 this.bg2.y = this.bg1.y + this.bg2.height } update (dt) { // 背景图片的移动速度 this.bg1.y -= 10; this.bg2.y -= 10; // 背景图片轮播逻辑(没明白可以看视频哦) if(this.bg1.y <= -this.bg1.height){ // 当一张背景移动到屏幕外面后,立马补到另一张背景图片的后面 this.bg1.y = this.bg2.y + this.bg1.height } if(this.bg2.y <= -this.bg2.height){ this.bg2.y = this.bg1.y + this.bg2.height } }

编写完成后,咱们就有了轮播的背景图。

5. 添加开始游戏标语

首先我们把游戏标语添加到节点树中,选择一个合适的位置:

为了提示玩家点击屏幕开始游戏,我们在这个节点下添加一个 label 节点用于显示文字:

为了模仿微信飞机大战的展示效果,我们给这行 点击屏幕开始游戏 的文字添加一个上下晃动的动画效果,这里用到了 cocos 的 animation 功能:

  1. 首先我们创建一个动画资源
  2. 将动画资源绑定到 点击屏幕开始游戏 所在的节点上
  3. 然后设置关键帧,给每个关键帧设定恰当的角度,比如说第一帧的角度为 0,第二帧的角度为 15,第三帧的角度为 0,第四帧为 -15,第五帧为 0。

连起来播放后大概就成了这样:

6. 编写游戏准备、游戏中、游戏暂停三个状态

虽然我们编写好了一个轮播的背景,有了动态的效果,但我们希望在游戏刚开始的时候背景是不动的,等玩家进入游戏后背景再动起来,让小飞机有飞翔的效果。

首先我们定义一个判断背景图片是否在动的变量

isBgMove = false

然后把移动背景的代码封装到一个方法里,在 update 方法中通过判断 isBgMove 变量控制背景是否移动:

update (dt) { if(this.isBgMove){ this.moveBg() } } moveBg(){ // 让背景图片动起来 this.bg1.y -= 10; this.bg2.y -= 10; if(this.bg1.y <= -this.bg1.height){ this.bg1.y = this.bg2.y + this.bg1.height } if(this.bg2.y <= -this.bg2.height){ this.bg2.y = this.bg1.y + this.bg2.height } }

有了控制背景轮播的开关后,我们编写游戏准备、游戏中、游戏暂停三个状态。

首先我们把上面定义的 shoot_copyright 节点改个名字,改成游戏准备节点 status_ready;

然后依次创建两个空节点 status_playing 和 status_pause:

然后在游戏开始页面创建一个暂停按钮:

为暂停按钮创建一个点击事件,我们编写一个通用处理点击事件的方法,通过控制台进行调试:

clickButton(sender, str){ if(str == "pause"){ console.log("点击了暂停按钮") } }

然后编写暂停页面:

  1. 首先添加一个暂停的背景图,设置透明度遮盖原有的游戏背景
  2. 添加三个按钮,设置好按钮的样式以及显示内容
  3. 为暂停背景设置一个 BlockInputEvents,屏蔽调下层节点

然后编写这三个页面的显隐关系,大概的逻辑是:

  1. 玩家进入游戏后显示一个静态的背景,当点击屏幕后隐藏调游戏准备界面,进入游戏开始界面
  2. 玩家可以在游戏界面点击暂停按钮,点击暂停按钮后由游戏开始界面进入游戏暂停界面
  3. 在游戏暂停界面有三个按钮,点击继续游戏会回到游戏开始界面,点击重新开始也会回到游戏开始界面,点击回到主页会回到游戏准备界面

以上的逻辑可以通过统一的按键点击方法进行处理:

clickButton(sender, str){ if(str == "pause"){ // 点击暂停后显示暂停页面 this.pause.active = true }else if(str == "continue"){ // 点击继续游戏后隐藏暂停页面 this.pause.active = false }else if(str == "restart"){ // 点击重新开始后隐藏暂停页面 this.pause.active = false }else if(str == "backHome"){ // 点击回到主页隐藏暂停界面,停止游戏,停止背景移动 this.pause.active = false this.playing.active = false this.isBgMove = false this.ready.active = true } }

实现效果大概是这样的:

7. 编写游戏主角我方飞机

编写好了游戏场景切换功能后,我们开始编写我们的游戏主角。

首先添加一个节点,为它设置一张图片(Sprite 属性),然后制作一个小动画:

然后编写飞机跟随手指(鼠标)移动的逻辑,简单来说就是要注册一个触摸移动的监听事件:

setTouch() { // .... this.node.on("touchmove", (event) => { // 获取飞机的位置 let hero_pos = this.hero.getPosition() // 获取手指(鼠标)距离上一次事件移动相对于左下角的距离对象 let move_pos = event.getDelta() // 飞机的位置加上移动的相对位置得到飞机的最新位置 this.hero.setPosition(cc.v2(hero_pos.x + move_pos.x, hero_pos.y + move_pos.y)) }, this); //... }

大概的效果是酱紫的:

8. 让飞机可以发射子弹

由于子弹是会重复利用的资源,我们这里采用预制体资源,首先我们在节点树中创建一个子弹节点,然后给子弹配一个脚本:

在每一帧中改变子弹的 y 值,让子弹有发射的效果。

update(dt) { this.node.y += 10 }

配置好脚本后,我们把子弹节点拖拽到资源管理器中,使其变成一个预制体,然后编写主逻辑脚本,先定义一个预制体:

// 子弹 @property(cc.Prefab) pre_bullet: cc.Prefab

然后尝试在每次鼠标点击结束(触摸手指离开屏幕)的时候生成一颗子弹:

setTouch() { this.node.on("touchend", (event) => { //...... // 生成一颗子弹 let bullet = cc.instantiate(this.pre_bullet) // 把子弹挂在到节点树上 bullet.parent = this.node // 获取飞机主角的位置 let pos = this.hero.getPosition() // 设置子弹的初始位置为飞机头 bullet.setPosition(cc.v2(pos.x, pos.y + this.hero.height / 2)) }, this); }

这样一来飞机就可以发射子弹了:

9. 对象池与单例

现在虽然能不停地发射子弹了,但是一直创建子弹实例不进行删除可不行,如果游戏时间久了游戏会越来越卡。

我们使用 cocos 提供的对象池对子弹进行缓存,先编写一个生成子弹的方法:

createBullet() { // 创建子弹的方法 let bullet = null // 生成子弹的时候先到对象池中取 if (this.bulletPool.size() > 0) { // 如果对象池中有子弹对象则直接使用 bullet = this.bulletPool.get() } else { // 如果对象池没有子弹了,就创建一颗新的子弹 bullet = cc.instantiate(this.pre_bullet) } // 获取子弹后挂在跟节点下 bullet.parent = this.node // 获取飞机的位置 let pos = this.hero.getPosition() // 设置子弹的初始位置 bullet.setPosition(cc.v2(pos.x, pos.y + this.hero.height / 2)) }

然后编写子弹消亡的逻辑,目前一共有三个场景可以回收子弹:

  1. 重新开始游戏
  2. 回到主页
  3. 子弹超出画布范围

// 回收单颗子弹 bulletKilled(bullet) { // 回收子弹的方法 bullet.setPosition(cc.v2(0, 0)) this.bulletPool.put(bullet) } // 回收全部子弹 removeBullets() { let children = this.node.children for (let i = children.length - 1; i >= 0; i--) { let bullet = children[i].getComponent("bullet") if (bullet) { this.bulletKilled(children[i]) } } }

阿菌在开发的时候比较困扰的问题是,我给子弹单独创建一个脚本后,怎么在子弹脚本中引用主逻辑类中的方法呢?

通过在 cocos 论坛搜索,大佬给出的答案是使用单例,单例的简单使用模版如下:

@ccclass export default class Singleton extends cc.Component { // 单例 public static instance: Singleton = null onLoad() { // 初始化单例 if (Singleton.instance == null) { Singleton.instance = this } else { this.destroy() return }

通过上面的代码,把主逻辑对象导出,在子弹脚本中可以这么使用:

微信飞机大战小游戏编写分享教程(初篇)如何制作?

const {ccclass, property} = cc._decorator; // 导入主逻辑类 import Singleton from "./main"; @ccclass export default class NewClass extends cc.Component { update(dt) { this.node.y += 15 if(this.node.y > 590){ // 使用主逻辑单例对象 Singleton.instance.bulletKilled(this.node) } } } 10. 添加敌机

添加敌机的逻辑和添加子弹的逻辑相似:

  1. 在节点树中创建一个敌机节点
  2. 创建敌机的脚本,并关联给敌机节点
  3. 把敌机节点制作成 PerFab
  4. 在主逻辑中编写敌机对象池、敌机创建、敌机销毁的方法

createEnemy1() { // 创建敌机1的方法 let enemy1 = null if (this.enemy1Pool.size() > 0) { enemy1 = this.enemy1Pool.get() } else { enemy1 = cc.instantiate(this.pre_enemy_1) } enemy1.parent = this.node enemy1.setPosition(cc.v2(0, 590)) } enemy1Killed(enemy1){ this.enemy1Pool.put(enemy1) } removeEnemy1s() { let children = this.node.children for (let i = children.length - 1; i >= 0; i--) { let enemy1 = children[i].getComponent("enemy1") if (enemy1) { this.bulletKilled(children[i]) } } }

在敌机脚本中设置敌机移动后,得到的效果大概是这样子的:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jujgCh49-1647963420444)(s21.aconvert.com/convert/p3r68-cdx67/6d7lo-6fcx8.gif)]

11. 子弹与敌机碰撞

有了敌机之后,我们让我方飞机发射的子弹可以击中敌机。

首先我们给敌机和子弹添加碰撞组件(记得给子弹和敌机添加分组):

然后到项目设置中设置敌机和子弹可以碰撞:

接下来编辑敌机死亡的帧动画(还要编辑一个敌机正常状态的动画):

然后在主逻辑中开启碰撞:

// 开启碰撞检测系统,未开启时无法检测 cc.director.getCollisionManager().enabled = true;

开启碰撞后,给子弹编写处理碰撞的方法:

onCollisionEnter(other, self) { if (self.tag == 1) { // 普通子弹命中了普通敌机 Singleton.instance.bulletKilled(this.node) } if (other.tag == 2){ // 击中的是普通敌机 let enemy = other.getComponent("enemy_1") if(enemy && !enemy.isDie){ enemy.hit() } } }

给敌机添加被击中后的处理逻辑:

hit(){ // 击中后状态设置为死亡 this.isDie = true // 播放帧动画 let anim = this.getComponent(cc.Animation) anim.play('enemy_1_die') } over(){ // 帧动画播放完后把敌机放回对象池中,等待下一次出现 Singleton.instance.enemy1Killed(this.node) }

记得给敌机的出生坐标设置一个随机值

//... enemy1.parent = this.node let randomX = 295 - 590 * Math.random() enemy1.setPosition(cc.v2(randomX, 590)) //...

得到的效果是这样的:

好了,上集就先到这,努力更新下集中......

游戏资源地址:
链接:pan.baidu.com/s/1rL82cUYMnxgZQ3xkff5RGw
提取码:r10d

学习参考:链接