如何开发一个简单的HTML5画布游戏?
创建画布
//创建画布
var canvas = document . createelement(" canvas ");
var CTX = canvas . get context(" 2d ");
帆布.宽度= 512;
canvas.height = 480
document . body . appendchild(canvas);
首先,我们需要创建一个画布作为游戏的舞台。HTML,编写一个
准备图片
//背景图片
var bgReady = false
var bgImage = new Image();
bgImage.onload = function () {
bgReady = true
};
bgimage . src = " images/background . png ";
游戏少不了图片,先加载一些图片吧。为了简单起见,这里只创建简单的图片对象,而不是编写一个类或者Helper来加载图片。变量bgReady用于标识图片是否已经加载,是否可以安全使用,因为如果图片是在没有加载的情况下绘制的,会给出错误。
我们用上面的方法来处理整个游戏中需要的三个画面:背景,英雄,怪物。
游戏对象
//游戏对象
var hero = {
速度:256,//像素每秒移动
x: 0,
y: 0
};
var monster = {
x: 0,
y: 0
};
var monster catch = 0;
现在定义一些稍后会用到的对象。我们的英雄有一个速度属性来控制他每秒移动多少像素。游戏过程中怪物不动,只有坐标属性就够了。monsters catch用于存储怪物被抓的次数。
处理用户输入
//处理键
var keydown = { };
addEventListener("keydown ",函数(e) {
keys down[e . keycode]= true;
},假);
addEventListener("keyup ",函数(e) {
删除keydown[e . keycode];
},假);
现在开始处理用户的输入(对于刚接触游戏开发的前端同学来说,这个部分一开始可能需要一些脑力)。在前端开发中,用户通常会在执行动画或者发起异步请求之前触发点击事件,但是这里我们希望游戏的逻辑能够更加紧凑,能够及时响应输入。所以我们首先保存用户的输入,而不是立即响应。
为此,我们使用keysDown对象来存储用户按下的键码。如果按下的键值在这个对象中,那么我们将相应地处理它。
开始游戏
//当用户抓到怪物时,开始新一轮游戏。
var reset = function () {
hero . x = canvas . width/2;
hero . y = canvas . height/2;
//在界面上随意放新的怪物。
monster . x = 32+(math . random()*(canvas . width-64));
monster . y = 32+(math . random()*(canvas . height-64));
};
重置方法用于开始新一轮的和平游戏。在这个方法中,我们把英雄放回画布的中心,把怪物放在一个随机的地方。
更新对象
//更新游戏对象的属性
var update = function (modifier) {
if(keydown中的38){//用户按下了↑。
hero.y -= hero.speed *修改器;
}
if(40 in keydown){//用户按下了↓
hero.y += hero.speed *修改器;
}
if(keydown中的37){//用户按下了键。
hero.x -= hero.speed *修改器;
}
if(39 in keydown){//用户按下→
hero.x += hero.speed *修改器;
}
//英雄和怪物相遇了吗?
如果(
hero.x & lt= (monster.x + 32)
& amp& ampmonster.x & lt= (hero.x + 32)
& amp& amphero.y & lt= (monster.y + 32)
& amp& ampmonster.y & lt= (hero.y + 32)
) {
++ monster scatter;
reset();
}
};
这是游戏中用来更新画面的更新功能,会定期反复调用。首先,它负责检查用户当前是否按住了中间的方向键,然后在相应的方向上移动英雄。
可能就是这个传入的修饰变量需要一点脑力。你可以去main。
在方法中看到它的来源,但是这里有必要详细解释一下。是一个从1开始,随时间变化的因子。比如1秒过去了,它的值就是1,英雄的速度会乘以1,也就是每秒移动256个像素;如果用了半秒,那么它的值就是0.5,英雄的速度乘以0.5,也就是说英雄在这半秒内的移动速度是正常速度的一半。理论上,由于这次更新,
方法调用的非常快,非常频繁,所以modifier的值会很小,但是有了这个因素,无论我们的代码运行的有多快,都可以保证英雄的移动速度是恒定的。
既然英雄的移动是基于用户的输入,那么就该检查移动过程中触发的事件了,也就是英雄遇到了怪物。这是这场游戏的胜利,怪兽捕手。
+1,开始新一轮。
渲染一个对象
//绘制所有对象
var render = function () {
如果(bgReady) {
ctx.drawImage(bgImage,0,0);
}
if (heroReady) {
ctx.drawImage(heroImage,hero.x,hero . y);
}
if (monsterReady) {
ctx.drawImage(monsterImage,monster.x,monster . y);
}
//分数
ctx.fillStyle = "rgb(250,250,250)";
CTX . font = " 24px Helvetica ";
ctx.textAlign = " left
ctx.textBaseline = " top
CTX . fill text(" monster RS catched:"+monster scapped,32,32);
};
之前的工作很无聊,直到你把一切都画出来。首先当然是画背景。然后做同样的事情,画英雄和怪物。这个过程中的顺序是有讲究的,因为后面画的对象会覆盖前面的对象。
之后我们改变了Canvas的绘制上下文的样式,调用fillText来绘制文本,也就是记分板部分。这款游戏没有其他复杂的动画效果和打斗场面,画图部分就搞定了!
主循环函数
//游戏主功能
var main = function () {
var now = date . now();
var delta = now-then;
更新(delta/1000);
render();
那么=现在;
//立即调用main函数
requestAnimationFrame(main);
};
上面的主函数控制着整个游戏的流程。首先,获取当前时间来计算时差(自从最后一次调用main函数以来已经过去了多少毫秒)。得到修饰符后,除以1000(即1秒的毫秒数),并将其传入更新函数。最后调用render。
函数并节省时间。
关于游戏中画面循环更新的讨论,请参考猛攻!竞技场案例研究.
循环的进一步解释
RequestAnimationFrame的浏览器兼容性处理
var w =窗口;
requestAnimationFrame = w . requestAnimationFrame | | w . webkitrequestanimationframe | | w . msrequestanimationframe | | w . mozrequestanimationframe;
如果你没有完全理解上面的代码也没关系,我只是认为解释它总是很棒的。
为了循环调用main函数,之前游戏用的是setInterval。但是现在有了更好的方法,那就是requestAnimationFrame。使用新方法,你必须考虑浏览器的兼容性。上面的垫片就是这个原因,而且是原来保罗爱尔兰博客的简化版。
开始游戏!
//小子,我们开始游戏吧!
var then = date . now();
reset();
main();
终于完成了,这是这个游戏的最后一个代码。首先,设置一个初始时间变量,首先运行主函数。然后打电话
重置
函数开始新一轮的游戏(如果你还记得的话,函数是把英雄放在画面中间,把怪物放在随机的地方,让英雄可以抓到)。
至此,我相信您已经掌握了开发一个简单的H5游戏所需的基本技能。玩这个游戏或者下载代码自己研究:)