基础能吃人
无意义的碎碎念
之前花了一周左右的时间细读了《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游戏引擎里它现在的排名是第一。我始终保持这个一个观点,框架、引擎这种东西,永远是让你程序写得更舒服而存在的,如果它让你不舒服了,那就没有学的必要。