Html5 Egret游戏开发 成语大挑战(九)设置界面和声音管理

在上一篇中,简单的使用界面元素快速实现了一个游戏中的二级页面,这种直接在游戏页面上做UI的做法并不太好,原因是,UI会让游戏的压力变大,即使它是隐蔽的,如果同样的功能在其它的地方也是一样的,那么就要写多个同样的逻辑吗?例如设置界面,游戏中的设置界面基本上功能都是一样,如果每个UI中都做一遍,是多么愚蠢的办法?在UI的代码设计中,一般来说,单独的功能不会在其它的地方用到,如GameOver,就直接写在UI里,而如果是通用功能,则最好的做法是做一个通用的单例类或者工厂类在需要的时候将它们初始化,在多个UI中复用逻辑规则。我们就直接用声音设置来实现上面的核心思想,通用类的UI制作,在开始之前,先把SoundMenager类准备好,顾名思义声音管理者,来管理这些声音。
声音管理和播放
请确保你的assets里有sound目录,里面的mp3都在,如buttonclick.mp3
直接实现下面的类:

class SoundMenager {private static shared: SoundMenager;public static Shared(): SoundMenager {if(SoundMenager.shared == null)SoundMenager.shared = new SoundMenager();return SoundMenager.shared;}private _click: egret.Sound;//点击声音private _word: egret.Sound;//点击字块的声音private _right: egret.Sound;//如果胜利private _wrong: egret.Sound;//如果错误private _bgm: egret.Sound;//背景音乐private _bgm_channel: egret.SoundChannel;//保存用来静音用public constructor() {this._click = new egret.Sound();this._click.load("resource/assets/sound/buttonclick.mp3");this._bgm = new egret.Sound();this._bgm.load("resource/assets/sound/Music.mp3");this._right = new egret.Sound();this._right.load("resource/assets/sound/right.mp3");this._wrong = new egret.Sound();this._wrong.load("resource/assets/sound/wrong.mp3");this._word = new egret.Sound();this._word.load("resource/assets/sound/type_word.mp3");}public PlayBGM() {if(this.IsMusic) {this._bgm_channel = this._bgm.play(0,0);}}public StopBGM() {if(this._bgm_channel != null) {this._bgm_channel.stop();}}public PlayClick() {if(this.IsSound) {this._click.play(0,1);}}public PlayRight() {if(this.IsSound) {this._right.play(0,1);}}public PlayWrong() {if(this.IsSound) {this._wrong.play(0,1);}}public PlayWord() {if(this.IsSound) {this._word.play(0,1);}}//音乐是否播放,保存设置public set IsMusic(value) {if(!value) {egret.localStorage.setItem("ismusic","0");this.StopBGM();} else {egret.localStorage.setItem("ismusic","1");this.PlayBGM();}}public get IsMusic(): boolean {var b = egret.localStorage.getItem("ismusic");if(b == null || b == "") {return true;}else {return b == "1";}}//声效是否播放,保存设置public set IsSound(value) {if(value) {egret.localStorage.setItem("isSound","1");} else {egret.localStorage.setItem("isSound","0");}}public get IsSound(): boolean {var b = egret.localStorage.getItem("isSound");if(b == null || b == "") {return true;}else {return b == "1";}}
}

我想这个代码就不做太多的解释了,它是用了异步load声音文件,通过几个Play方法来播放,实现了两个属性:IsSound和IsMusic,来控制是否静音和播放音乐,这个类里_bgm_channel保存了bgm的声音通道,当静音的时候就会stop声音,确保UI交互是正确的。
将它们加到Begin.ts里

运行一下,你会发现出现了这个错误:

大概的意思是和它所写的不太一样,如果你有耐心跟踪断点会有惊喜,在这里就不卖关子,出这个错误的原因是,egret.Sound.load方法中初始化的一个属性是null,所以,避免这个问题的方式也很简单,在LoadingUI的构造函数中调用SoundMenager.Shared()完成预先加载。

public constructor() {super();//预先加载声音
    SoundMenager.Shared();this.createView();
}

这个时间差异其实只有几个毫秒,但是能正确的让声音输出,估计是底层的问题,就不深究其原因了,反正能解决就行,对于异步加载还是预先加载,这属于个人习惯问题,但声音在现在的手机游戏中并不是主要的组成部分,每次打开在加载游戏声音上耗费大量时间得不偿失,不如先玩起来再播放体验来的好。
在你想要加的地方都加上声音,这里就不一一列举,只需要提一下关于错误声音,需要在SceneGame类里做一个判断:

它的意思很简单,如果拼写的检查字段是4个汉字,就会提示错误的声音,胜利的声音之前就处理过了,所以逻辑上没有问题。
好了,打开游戏,测试声音,感觉一下哈
通用的设置界面
设置界面都是通用的,所以我们可以使用一个类配一个皮肤来实现它,建立一个名为GameSettingSkin的exml皮肤文件然后设计设置界面,由于没有准备相关的素材,只得就地取材,将MoneyBG_png这个图片做一下改造,变成九宫格的图形,这样就可以自由拉伸,当设置界面的底板了:

同样,利用YesBtn_jpg和其它的素材组成游戏设置界面:

最终的exml的文件应该是这样的:

<?xml version='1.0' encoding='utf-8'?>
<e:Skin class="GameSettingSkin" width="720" height="1136" xmlns:e="http://ns.egret.com/eui" xmlns:w="http://ns.egret.com/wing"><e:Rect right="0" top="0" bottom="0" left="0" fillAlpha="0.6" locked="true"/><e:Image source="MoneyBG_png" scale9Grid="17,8,196,51" width="400" height="255" horizontalCenter="0" verticalCenter="0.5"/><e:Button id="btn_agree" y="623" horizontalCenter="0.5"><e:skinName><e:Skin states="up,down,disabled"><e:Image width="100%" height="100%" source="YesBtn_jpg" source.down="YesBtn1_jpg"/><e:Label id="labelDisplay" horizontalCenter="0" verticalCenter="0"/></e:Skin></e:skinName></e:Button><e:Group width="102" height="94" x="238" y="512"><e:Button id="btn_music" y="0" x="0"><e:skinName><e:Skin states="up,down,disabled"><e:Image width="100%" height="100%" source="btn_music_png" source.down="btn_music_down_png"/><e:Label id="labelDisplay" horizontalCenter="0" verticalCenter="0"/></e:Skin></e:skinName></e:Button><e:Image id="img_music_disable" x="6" y="2" source="btn_disable_png" touchEnabled="false"/></e:Group><e:Group x="403" y="512" width="102" height="94"><e:Button id="btn_sound" y="0" x="0"><e:skinName><e:Skin states="up,down,disabled"><e:Image width="100%" height="100%" source="btn_sound_png" source.down="btn_sound_down_png"/><e:Label id="labelDisplay" horizontalCenter="0" verticalCenter="0"/></e:Skin></e:skinName></e:Button><e:Image id="img_sound_disable" y="2" x="6" source="btn_disable_png" touchEnabled="false"/></e:Group><e:Label text="设置" y="466" horizontalCenter="0"/>
</e:Skin>

那么配以.ts类来实现UI的逻辑:

//使用一个全局通用的设置界面
class GameSetting extends eui.Component {private static shared: GameSetting;public static Shared(): GameSetting {if(GameSetting.shared == null)GameSetting.shared = new GameSetting();return GameSetting.shared;}private btn_agree:eui.Button;       //同意按钮,相当于直接关闭界面private img_music_disable: eui.Image;//音乐静音显示private img_sound_disable: eui.Image;//声音静音显示private btn_sound: eui.Button;      //声音按钮private btn_music: eui.Button;      //音乐按钮public constructor() {super();this.skinName = "src/Game/GameSettingSkin.exml";this.btn_agree.addEventListener(egret.TouchEvent.TOUCH_TAP,this.click_agree,this);this.btn_sound.addEventListener(egret.TouchEvent.TOUCH_TAP,this.click_sound,this);this.btn_music.addEventListener(egret.TouchEvent.TOUCH_TAP,this.click_music,this);//通过声音管理类来处理界面显示this.update_buttonstate();}private click_agree(){SoundMenager.Shared().PlayClick();this.parent.removeChild(this);}private click_sound(){SoundMenager.Shared().PlayClick();SoundMenager.Shared().IsSound = !SoundMenager.Shared().IsSound;this.update_buttonstate();}private click_music(){SoundMenager.Shared().PlayClick();SoundMenager.Shared().IsMusic = !SoundMenager.Shared().IsMusic;this.update_buttonstate();}private update_buttonstate(){this.img_music_disable.visible = !SoundMenager.Shared().IsMusic;this.img_sound_disable.visible = !SoundMenager.Shared().IsSound;}
}

这个代码我就不做太多的讲解,就是对于一些元素的控制,eui大法真好啊。
下面在SceneBegin、SceneGame、SceneLevels的皮肤文件中分别加入btn_setting,同样,使用MoneyBG_png来做通用的底版,省事就行了。

在各个类中添加对它的定义和处理事件

//第9章新加设置按钮
private btn_setting: ui.Button;
//第9章设置事件
this.btn_setting.addEventListener(egret.TouchEvent.TOUCH_TAP,this.onclick_setting,this);

实现onclick_setting方法:

private onclick_setting() {SoundMenager.Shared().PlayClick();this.addChild(GameSetting.Shared());
}

当点击设置的时候,直接将设置界面的单例UI给添加到本界面中,对应的在GameSetting类中也有this.parent.removeChild(this);将自己移除的方法,所有的设置界面都是一个,结构看起来清晰了很多。
一种比较笨的方式就是挨个添加,还有一种方式是创造一个设置按钮的独立按钮,将它的逻辑写入自己内部,虽然是一个好方法,可是使用起来比较麻烦,当没有大量的独立处理需求时(如ICON),还是用挨个添加比较简单一些。

本篇已经完结,使用声音管理类来加载和播放声音,用单例来实现通用的界面UI的逻辑处理,在多个场景中重复使用。

到此为止这个游戏的完成度已经超过80%,剩下的就是慢慢雕琢以及各种功能的添加,有了前面的基础,后面的扩展开发已经变的非常easy。此篇抛砖引玉之作能够帮助新学egret的朋友快速上手,其中的一些做法也许不是最好的,问题也一样很多,欢迎批评指正。

本篇项目源码:ChengyuTiaozhan6.zip(由于博客园的文件大小限制,resource资源方面请到第二篇的后面下载)

posted on 2016-05-02 21:02 nowpaper 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/nowpaper/p/5453102.html

Html5 Egret游戏开发 成语大挑战(九)设置界面和声音管理相关推荐

  1. Html5 Egret游戏开发 成语大挑战(一)开篇

    最近接触了Egret白鹭引擎,感觉非常好用,提供了各种各样的开发工具让开发者和设计者更加便捷,并且基于typescript语言开发省去了很多学习成本,对于我们这种掉微软坑许久的童鞋来说,确实很有吸引力 ...

  2. Html5 Egret游戏开发 成语大挑战(五)界面切换和数据处理

    Html5 Egret游戏开发 成语大挑战(五)界面切换和数据处理 经过前面的制作,使用Egret的Wing很快完成了开始界面和选关卡界面,下面通常来说就是游戏界面,但此时界面切换和关卡数据还没有准备 ...

  3. Html5 Egret游戏开发 成语大挑战(八)一般性二级页面处理

    Html5 Egret游戏开发 成语大挑战(八)一般性二级页面处理 在游戏中,我们一般会有各种各样的二级页面,比如游戏暂停界面或者游戏结束界面,这些界面组成了对玩家交互主要手段,在游戏开发中,对于这些 ...

  4. Html5 Egret游戏开发 成语大挑战(二)干净的eui项目和资源准备

    Html5 Egret游戏开发 成语大挑战(二)干净的eui项目和资源准备 现在我们使用egret来起步开发一个名叫<成语大挑战>的小游戏,关于egret的开发环境就不在这里啰嗦了,直接去 ...

  5. Html5 Egret游戏开发 成语大挑战(四)选关界面

    Html5 Egret游戏开发 成语大挑战(四)选关界面 通过前面的开始界面基本上了解了eui的使用方法,可以简单快速的制作一个UI界面,本篇使用第二界面选关界面展示更为难一点的代码控制,来展现关卡地 ...

  6. Html5 Egret游戏开发 成语大挑战(六)游戏界面构建和设计

    Html5 Egret游戏开发 成语大挑战(六)游戏界面构建和设计 本篇将主要讲解游戏界面的构建和设计,会应用到egret.eui的自定义组件,可以很直观的构建一个游戏整体,这里我们仍然只需要使用Eg ...

  7. Html5 Egret游戏开发 成语大挑战(七)游戏逻辑和数据处理

    Html5 Egret游戏开发 成语大挑战(七)游戏逻辑和数据处理 本篇在前面的基础上,将进行逻辑的编码开发让游戏能够正式的玩起来,这里没有注重太多的体验细节,而是直接实现游戏的规则逻辑,将分成两个部 ...

  8. Html5 Egret游戏开发 成语大挑战(三)开始界面

    Html5 Egret游戏开发 成语大挑战(三)开始界面 本篇需要在前面的素材准备完毕,才可以开始,使用egret的eui结合代码编辑,快速完成基本的界面搭建,这里写的可能比较细,目的是减少大家对于其 ...

  9. 微信小游戏 腾讯课堂《白鹭教育 - 成语大挑战小游戏开发》学习笔记

    腾讯课堂<白鹭教育 - 成语大挑战小游戏开发>:https://ke.qq.com/course/287266 学习笔记 首先这个视频课程简单介绍了一个小游戏的制作,包括新建项目.适配模式 ...

最新文章

  1. idea添加database插件_IDEA高级玩法:集成JIRA、UML类图插件、SSH、FTP、Database管理......
  2. 【C++ 语言】C++字符串 ( string 类 | 创建方法 | 控制台输出 | 字符串操作 | 栈内存字符串对象 | string* )
  3. hyperledger-simple-app
  4. Microsoft Power BI Desktop概念学习系列之Microsoft Power BI Desktop的官网自带示例数据(图文详解)...
  5. 强大的jQuery图片查看器插件Viewer.js
  6. linux实验三makefile,实验平台上Makefile详细的解释
  7. 推荐算法--其他信息(07)
  8. B君的圆锥(51Nod-1629)
  9. Docker系列(二):Docker安装
  10. 谁与争锋,2020腾讯广告算法大赛初赛正式启动
  11. thinkpad分区win10_预装win10系统Thinkpad笔记本只有一个C盘怎么分区
  12. 如何使用Tipard 3D Converter转换2D视频格式
  13. python:关于读取文件的指定行的问题
  14. Cesium雷达放射波
  15. c语言汇率转换代码_原生JS实现汇率转换功能代码实例
  16. Forth 语言概要
  17. SaaS 公司融资的「22条军规」
  18. optuna-自动化调参利器
  19. 【Vue轮播插件】常用的vue轮播插件整理
  20. OS-练习题(10~13)

热门文章

  1. c# rar解压大小_C#解压RAR压缩文件
  2. 通过Hyper-V的方式快速安装Linux虚拟机
  3. 图像神经网络模型有哪些,图像神经网络模型制作
  4. 【车辆计数】基于matlab GUI背景差分法道路行驶多车辆检测【含Matlab源码 1911期】
  5. Linux上:使用VMware17安装Centos8.5并配置网络、WSL安装Ubuntu、
  6. 面对这样的网络状况我真的醉了
  7. 开发运维(DevOps)自动化运维与持续交付企业级实战
  8. LabVIEW控制Arduino实现RGB调色灯(基础篇—6)
  9. 雷神笔记本做java,八代酷睿+144Hz电竞屏 雷神迎来新911黑幽灵游戏本评测
  10. PG数据库查看数据大小参考