基础能吃人
无意义的碎碎念
之前花了一周左右的时间细读了《Pro HTML5 Games》这本书的前5章,发现一个很重要的道理,变量的对象(函数)化封装非常的重要,一个能够防止歧义,避免环境污染,还有一个是是代码显得简洁美观。
没有任何基础的情况下(纯原生canvas),当初做一个类东方游戏的时候,我是这样写的;总共近1k行,放个前一百行,你们体验一下:
捂眼(瞎)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 
  | var canvas, 	ctx, 	w, 	h, 	bgPIC = new Image(), 	picLoc, 	picSpeed = 0.2; bgPIC.src = "./img/bg.png"; EventUtil.addHandler(window, "load", start); EventUtil.addHandler(window, "keydown", key_down) EventUtil.addHandler(window, "keyup", key_up) var gameover = false, 	score = 0, 	Fscore = 0, 	scoreL = true, 	edgeScore = 5, 	sScore = 200, 	mScore = 500, 	backgroundColor = "rgb(235,0,0)", 	menuColor = "rgb(30, 30 ,100)"; var ballinit = { 	x : 150,  	y : 300, 	r : 4, 	vx : 0, 	vy : 0, 	v : 5,	 	sv : 2,	 	nv : 5,  	rate : 2.5,	 	color : "rgba(255,0,0,1)", 	isSlow : false, 	isProtected : false, }; var ball = new Object(); for(var pro in ballinit){ball[pro] = ballinit[pro];} var lifeLeft = 2, 	bombsinit = 3, 	bombsLeft = 3, 	bullets = [], 	bombs = [], 	bombAvai = true, 	bombCD = 5000, 	protectTime = 2000; 	 var enemyBullet = [], 	enemis = [], 	levelupCD = 30000, 	levelNum = 0, 	level = { 		dayuT : 3000, 		zhongyuT : 2000, 		EST : 1000, 		EMT : 2000, 	}, 	ts1,ts2,ts3,ts4,ts5,ts6,levelup; var isDowninit = { 	up : false, 	down : false, 	left : false, 	right : false, 	item : false, }; var isDown = new Object(); for(var pro in isDowninit){isDown[pro] = isDowninit[pro]}; isDown.shoot = false; function start(){ 	canvas = document.getElementById('canvas') 	ctx = canvas.getContext('2d') 	canvas.width = 500 	canvas.height = 400 	w = canvas.width - 200 	h = canvas.height 	picLoc=bgPIC.height-bgPIC.width*h/w 	 	var ts1 = setInterval(function(){		 		update(ball) 		render(ball, ctx) 	}, 20) 	var ts2 = setInterval(function(){ 		 		if(isDown.shoot){ 			if(ball.isSlow){ 				bullets.push( 					bullet({swing:0.3,dx:4,dy:-3}),  					bullet({swing:-0.3,dx:-4,dy:-3}), 					bullet({swing:1,dx:10,dy:5}), 					bullet({swing:-1,dx:-10,dy:5}) 				); 			}else { 				bullets.push( 					bullet({swing:2,dx:7,dy:-3}),  					bullet({swing:-2,dx:-7,dy:-3}), 					bullet({swing:6,dx:15,dy:20}), 					bullet({swing:-6,dx:-15,dy:20}) 				); 			} 		} 	}, 50) 	IntervalStart() 	levelup = setInterval(levelUP, levelupCD) } 
  | 
举个例子。
一个场景对象state,我们要创建它,初始化它,更新它,渲染它,我们就不应该凌乱的陈列函数,应该用对象或是方法去封装它们比如这样:
1 2 3 4 5 6 
  | var state = {     create: function() {},     init:  function() {},     update:  function() {},     render: function() {}, } 
  | 
 
不过我更推荐下面这个构造函数(慎用)
1 2 3 4 5 6 
  | function state ()  {     this.create = function() {};     this.init = function() {};     this.update = function() {};     this.render = function() {}; } 
  | 
一些零碎而重要的全局变量和参数,也应该封装:
1 2 3 4 5 6 7 8 9 10 11 12 
  | var game = {     ctx: Document.getElementById("canvas").getContext('2d'),          init: function(){},      } var box2d = {     scale: 30, 	      } 
  | 
这样说可能让人更凌乱了。但是不管一个HTML游戏怎么变,都可以归于几个模块(以angry bird为例):
最开头的自执行函数
用于某些无法解释的黑科技。
 
game对象
包含其他对象的初始化,DOM的操作判断,背景音乐的判断控制,游戏的进程管理控制,动画的数据更新与渲染器管理,以及其他不会分类的变量与方法。
 
levels对象
用于存放每一关的数据,包括音乐图片敌人数据以及它们的初始化方法和加载的方法。
 
entities对象
存放每一种敌人或互动物体的详细信息,和创建它们时“数形结合”的方法。
 
box2d对象
具体的物理引擎的内部方法的简化与具体实现。
 
loader对象
加载器,所有的音乐图片加载统一用这个对象里的的方法,包括浏览器的支持,加载与渲染的顺序问题等。
 
mouse对象
初始化鼠标操作的事件,监听移动,按下,放开等状态。
 
封装好以后,游戏就变成这样辣
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 
  | (function(){... })(); $(window).load(function(){     game.init(); }); var game = {... }; var levels = {... }; var entities = {... }; var box2d = { }; var loader = {... }; var mouse = {... }; 
  | 
是不是看的很爽!
头疼的安全问题
在涉及到webGL的时候,学习瓶颈的出现往往是代码OK的情况下,只要一出现drawImage,Safari抛出个”SecurityError”,Chrome抛出个”canvas tainted by cross-origin data”,解决无果,心灰意冷,放弃。
今天要学习的Phaser也是一样,就好像好不容易看上挺好一妹子,谈不上话,心塞塞。英文文档看的很吃力,前辈们表示不会,心灰意冷。一个简单的图片移动的例子,十几行代码,就是跑不动。幸好把源码放到FF里时,它跑动了,在解决跨域资源问题之前,我先把火狐当祖宗一样供着吧!(拥抱ES6)
伪·正片
我们来谈谈Phaser
Phaser.js是一个游戏引擎,目前将要出Phaser3版本。它帮开发者造好了轮子,直接通过Phaser对象方法来完成游戏的开发。
这个引擎说大不大,说小不小,近10w行代码,压缩后也还有700多kb。用这个引擎做的游戏很多,在js游戏引擎里它现在的排名是第一。我始终保持这个一个观点,框架、引擎这种东西,永远是让你程序写得更舒服而存在的,如果它让你不舒服了,那就没有学的必要。