Files
hexo-blog/source/_posts/egret-练手-《围住神经猫》.md
T
2020-11-23 18:59:26 +08:00

252 lines
10 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: egret 练手 《围住神经猫》
tags: []
id: '115'
categories:
- - 分享
date: 2017-09-04 11:42:10
---
Egret引擎是一个开源免费的游戏框架,用于构建二维游戏、演示程序和其他图形界面交互应用等。Egret使用TypeScript脚本语言开发。当游戏完成最终的打包后,可以将程序转换为HTML5游戏。实现跨平台特性。 Egret不仅仅是一个基于HTML5技术的游戏引擎,我们的产品线中除了Egret引擎还提供了很多辅助游戏开发的工具。准确的来说,Egret是一套游戏开发的解决方案。你可以使用Egret引擎来帮助你开发HTML5游戏,并运行在手机和PC端的浏览器中,同时也你可以使用Egret提供的相关工具搭建你自己的游戏开发工作流。 Egret的语法与ActionScript 3.0 一致,如果对as3.0熟悉的童鞋能很快上手。 果然有兴趣的童鞋可以直接去Egret的官网,有详细的文档资料 [白鹭引擎官网](https://www.egret.com/) 最近学习Egret,看了一些文档后,决定找个简单的项目自己练一下手,《围住神经猫》应该是个很好的选择。 先贴上完成的作品 [Demo](https://demo.dengtongyu.com/pages/nervcat/) **1.新建项目** 打开EgretWing --> 文件 --> 新建项目 --> Egret游戏项目 完成后打开 src 下的 Main.ts,改文件就是整个项目的入口文件,里面还有一些已经写好的方法,方便你后面调用。 具体请参考 [传送门](http://edn.egret.com/cn/article/index/id/579) 里面介绍得很详细 **2.加载进度条** 新建游戏项目后,默认的加载进度比较简陋,我们需要美化一下。 打开 src\\LoadingUI.ts 文件,这个就是加载进度条的类。
```
class LoadingUI extends egret.Sprite {
public constructor() {
super();
this.createView();
}
private textField:egret.TextField;
private createView():void {
this.textField = new egret.TextField();
this.addChild(this.textField);
this.textField.y = 300;
this.textField.width = 480;
this.textField.height = 100;
this.textField.textAlign = "center";
}
public setProgress(current:number, total:number):void {
this.textField.text = `Loading...${current}/${total}`;
}
}
```
从代码可以看出,进度条仅仅是用文字展示了加载进度,我们来加个进度条UI美化一下。
```
class LoadingUI extends egret.Sprite {
public constructor() {
super();
this.createView();
}
private textField:egret.TextField;
private pBarBg:egret.Shape;
private pBarMove:egret.Shape;
private createView():void {
this.pBarBg = new egret.Shape();
this.pBarBg.graphics.beginFill( 0x989898, 1);
this.pBarBg.graphics.drawRect( 0, 0, this.width, this.height );
this.pBarBg.graphics.endFill();
this.addChild(this.pBarBg);
this.pBarMove = new egret.Shape();
this.addChild(this.pBarMove);
this.textField = new egret.TextField();
this.textField.width = this.width;
this.textField.textAlign = "center";
this.textField.y = 15;
this.addChild(this.textField);
}
private moveProgressBar(percent:number):void{
this.pBarMove.graphics.beginFill( 0x518cdd, 1);
this.pBarMove.graphics.drawRect( 0, 0, this.width*percent, this.height);
this.pBarMove.graphics.endFill();
}
public setProgress(current:number, total:number):void {
var num = Math.floor(current / total * 100);
this.textField.text = 'Loading... ' + num.toString() + " %";
this.moveProgressBar(current/total);
}
}
```
效果如图: ![20170901165944](https://image.dengtongyu.com/blog/2017/09/20170901165944.png) **3.开始画面** 进度条弄好之后,我们开始做游戏开始的画面。如图: ![20170901171729](https://image.dengtongyu.com/blog/2017/09/20170901171729.png) 可以看出,开始画面由背景、网格地图和开始按钮的图片组成,这个实现起来很简单。
```
private mapGroup:eui.Group;//地图容器
private circleArray:Array<object>;//圆圈网格的数组
private bg:egret.Bitmap;//开始Bitmap
private popGroup:eui.Group;//开始画面容器
private btnStart:eui.Button;//开始按钮
private btnStartPng:egret.Bitmap;//开始Bitmap
private init():void{
//利用白鹭预设的创建bitmap方法创建背景图片
this.bg = this.createBitmapByName("bg_jpg");
this.stage.addChild(this.bg);
//地图容器
this.mapGroup = new eui.Group();
this.mapGroup.width = 560;
this.mapGroup.height = 560;
this.mapGroup.x = 40;
this.mapGroup.y = 400;
this.stage.addChild(this.mapGroup);
//开始画面容器
this.popGroup = new eui.Group();
this.popGroup.width = this.SW;
this.popGroup.height = this.SH;
this.popGroup.layout = new eui.BasicLayout();
this.stage.addChild(this.popGroup);
//开始Bitmap
this.btnStartPng = this.createBitmapByName("btn_start_png");
this.btnStartPng.scaleX = this.btnStartPng.scaleY = 1.2;
//开始按钮
this.btnStart = new eui.Button();
this.btnStart.width = this.btnStartPng.width;
this.btnStart.height = this.btnStartPng.height;
this.btnStart.horizontalCenter = 0;
this.btnStart.verticalCenter = 0;
this.popGroup.addChild(this.btnStart);
this.btnStart.addChild(this.btnStartPng);
this.btnStart.addEventListener(egret.TouchEvent.TOUCH_TAP,this.touchHandler,this);
}
private touchHandler(event:TouchEvent) {
this.popGroup.visible = this.btnStartPng.visible = false;
this.btnStart.removeEventListener(egret.TouchEvent.TOUCH_TAP,this.touchHandler,this);
}
然后在createGameScene方法里面执行this.init()就可以了。
但是我们还要绘制围住神经猫的9X9的网格地图。
我们在 src 下面创建一个自定义布局类,命名为 Map.ts
```
```
module uilayout {
var UIComponentClass = "eui.UIComponent";
/**自定义的布局类*/
export class CatMap extends eui.LayoutBase{
public constructor(){
super();
}
/**
* 计算target的尺寸
* 如果您的自定义布局需要根据内部子项计算尺寸,请重写这个方法
**/
public measure():void{
super.measure();
}
/**
* 重写显示列表更新
*/
public updateDisplayList(unscaledWidth:number, unscaledHeight:number):void{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if (this.target==null)
return;
let sunElement:eui.UIComponent;
//子元素个数
let count:number = this.target.numElements;
//元素x轴方向间隔
let gapX:number = 0;
//元素y轴方向间隔
let gapY:number = 0;
//元素所在列数
let column:number = 0;
//元素所在行数
let row:number = 0;
//奇偶行数错位距离
let parityWidth:number = 0;
if(count > 0) {
sunElement = <eui.uicomponent> this.target.getElementAt(0);
gapX = (unscaledWidth - sunElement.width * 9 - sunElement.width / 2)/8;
gapY = (unscaledHeight - sunElement.height * 9 - sunElement.height / 2)/8;
//console.log(unscaledWidth,unscaledHeight,sunElement.width,sunElement.height);
}
for (let i:number = 0; i < count; i++){
let layoutElement:eui.UIComponent = <eui.uicomponent> ( this.target.getElementAt(i) );
if ( !egret.is(layoutElement,UIComponentClass) !layoutElement.includeInLayout ) {
continue;
}
row = Math.floor(i / 9);
column = i % 9;
if(row % 2 == 0) {
parityWidth = 0;
}else{
parityWidth = layoutElement.width / 2;
}
let childX:number = column * (layoutElement.width + gapX) + parityWidth;
let childY:number = row * (layoutElement.height + gapY);
layoutElement.setLayoutBoundsPosition(childX, childY);
}
}
}
}
```
这样一个自定义布局类就写好了,如果对自定义布局不太了解的,可以去Egret的官网查看文档 [传送门](http://edn.egret.com/cn/article/index/id/525) 然后,我们在Main.ts入口文件里绘制9X9的圆圈网格。
```
/**创建网格**/
private creatMap() {
this.circleArray = new Array();
for(let i = 0;i<81;i++){ let circleData = new Object(); circleData['ui'] = new eui.Group(); circleData['ui'].name = i; circleData['img1'] = this.createBitmapByName('pot1_png'); circleData['img2'] = this.createBitmapByName('pot2_png'); if(i == 40) { circleData['img1'].visible = true; circleData['img2'].visible = false; circleData['val'] = 0; }else{ if(Math.random()*10 > 8) {
circleData['img1'].visible = false;
circleData['img2'].visible = true;
circleData['val'] = 1;
}else{
circleData['img1'].visible = true;
circleData['img2'].visible = false;
circleData['val'] = 0;
}
}
this.circleArray.push(circleData);
circleData['img1'].scaleX = circleData['img1'].scaleY = 1.2;
circleData['img2'].scaleX = circleData['img2'].scaleY = 1.2;
circleData['ui'].width = circleData['img1'].width;
circleData['ui'].height = circleData['img1'].height;
//circleData['ui'].layout = new eui.BasicLayout();
circleData['ui'].addChild(circleData['img1']);
circleData['ui'].addChild(circleData['img2']);
if(i == 40) {//中间神经猫的位置
this.insertRunCat(circleData['ui']);
this.cat.visible = false;
this.catPos = 40;
}
if(circleData['val'] == 0) {
circleData['img1'].touchEnabled = true;
circleData['img1'].addEventListener(egret.TouchEvent.TOUCH_TAP,this.touchCircle,this);
}
this.mapGroup.addChild(circleData['ui']);
}
//引用自定义布局
this.mapGroup.layout = new uilayout.CatMap();
}
```
然后在init方法里面执行this.creatMap()就可以完成绘制了 ![20170901171508](https://image.dengtongyu.com/blog/2017/09/20170901171508.png) 后面的操作逻辑就不赘述了,有机会再跟大家分享。