H5游戏选择

1. H5游戏效果呈现

现在的 H5 游戏渲染方式一般有 2D 渲染、3D 渲染、VR 渲染三种。 而 2D 渲染一般也有三种:Dom 渲染、Canvas 渲染、WebGL 渲染。Dom 由于性能原因,一般只适合做一些动画效果较少,交互较少的小游戏。

一般来说,对于 2D 小游戏来说,Canvas 渲染已经足够。然而 Canvas 渲染由于底层封装层次多,不足以支撑起大型游戏的性能要求,因此大型游戏最好选择 WebGL 渲染或者浏览器内嵌 Runtime.

2. WebAssembly

WebAssembly 是一种新的字节码格式,主流浏览器都已经支持 WebAssembly。 和 JS 需要解释执行不同的是,WebAssembly 字节码和底层机器码很相似可快速装载运行,因此性能相对于 JS 解释执行大大提升。 也就是说 WebAssembly 并不是一门编程语言,而是一份字节码标准,需要用高级编程语言编译出字节码放到 WebAssembly 虚拟机中才能运行, 浏览器厂商需要做的就是根据 WebAssembly 规范实现虚拟机.

WebAssembly 字节码是一种抹平了不同 CPU 架构的机器码,WebAssembly 字节码不能直接在任何一种 CPU 架构上运行, 但由于非常接近机器码,可以非常快的被翻译为对应架构的机器码,因此 WebAssembly 运行速度和机器码接近,这听上去非常像 Java 字节码。

相对于 JS,WebAssembly 有如下优点:

  • 体积小:由于浏览器运行时只加载编译成的字节码,一样的逻辑比用字符串描述的 JS 文件体积要小很多;
  • 加载快:由于文件体积小,再加上无需解释执行,WebAssembly 能更快的加载并实例化,减少运行前的等待时间;
  • 兼容性问题少:WebAssembly 是非常底层的字节码规范,制订好后很少变动,就算以后发生变化,也只需在从高级语言编译成字节码过程中做兼容。可能出现兼容性问题的地方在于 JS 和 WebAssembly 桥接的 JS 接口

目前能编译成 WebAssembly 字节码的高级语言有:

  • AssemblyScript:语法和 TypeScript 一致,对前端来说学习成本低,为前端编写 WebAssembly 最佳选择;
  • c\c++:官方推荐的方式,详细使用见文档;
  • Rust:语法复杂、学习成本高,对前端来说可能会不适应。详细使用见文档;
  • Kotlin:语法和 Java、JS 相似,语言学习成本低,详细使用见文档;
  • Golang:语法简单学习成本低。但对 WebAssembly 的支持还处于未正式发布阶段,详细使用见文档。

WebAssembly 的二进制文件格式 wasm,这种格式的文件人眼无法阅读,为了阅读 WebAssembly 文件的逻辑,还有一种文本格式叫 wast

3. H5游戏引擎

Egret

白鹭引擎是企业级游戏引擎,有团队维护。Egret 在工作流的支持上做的是比较好的,从 Wing 的代码编写,到 ResDepot 和 TextureMerger 的资源整合,再到 Inspector 调试,最后到原生打包(支持 APP 打包),游戏开发过程中的每个环节基本都有工具支撑。官网上的示例,教程也是比较多。值得一提的是,今年5月白鹭引擎支持了 WebAssembly ,这对于性能的提升又是一大里程碑

LayaAir

在渲染模式上,LayaAir 支持 Canvas 和 WebGL 两种方式;在工具流的支持程度上,主要是提供了 LayaAir IDE。LayaAir IDE 包括代码模式与设计模式,支持代码开发与美术设计分离,内置了 SWF 转换、图集打包、JS 压缩与加密、APP 打包、Flash 发布等实用功能

Phaser

Phaser 在渲染方面直接封装了 Pixi;架构方面,Phaser 内嵌了3个物理引擎(Arcade Physics、Ninja、p2.js),提供粒子系统、动画、预下载和设备适配方案;兼容性方面,Phaser 的焦点是放在移动端浏览器上的;API 方面,Phaser 能实现丰富的游戏功能,适合复杂度高的游戏开发。

Cocos2d-x

Cocos2d-x 是业界比较老牌的游戏引擎了,同时支持 C++ ,Lua 和 JavaScript 三种开发语言,官方用例来看更倾向于 C++ 开发,适合做一些中大型游戏开发。Cocos2d-x 提供 Cocos Creator 游戏开发工具,组件化,脚本化,数据驱动,跨平台发布。

Three.js

相信对于很多有关注 3D 游戏的开发者来说,Three.js 早已经耳熟能详了。实际上,Three.js 官方定位并不是游戏引擎,而是一个 JS 3D 库。Three.js 更倾向于展示型的视觉呈现,比较少直接拿 Three.js 来开发 H5 游戏。渲染环境上,Three.js 支持 WebGL 和 CSS3D 两种渲染模式。

button 区别

<button> 标签定义一个按钮。 在 button 元素内部,您可以放置内容,比如文本或图像。这是该元素与使用 input 元素创建的按钮之间的不同之处。

<button> 控件 与 <input type="button"> 相比,提供了更为强大的功能和更丰富的内容。<button> 与 </button> 标签之间的所有内容都是按钮的内容,其中包括任何可接受的正文内容,比如文本或多媒体内容。例如,我们可以在按钮中包括一个图像和相关的文本,用它们在按钮中创建一个吸引人的标记图像。

唯一禁止使用的元素是图像映射,因为它对鼠标和键盘敏感的动作会干扰表单按钮的行为。

请始终为按钮规定 type 属性。Internet Explorer 的默认类型是 “button”,而其他浏览器中(包括 W3C 规范)的默认值是 “submit”。

jquery

jQuery 是一个高效、精简并且功能丰富的 JavaScript 工具库.

jQuery 库包含以下特性:

  • HTML 元素选取
  • HTML 元素操作
  • CSS 操作
  • HTML 事件函数
  • JavaScript 特效和动画
  • HTML DOM 遍历和修改
  • AJAX
  • Utilities

在引入jquery时,标签要闭合,否则可以产生,脚本不起作用的现象。

	<script src="_{ _% static 'timeblog/jquery-1.4.4/jquery.min.js'  _%_}"/>

应该用

	<script src="_{ _% static 'timeblog/jquery-1.4.4/jquery.min.js'  _%_}"></script>

DOM加载完成函数

  • 使用jQuery插件一般都这么写

      $(function(){
          //do something
          alert('something  finished!')
      });
    

其实这个就是jQuery ready()的简写,他等价于

$(document).ready(function(){
    //do something
    alert('something  finished!')
});
  • 在不使用jQuery的情况下,可以使用DOMContentLoaded事件可以判断DOM的ready状态。

      document.addEventListener('DOMContentLoaded', function () {
           //do something
           alert('something  finished!')
      }); 它表示在document节点上监听DOMContentLoaded事件,一旦document中的DOM完成加载就触发此事件。
    
  • IE8不支持DOMContentLoaded事件,因此在较低版本的浏览器中,可以使用 readystatechange事件,效果是一样的。

      document.onreadystatechange = function () {
        if (document.readyState == "interactive") { 
                //do something
               alert('something  finished!')
        _}_}
    

其中,document.readyState属性返回当前文档的状态,共有三种可能的值。

- loading:加载HTML代码阶段(尚未完成解析)

- interactive:加载外部资源阶段时

- complete:加载完成时
  • Dom Load

DOM在完全加载完成之后会触发load事件,此时如果想做点事情的话,可以这么写

window.onload=function(){
      //do something
      alert('something  finished!')
} 注意,不要写成document.onload,因为在大多数浏览器中,在document上监听load事件是无效的,应当在window上监听。

使用jQuery的写法

$(window).load(function(){
          //do something
         alert('something  finished!')
}) 这就是Dom Load,他的作用就是,在DOM以及其中的图片等其他外部文件全部加载完毕之后触发。

键盘事件

键盘事件用来描述键盘行为,主要有keydown、keypress、keyup三个事件

document.onkeydown = function(e){
    if(!test.mark){
        test.innerHTML ='';
    }
    test.mark = 1;
    e = e || event;
    test.innerHTML += e.type;
}

document.addEventListener("keydown",keydown);
//键盘监听,注意:在非ie浏览器和非ie内核的浏览器
//参数1:表示事件,keydown:键盘向下按;参数2:表示要触发的事件
function keydown(event){
    //表示键盘监听所触发的事件,同时传递参数event
    switch(event.keyCode){
        case 37:
            alert("左键");
            break;
        case 39:
            alert("右键");
            break;
    }
}

定时器

setInterval(fun, ms)

fun-函数

ms-时间间隔,毫秒

游戏主循环用这个可以实现。

clearInterval(interval);//结束定时器

var interval = setInterval("redoMethod()",1000);//每隔一秒执行一次redoMethod()
 
//假如有两个按钮:继续、暂停
$("#btn-pause").click(function(){//点击暂停按钮
    if(interval){
        clearInterval(interval);
        interval = null;
    }
});
$("#btn-continue").click(function(){//点击继续按钮
    if(interval){
        clearInterval(interval);
        interval = null;
    }
    interval = setInterval("redoMethod()",1000);
});
 
function redoMethod(){
    //循环做某些事情
}

jquery.html()

html() 方法返回或设置被选元素的内容 (inner HTML)。 如果该方法未设置参数,则返回被选元素的当前内容。

$(selector).html()//get
$(selector).html(content)//set

js命名空间

若需定义一个名叫“jsnamespace”顶层命名空间,那么这样写——

var jsnamespace = window.jsnamespace || {};
其实就是使用对象字面量(object literal)的办法声明一个对象变量。即可理解为——

var jsnamespace = {};
赋值写成 window.jsnamespace || {} ,
是为了在重复定义时避免被误覆盖掉。这样便能很方便的在多个文件里定义命名空间了。

示例:

var jsnamespace = window.jsnamespace || {};	
jsnamespace.PersonInfo = function(cfg) {
    cfg = cfg || {};
    this.name = cfg["name"] || "";
    this.gender = cfg["gender"] || "?";
};
可这样使用该类——

    var p1 = new jsnamespace.PersonInfo();
    p1.name = "Zhang San";    // 张三.
    p1.gender = "男";

js构造函数与原型

  • 构造函数

(1)构造函数始终都应该以一个大写字母开头;构造函数本身也是函数,只不过可以用来创建对象;要创建构造函数的新实例,必须使用new操作符;

(2)构造函数例子:

function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;
    this.sayName=function(){
        alert(this.name);
    };
}
var person1=new Person("Nicholas",29,"Software Engineer");
var person2=new Person("Greg",27,"Doctor");

(3) Object.create()

有时候拿不到构造函数只能拿到一个现有的对象,我们想以现有的对象为模板生成实例对象时可以借助这个方法。

var person1 = {
    name: 'tom',
    age: 27
};

var person2 = Object.create(person1);
    person2.name; //tom
  • 原型

对象默认包含了两个成员属性:constructor和__proto__

(1)每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象。使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。

(2)当为对象实例添加一个属性时(person1.name=”Grey”),这个属性就会屏蔽原型对象中保存的同名属性。

一般来说,我们可以使用constructor属性来测试对象的类型:

var myArray = [1,2,3];
(myArray.constructor == Array); // true

js canvas

获取元素:

var mycanvas = document.getElementById("backcanvas");
cavasgame.ctx = mycanvas.getContext("2d");

画圆:

ctx.beginPath();
ctx.arc(pos.x, pos.y, r, 0, Math.PI*2);
ctx.closePath();
ctx.strokeStyle = "#cfc";	//画圆边线颜色
ctx.stroke(); 				//画圆边线
ctx.fillStyle = "green";	//填充颜色
ctx.fill();					//填充内部区域

清区域:

ctx.clearRect(0,0, mycanvas.width, mycanvas.height);

参考:

  1. my coding.net
  2. H5游戏开发:游戏引擎入门推荐
  3. webassembly
  4. http://webassembly.org.cn/getting-started/developers-guide/
  5. https://blog.csdn.net/qq_17007915/article/details/77734324
  6. https://www.cnblogs.com/wjbyzsa/archive/2018/08/11/9459881.html
  7. DOM加载过程中ready和load的区别
  8. JavaScript 实现命名空间(namespace)的最佳方案
  9. 构造函数及原型相关介绍
  10. https://www.cnblogs.com/alichengyin/p/4852616.html