欢迎点击「算法与编程之美」↑关注我们!
本文首发于微信公众号:"算法与编程之美",欢迎关注,及时了解更多此系列文章。
作者|王小强
来源|https://my.oschina.net/wxqdoit
简述
LayaAir 是基于HTML5开源引擎,所开发的游戏既可以网页运行,也可以打包Android & ios app运行,目前更到1.7.19.1 beta版本,本次使用1.7.18稳定版。 本文介绍laya的下载安装,项目创建,目录结构,环境配置与es6 的支持,及具体开发知识,网页端发布等等方面。
下载安装
官网传送门:www.layabox.com
进入首页看到如下两个下载按钮:
此刻就让人有点懵逼了,layaAir Engine可以理解为引擎内核(源码),IDE就是集成开发工具了,直接下载IDE就好,因为下载下来的已经集成对应版本的源码包了(你会发现,每一个版本的源码都有对应版本的IDE。截止目前更到1.7.19.1 beta版本,为了稳定还是使用1.7.18版本。如下(对,你没看错,蓝色那个,点...点...点它:
下载完成之后是一个zip压缩包,不用安装的,直接解压到你想放的位置,完事儿之后就可以使用了:
就是他了(.exe文件,双击吧,看到如下界面你就完成第一步了!
项目创建与目录结构
点击新建项目,弹出如下框:
选择默认的UI示例项目,类型选择JavaScript项目,如果你会as或者ts也可以选它,然后点击创建,创建完成进入代码模式,简单标注了一下:
接下来什么将调试器选择chrome调试,点击三角按钮或者按f5运行,你会看到如下一个巨丑的页面弹出来emmmm(真的很丑,但是只要正常看到,这一步就算完成了)。
接下来是目录结构,传送门:https://ldc.layabox.com/doc/?nav=zh-js-1-0-0,不过这个里面说的hin多hin杂,在这里简单说重点:
项目运行配置文件(.laya文件夹)。
- launch.json,当你将项目移动或拷贝到别处的时候需要修改,什么路径统统要改。
- 如果你用chrome运行项目,会有一个chrome文件夹,不用管他,垃圾东西。
项目的输出目录(bin文件夹)。项目编译后的东西都在里面,什么动画,图集,你的源码等等,最后项目发布也是从这个目录发布
- lib,全是引擎的源码包,不用的可以删除
- res,资源文件,图片图集,音频文件都可以在里面
- index.html,点进去看看,里面说的很清楚了
UI项目目录(laya)。其实这些都看自己的喜好,没有规定的话,只要合理爱咋咋地吧。
- laya/assets目录用来存放UI页面、粒子等组件所需的图片资源。
- laya/pages目录用来存放LayaAirIDE创建页面布局生成的文件。
代码提供文件目录(libs),不用管他。
项目代码目录(src)。
这个就比较牛逼了,全是你的代码,不过后面我们不在里面开发。
目录结构也介绍完了,这一节大概就是这些,下一节讲解配置我们真正的而开发环境。
环境配置
既然是属于h5前端开发,自然要配置一系列的工具。webpack,babel,gulp等等。(如果大家不想使用这些工具,直接用项目默认的开发模式也可以,前面也足够了)
- 安装Node.js,推荐稳定版本8.x吧(不会问度娘。
- 在项目根目录新建文件夹www(其实开发文件夹应该叫做src的,无奈被默认的目录占用了,src这个文件夹不能动他,因为构建的ui文件类会在里面,稍后我们输出webpack的main.js也会放在里面。然后项目编译时会用到src)。
- 接下来切换到下方的终端(没有看到的话f5一下吧),用npm安装如下一堆依赖的东西(你可以直接建一个package.json文件,将下面的考进去,然后npm install,谢谢赶紧我~~)。完了之后www会有一个node_modules文件夹,全是刚才装的b:
- { "name": "webpack-demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo "Error: no test specified" && exit 1", "webpack": "webpack" }, "author": "wxq", "license": "ISC", "dependencies": { "babel-cli": "^6.26.0", "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-plugin-transform-runtime": "^6.23.0", "babel-polyfill": "^6.26.0", "babel-preset-env": "^1.6.1", "dateformat": "^3.0.3", "gulp": "^3.9.1", "gulp-babel": "^7.0.1", "gulp-less": "^3.4.0", "gulp-util": "^3.0.8", "webpack": "^3.10.0", "webpack-stream": "^4.0.0" } } 创建.babelrc文件,里面是babel的预设集配置等,如果你不想懂,可以直接copy进去: { "presets": ["env"], "plugins": [[ "transform-runtime", { "helpers": false, "polyfill": false, "regenerator": true, "moduleName": "babel-runtime" } ]] }
- 创建webpack.config.js文件,这个是webpack的配置文件,主要配置webpack打包的入口文件口和输出文件,之后会时候gulp的自动任务执行webpack打包,同时会将es6(es7、es8)通过bable转译为es5。
- 创建gulpfile.js文件,这个是gulp的配置文件,如果你不想懂,也可以直接copy进去: const gulp = require("gulp"); //转译JavaScript gulp.task("webpack",()=>{ const webpack = require("webpack-stream"); const config = require("./webpack.config"); gulp.src("./src/**/*.js") .pipe(webpack(config)) .pipe(gulp.dest("../src/")) }); gulp.task("watch",function(){ gulp.watch("./src/**/*.js",['webpack']); }); gulp.task("default",["webpack",'watch']); 解释一下吧,引入依赖gulp,创建三个任务,第一个是打包任务,webpack执行,第二个是watch任务监听文件变化自动执行第一个任务,这样就不需要每次修改文件都去执行gulp命令了,美滋滋~~,第三个默认任务,就是去执行上面两个咯。
- 执行npm install gulp -g 安装gulp到全局(必须安装到全局 全局 -g),不然会报错。
上述步骤完成且没有问题之后,成功之后再去执行gulp命令吧,如图我将www下面的src文件夹下面的所有东西都打包到了根目录下的src文件夹的mian.js文件里面:
然后打开你的www-->src-->main.js:
就长这样啦,然后去把index.html里面的代码改改吧,噢啦,环境搭建完成。
代码语言:javascript复制<!--IDE生成的UI文件-->
<script src="../src/ui/layaUI.max.all.js"></script>
<!--jsfile--startTag-->
<script src="../src/main.js"></script>
<!--jsfile--endTag-->
如果到这里,你没有如遇到什么难题,那我们就可以准备进入正题了,emmmm。
开发入门
舞台搭建与适配
开发目录下新建的main.js文件全部代码删除,然后不用管它,接下来:
GameMain.js:
代码语言:javascript复制export class GameMain {
constructor() {
}
static init() {
Laya.MiniAdpter.init();
Laya.init(768, 1366, Laya.WebGL);
Laya.stage.bgColor = "#5a7b9a";
//水平对齐方式,水平居中
Laya.stage.alignH = Laya.Stage.ALIGN_CENTER;
//垂直对齐方式,垂直居中
Laya.stage.alignV = Laya.Stage.ALIGN_MIDDLE;
//按照宽度
Laya.stage.scaleMode = Laya.Stage.SCALE_SHOWALL;
//屏幕适配,横屏还是竖屏,默认不改变
Laya.stage.screenMode = Laya.Stage.SCREEN_NONE;
//禁用多点触控
Laya.MouseManager.multiTouchEnabled = false;
}
}
如果es6不懂的可以先去补一下,创建一个静态的方法init()。
Laya.MiniAdpter.init();//如果不考虑微信小游戏可以不加,当然加上也不会怎样。
Laya.init(768, 1366, Laya.WebGL);//初始化舞台大小,记住这个尺寸是设计大佬给的,她们的图都按照这个尺寸来做的。宽、高、渲染方式。
Laya.stage.bgColor = "#5a7b9a";//这个舞台背景,爱咋咋地吧。
接下来的全是做是配的,copy贴上去就对了。还有其他的适配方式,以及参数,自己去官网看吧,反正我怎么不用。
关于图集打包与资源加载策略
在进入main文件之前讲一讲这两点:图集打包与资源加载。
图集打包:
进入编辑模式,你懂我意思吧:
看图的时候不要问我拿来那么多文件,看重点:在这个界面,当你按下f12的时候,会发布代码,并将红色框里的文件夹里面的图片,按分文夹的方式打包成图集,这些文件就是在www/laya/assets下面,发布完成之后,你在bin/res/atlas下面看到图集的.png与.atlas(json)文件,这两个文件都是一一对应的。
注意:在编辑模式按f9可以进行设置,包括图集的大小,当然,这里主要也是设置图集大小。
这图集打包就这样咯,接下来是资源加载↓↓↓↓↓
资源加载:
关于资源加载如果做过游戏都知道,有一个载入界面,载入界面用到的所有资源最好是放在游戏包里面,进行第一次加载。第一次加载完成之后就是加载游戏需要的其它大部分资源,这里面的资源有可能是在本地,也有可能加载网络资源,一般需要写一个资源加载类。
简单介绍laya里面的资源加载类该如何写:
主要使用Laya.loader.load()方法进行加载,该方法有三个参数:
代码语言:javascript复制Laya.loader.load(this.resources, Laya.Handler.create(this, loaded), Laya.Handler.create(this, loading, null, false));
第一个,资源,如果单个加载,可以写字符串路径,如果批量加载,写成数组对象:
代码语言:javascript复制let res = [
{url: "res/atlas/start.atlas"},
{url: "res/atlas/activity.atlas"},
{url: "res/atlas/popup.atlas"},
{url: "res/atlas/comp.atlas"},
{url: "res/atlas/part.atlas"},
{url: "res/atlas/shareMask.atlas"},
{url: "res/atlas/common.atlas"},
{
url: "res/sound/btn_click.mp3",
name: "btn_click",
type: Laya.Loader.SOUND
},
{
url: "res/sound/btnShowSound.mp3",
name: "btnShowSound",
type: Laya.Loader.SOUND
}
]
name可以作为名字调用资源,如果不写,用的时候只能通过字符串路径调用资源;
type是资源类型,也可以不写,但最好写上
第二个:加载完成的回调,只返回true或者false,
第三个:加载过程的回调,返回的是数字,从0-100。
上一下完整的代码:
代码语言:javascript复制import {GameMain} from './base/GameMain.js'
import {ResLoader} from './utils/ResLoader.js'
import {MainBoard} from "./base/MainBoard";
import {UserUtils} from "./utils/UserUtils";
import {GlobalData} from "./base/GlobalData";
import {GameEvent} from "./utils/GameEvent";
import {LayoutUtils} from "./utils/LayoutUtils";
GameMain.init();
Laya.loader.load("res/atlas/loading.atlas", Laya.Handler.create(this, function (e) {
let resManager = ResLoader.getInstance();
let loading = new ui.view.gameLoadingUI();
Laya.stage.addChild(loading);
let sp_mask = loading.sp_mask;
sp_mask.optimizeScrollRect = true;
resManager.loaded((e) => {
let mainBoard = MainBoard.getInstance();
let user = UserUtils.getInstance();
user.getWxUser({
sucFn: () => {
console.log('登陆成功v1.0.0');
Laya.stage.addChild(LayoutUtils.getInstance().map.get("gameStartUI"));
Laya.stage.removeChild(loading);
mainBoard.initMainBoard();
GameEvent.getInstance().bindListenEvent();
GameEvent.getInstance().remarkGameTime();
}, errFn: () => {
alert('登陆失败');
}
});
}, (e) => {
let process = parseInt(e * 100);
loading.progress_text.text = process '%';
sp_mask.scrollRect = new Laya.Rectangle(0, 0, 5.2 * process, 24);
});
}));
resManager是我自己写的资源加载管理器,做统一资源管理,其实跟这加载一样,只是资源多,封装了一下。
多说一句:单例模式
因为这里基于es6的类,常常需要实例化类,像资源加载这种只需要实例化一次的就需要用到js的单例模式,具体实现如下:
代码语言:javascript复制export class ResLoader {
static getInstance() {
return ResLoader.instance ? ResLoader.instance : ResLoader.instance = new ResLoader();
}
constructor() {}
}
UI创建
如果你不想通过它的编辑器创建界面也是可以的,只不过全部用代码来实现比较麻烦,看看他的ui有哪些组件吧,传送门:https://layaair.ldc.layabox.com/api/?category=UI&class=laya.ui.AsynDialog
什么Image,Text,Button,Sprite全部自己写也很不爽。不过你可以试试用自己写代码的方式来进行游戏布局,比如我写的一些:
代码语言:javascript复制diyPopup(btnImgs) {
let length = btnImgs.length;
let btnArr=[];
let popupUI = this.map.get('gamePopupUI');
for (let i = 0; i < 3; i ) {
popupUI.removeChildByName(`btn${i===0?'':i}`)
}
if (length === 1) {
let btn = new Laya.Image().size(262, 116).pos(250, 678);
btn.skin = btnImgs[0];
btn.name = 'btn';
btnArr.push(btn);
popupUI.addChild(btn);
} else if (length === 2) {
let btn1 = new Laya.Image().size(262, 116).pos(67, 678);
btn1.name = 'btn1';
btn1.skin = btnImgs[0];
let btn2 = new Laya.Image().size(262, 116).pos(443, 678);
btn2.name = 'btn2';
btn2.skin = btnImgs[1];
btnArr.push(btn1,btn2);
popupUI.addChild(btn1);
popupUI.addChild(btn2);
}
//遮罩
popupUI.bg_wrap.graphics.clear();
popupUI.bg_wrap.graphics.drawRect(0, 0, Laya.stage.width, Laya.stage.height, "#000000");
return {popupUI:popupUI,btnArr:btnArr}
}
//自定义
diyIcon(iconArr) {
let length = iconArr.length;
let mainUI = this.map.get('gameMainUI');
mainUI.icon_wrap.destroyChildren();
let iconUI = [];
if (length === 1) {
let icon = new Laya.Image().size(77, 68).pos(258, 0);
icon.skin = iconArr[0];
mainUI.icon_wrap.addChild(icon);
iconUI.push(icon)
} else if (length === 2) {
for (let i = 0;i < length;i ){
let icon = new Laya.Image().size(77, 68).pos(207 i*(30 77), 0);
icon.skin = iconArr[i];
mainUI.icon_wrap.addChild(icon);
iconUI.push(icon)
}
} else {
for (let i = 0;i < length;i ){
let icon = new Laya.Image().size(77, 68).pos(169 i*(15 77), 0);
icon.skin = iconArr[i];
mainUI.icon_wrap.addChild(icon);
iconUI.push(icon)
}
}
return iconUI;
}
还是用编辑器拖拖拉拉舒服,点击view新建页面/场景,最好把逻辑类勾,本人当时没有勾上,就全部发布到一个文件里面去了,下面会说的。然后直接往上怼:
做完之后按f12发布,就会发布到src/ui下面的layaUI.max.all.js里面。
接下来在代码里面引用:
代码语言:javascript复制let gameMain= new ui.view.gameMainUI();
Laya.stage.addChild(gameMain);//添加到舞台,removeChild()你懂吧
如此,页面场景也可以自己搭建好了。其实还有一部分是粒子和动画,但是我觉得这个可以看看官网给的教程(我司有做粒子和动画的,我不会),传送门:https://ldc.layabox.com/doc/?nav=zh-js-2-1-10。
这一入门部分也就告一段落,基本上可自己写出一个demo。下一篇准备讲讲使用laya的API以及其中遇到的巨坑。laya系列完了之后准备再写一个egret入门与坑的系列。如果有错误的地方,还请多多指教。
拓展阅读:
深入理解遗传算法(一)
深入理解遗传算法(二)
从1到100求和学算法思维(一)
从1到100求和学算法思维(二)
从1到100求和学算法思维(三)
从1到100求和学算法思维(四)
从1到100求和学算法思维(五)
从1到100求和学算法思维(六)
where2go 团队
微信号:算法与编程之美
温馨提示:点击页面右下角“写留言”发表评论,期待您的参与!期待您的转发!