开发 | 傻瓜式操作带你初始化「跳一跳」游戏场景

作者:刘凌歌

上一篇教程里,知晓程序为大家详细讲解了如何创建小游戏「跳一跳」的游戏场景。通过介绍,大家一定对于小游戏的开发有了更进一步的认识。

今天我们将为大家讲解事件的绑定以及 EUI 的进一步使用,以及什么叫「工厂方法」。

为开始按钮绑定事件

上一篇中,我们为 Button 组件定义了 ID 为「beginBtn」,接下来在 BeginScene.ts 文件中声明这个组件的变量。

首先选择 Button 组件「复制自定义」:

这步操作,使得编辑器已经生成好了组件的代码,我们在 BeginScene.ts 文件中直接粘贴:

接下来,我们依旧在这个文件里调用自定义的 init() 初始化方法,为开始按钮绑定点击事件:

这里主要使用 Egret 引擎中的 addEventListener() 方法来为 beginBtn 绑定事件,代码如下:

// 初始化(给开始按钮绑定点击事件)
private init(){
    this.beginBtn.addEventListener(egret.TouchEvent.TOUCH_TAP,this.tapHandler,this);
}
private tapHandler(){
    // 切换场景
    SceneMange.getInstance().changeScene('gameScene');
}

有绑定事件,就会有移除事件:

// 移除事件
public release(){
    if(this.beginBtn.hasEventListener(egret.TouchEvent.TOUCH_TAP)){
        this.beginBtn.removeEventListener(egret.TouchEvent.TOUCH_TAP,this.tapHandler,this);
    }
}

完善场景的切换逻辑

此时距我们点击开始按钮能有效果还差最后一步,那就是在场景控制器 SceneMange.ts 的 changeScene() 中添加释放资源的逻辑:

代码如下:

// 切换场景
public changeScene(type){
    // 释放资源
    if(type == 'gameScene'){
        this.beginScene.release();
    }
    // 移除所有显示列表中的对象
    this.removeChildren();
    // 添加下一个场景
    this.addChild(this[type]);
}

到这里,我们在微信开发者工具中调试代码就可以看到点击「开始游戏」的效果了,不过游戏场景下还是一片空白。

初始化游戏场景 EUI

找到项目结构下 resource 目录下的 scene 文件夹下的 GameScene.exml。按照之前的方法,将游戏场景的宽高设置成舞台宽高:宽 640,高 1136。

添加 Group 组件:拖动组件 - 布局 - Group 组件到 EUI 舞台,并设置其 ID 为「blockPanel」,设置约束为上下左右填充整个舞台。

加入背景图片:拖动组件 - 控件 - Image 控件到舞台,放在 Group 组里,将其作为背景,资源名为「bg_jpg」,设置约束为上下左右填充整个舞台。

接下来我们就要让「小 i」加入舞台了!

置入「小 i」:同样的方式拖入 Image 控件,设置 ID 为「player」,添加资源「piece_png」,宽和高分别为 48 和 130,位置暂时不用约束,后期我们会在代码里去控制。

添加积分 Lable:拖入 Lable 控件,ID 设为「scoreLable」,标签为「0」,样式颜色选择黑色,透明度设为「90」,x 值、y 值、宽、高分别为:100、100、51、90。

最后我们在 blockPanel 的 Group 上右键选择「复制自定义」,然后粘贴复制的 EUI 组件信息到 gameScene.ts 中去。记得随手 ctrl+s 保存。

初始化游戏场景资源

初始化完游戏场景 EUI 后,我们开始初始化 GameScene.ts 游戏场景资源。

首先添加几个变量:

// 所有方块资源的数组
private blockSourceNames: Array<string> = [];
// 按下的音频
private pushVoice: egret.Sound;
// 按下音频的SoundChannel对象,用来暂停该音频
private pushSoundChannel: egret.SoundChannel;
// 弹跳的音频
private jumpVoice: egret.Sound;

然后我们我们自定义初始化方法 init() 并调用。

private init() {
    this.blockSourceNames = ["block1_png", "block2_png", "block3_png"];
    // 初始化音频
    this.pushVoice = RES.getRes('push_mp3');
    this.jumpVoice = RES.getRes('jump_mp3');

    // 添加触摸事件
    this.blockPanel.touchEnabled = true;
    this.blockPanel.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onKeyDown, this);
        this.blockPanel.addEventListener(egret.TouchEvent.TOUCH_END, this.onKeyUp, this);
    // 设置玩家的锚点
    this.player.anchorOffsetX = this.player.width / 2;
    this.player.anchorOffsetY = this.player.height - 20;
}
// 按下的事件逻辑
private onKeyDown(){
}
// 放开的事件逻辑
private onKeyUp(){
}

完整示例如下:

工厂方法生成随机的盒子方块

现在,我们已经构建了基本的 UI 框架,下面我们将从代码层面创建盒子。

「跳一跳」小游戏中需要一个接一个的随机方块,这里由于我们是 2D 画面来实现,所以我们找了三个颜色不同的盒子来演示。

在此之前,还是需要预先在 GameScene.ts 中声明一些必要的变量:

// 所有方块EUI的数组
private blockArr: Array<eui.Image> = [];
// 所有回收方块EUI的数组
private reBackBlockArr: Array<eui.Image> = [];

如图所示:

这个数组

reBackBlockArr 这个数组,是对象池,用来存放超出屏幕的方块盒子。在新创建盒子模型的时候,先查看对象池有没有可以使用的,有的话就直接使用了。然后把这个 EUI 从

reBackBlockArr

拿出来放到

blockArr

中。

等这个 EUI 超出屏幕的时候,就是该销毁了, 把这个 EUI 从显示列表中删除,并且从 blockArr 拿出来放到 reBackBlockArr 中。

这样就形成了一个循环,游戏整个过程中的 EUI 也就是仅仅几个而已。

// 工厂方法,创建一个方块
private createBlock(): eui.Image {
    var blockNode = null;
    if (this.reBackBlockArr.length) {
        // 回收池里面有,则直接取
        blockNode = this.reBackBlockArr.splice(0, 1)[0];
    } else {
        // 回收池里面没有,则重新创建
        blockNode = new eui.Image();
    }
    // 使用随机背景图
    let n = Math.floor(Math.random() * this.blockSourceNames.length);
    blockNode.source = this.blockSourceNames[n];
    this.blockPanel.addChild(blockNode);
    // 设置方块的锚点
    blockNode.anchorOffsetX = 222;
    blockNode.anchorOffsetY = 78;
    // 把新创建的block添加进入blockArr里
    this.blockArr.push(blockNode);
    return blockNode;
}

如图所示:

工厂方法解析:

  • 创建一个方块盒子 EUI,先去对象池里拿,有的话直接拿出来(记得,拿出来的意思事从对象池里面删除)直接用;
  • 如果对象池里面没有的话,就通过 new eui.Image() 方法来创建一个。
  • 从资源数组里面随机一个图片资源:Math.floor(Math.random() * this.blockSourceNames.length);;
  • 把图片资源的纹理添加到方块盒子组件上,然后添加到 blockPanel 这个组件里面,这样显示列表就可以渲染出来这个随机的方块盒子了。

可以看到,在代码注释中写到「设置方块的锚点」。所谓「设置方块的锚点」,就是把一个点当做「中心」,我们把盒子在视觉中的中心作为锚点:

在之前自定义初始化方法 init() 并调用时,我们也已通过以下代码把「小 i」 的「中心」设置在里视觉的脚底:

// 设置玩家的锚点
this.player.anchorOffsetX = this.player.width / 2;
this.player.anchorOffsetY = this.player.height - 20;

设置好锚点之后,EUI 对象的 x/y 的值就是相对与这个锚点来说了。

在下一次的教程里,我们将带大家创建游戏起始界面并且进行触摸事件的逻辑实现。

如果在开发过程中你有什么疑问,也可以留言告诉我们。

原文发布于微信公众号 - 知晓程序(zxcx0101)

原文发表时间:2018-03-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏极乐技术社区

微信小程序那点事:特性总结

一、微信小程序运行环境 1、完全封闭的环境不等于浏览器环境 2、WXML/WXSS/JS格式 3、WXML 不等于 HTML 4、WX...

2126
来自专栏小程序之家

如何使用小程序表单组件

上一篇文章中,我们给大家介绍了小程序的视图容器及基础内容组件,该组件主要应用是输出内容。接下来这篇文章中,我们将继续介绍小程序最常用的表单组件,该组件主要应用是...

2333
来自专栏Golang语言社区

H5一二事 - 要饭的

先回顾一下WEB技术的几个阶段 那么H5肯定不是多了一些标签就完事了,H5也跟酷炫没什么关系,那是CSS3的事情,它更多的职责是功能,而不是外观,是JavaSc...

3078
来自专栏云瓣

React之父子组件传递和其它一些要点

react是R系技术栈中最基础同时也是最核心的一环,2年不到获取了62.5k star(截止到目前),足可见其给力程度。下面对一些react日常开发中的注意事项...

3998
来自专栏IMWeb前端团队

移动端重构实战系列2——line list

本文作者:IMWeb 结一 原文出处:IMWeb社区 未经同意,禁止转载 ”本系列教程为实战教程,是本人移动端重构经验及思想的一次总结,也是对sand...

2198
来自专栏九彩拼盘的叨叨叨

前端组件整理

4172
来自专栏DeveWork

巧用CSS3 :target 伪类制作Dropdown下拉菜单(无JS)

:target 是CSS3 中新增的一个伪类,用以匹配当前页面的URI中某个标志符的目标元素(比如说当前页面URL下添加#comment就会定位到id=“com...

2328
来自专栏Debian社区

HTML 5.1 — 14 项新增特性及使用案例

HTML5 属于万维网联盟 (W3C), 这个组织为整个网络界提供了标准,如此形成的协议可在全世界通行。在 2016 年 11 月, W3C 对长期行使的 HT...

592
来自专栏Nian糕的私人厨房

WeChat 文章列表页面(二)

本次的系列博文的知识点讲解和代码,主要是来自于 七月老师 的书籍《微信小程序开发:入门与实践》,由个人总结并编写,关于更多微信小程序开发中的各项技能,以及常见问...

1464
来自专栏Web行业观察

你真的了解回流和重绘吗?(面试必问)

回流和重绘可以说是每一个web开发者都经常听到的两个词语,我也不例外,可是我之前一直不是很清楚这两步具体做了什么事情。最近由于部门内部要做分享,所以对其进行了一...

1744

扫码关注云+社区

领取腾讯云代金券