前段时间BrowserQuest激起了我对html5的乐趣,接下来记下一个小型html5躲避游戏的实现。
先上图
游戏很简单,键盘控制人物上下左右移动,躲开怪物,时间越长越牛x。
主要是两部分组成:一部分就是人物、地图的结构搭建,另一部分就是让英雄、怪物相应地动起来。
HTML5写游戏和传统的游戏思路完全一样,同样也是不停刷新屏幕,游戏实际上也就是图片的适时摆放问题,HTML5无非就只用到了一个canvas(画布)的性质用来摆放图片。
Step 1 做好准备
新建一个html文件,命名为index.html,用作游戏的容器。代码如下:
- <html>
-
<head>
-
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-
<title>html5 game</title>
-
</head>
-
<body>
-
<h1>html5 game</h1>
-
<script type="text/javascript" src="move.js"></script>
-
</body>
-
</html>
ps:script的引用最好放在body里放在body会有问题。
再新建个文件,move.js
- var canvas = document.createElement("canvas"); //创建元素canvas,即我们要用的画布
-
var ctx = canvas.getContext("2d");//说明我们要用的画布是2d,因为canvas也有WebGL支持3d
-
canvas.width = 512;//设置画布的长宽
-
canvas.height = 480;
- document.body.appendChild(canvas);//前面基本信息都设置好了之后,将这个元素添加到body标签下。
这样画布就算是搭建好了。
顺带在下面加几个和图片有关的函数。
- var bgReady = false;
-
var bgImage = new Image();
-
bgImage.src = "move/background.png";
-
bgImage.onload = function(){
-
bgReady = true;
- }
-
-
var heroReady = false;
-
var heroImage = new Image();
-
heroImage.src = "move/hero.png";
-
heroImage.onload = function(){
-
heroReady = true;
- }
-
-
var monsterReady = false;
-
var monsterImage = new Image();
-
monsterImage.src = "move/monster.png";
-
monsterImage.onload = function(){
-
monsterReady = true;
- }
这个游戏用了三张图片,依次为背景、英雄、怪物。这段代码很容易理解,为了不在图片没有加载完成的时候就draw图片。
Step 2 定义原型
接下来定义一下英雄的原型。
- var hero = {
- speed: 256,
- x: canvas.width/2,
- y: canvas.height/2
- }
这个原型也很好理解,每秒钟英雄可以移动256个像素,英雄初始的位置为画布中央(x,y分别为坐标)。
接下来轮到怪物了。: )
- function monster() {
-
this.x = Math.random() * canvas.width;//初始为止随机
-
this.y = Math.random() * canvas.height;
-
this.speed = 100;
-
this.xDirection = 1;//默认移动方向为x轴正方向(以左上角为零点,下方和右方为正)
-
this.yDirection = 1;//同样也为y轴正方向
-
this.move = function (modifier) {//移动函数
- this.x += this.xDirection * this.speed * modifier;
- this.y += this.yDirection * this.speed * modifier;
-
if (this.x >= canvas.width - 32)//碰撞返回部分
- {
-
this.x = canvas.width - 32;
-
this.xDirection = -1;
-
}else if (this.x <= 0)
- {
-
this.x = 0;
-
this.xDirection = 1;
-
}else if (this.y >= canvas.height - 32)
- {
-
this.y = canvas.height - 32;
-
this.yDirection = -1;
-
}else if (this.y <= 0)
- {
-
this.y = 0;
-
this.yDirection = 1;
- }
- };
- }
怪物比英雄的定义要复杂得多。首先,怪物每隔五秒会增加一个(为增加难度),故不能单纯创建一个数组,而是需要一个类,再用类创建怪物对象。js当中只有类的半实现,具体使用function来创建。然后,怪物需要有撞墙返回的性质。
怪物的速度比英雄略慢,为100像素/秒。默认坐标在画布当中随机。怪物以45度移动。xDirection,yDirection合起来表示左上、左下、右上、右下4个方向。然后monster这个类有个move的动作,modifier表示两次刷新的时间间隔,可以计算出经过时间间隔后怪物的坐标。下面4个if函数用来判断,是否超越边界,超越则马上转向,以实现碰撞的效果。
- var monsterSum = 0;
-
var monsterList = new Array();
- monsterList[monsterSum] = new monster();
前面用var已经创建了英雄的实例,但是monster我们只建立了类而已,接下来要实例化。monsterSum表示怪物的数量,为方便,按照c的习惯,从0开始技术,即0表示有一个怪物。monsterList用来表示一个存怪物对象的数组,然后顺带新建一个怪物。
Step 3 游戏动起来!
先添加一个事件来接收键盘的动作,上下左右用对应的ascii码。因为游戏并不是摁一下方向键,就移动一段距离。而是,判断一个时间间隔内的动作(最后的动作,中间有可能会变化,故用数组保存最后结果)。
- var keysDown = {};
- addEventListener("keydown", function (e) {
- keysDown[e.keyCode] = true;//如果有"keydown"这个动作,即摁下某键,就会存进keysDown数组
- }, false);
- addEventListener("keyup", function (e) {
- delete keysDown[e.keyCode];
- });
下面上主函数
- var main = function () {
-
var now = Date.now();
-
var delta = now - then;
- Move(delta / 1000);//每次间隔时间根本不是1ms,比1ms要大得多
- Draw();
- Check();
-
then = now;
- }
main函数就是主函数,就是一个刷新所执行的函数。now、then两个变量记录两次刷新的时间间隔,这个时间间隔并不是固定的,一般为几百毫秒。delta 是两者之差,单位为毫秒。下面依次解释各个函数:Move()用来计算英雄和怪物的新位置。Draw()用来画背景、人物、文字。Check()用来检查,怪物和英雄是否相撞。
Move():
- var Move = function (modifier) {
- if (38 in keysDown) {
-
hero.y -= hero.speed * modifier;
- }
- if (40 in keysDown) {
- hero.y += hero.speed * modifier;
- }
- if (37 in keysDown) {
-
hero.x -= hero.speed * modifier;
- }
- if (39 in keysDown) {
- hero.x += hero.speed * modifier;
- }
-
if (hero.x >= canvas.width - 32) {
-
hero.x = 0;
-
}else if (hero.x <= 0) {
-
hero.x = canvas.width - 32;
- }
-
if (hero.y >= canvas.height - 32) {
-
hero.y = 0;
-
}else if (hero.y <= 0) {
-
hero.y = canvas.height - 32;
- }
-
for (var i = 0; i <= monsterSum; i++) {
- monsterList[i].move(modifier);
- }
- }
这里很好理解,判断这段时间间隔英雄的动作。算出新位置后,判断英雄是否跑出了画布,跑出了就从另一头出来(感谢 @昭曈 的创意)。接下来依次调用各个怪物的move函数,计算他们的新位置。
Draw():
- var Draw = function () {
- if (bgReady) {
- ctx.drawImage(bgImage, 0 ,0);
- }
- if (heroReady) {
- ctx.drawImage(heroImage, hero.x, hero.y);
- }
- if (monsterReady) {
-
for (var i = 0; i <= monsterSum; i++)
- ctx.drawImage(monsterImage, monsterList[i].x, monsterList[i].y);
- }
-
ctx.fillStyle = "rgb(250, 250, 250)";
-
ctx.font = "24px Helvetica";
-
ctx.textAlign = "left";
-
ctx.textBaseline = "top";
-
last = Date.now() - start;
- ctx.fillText(last/1000, 32, canvas.height - 64);
- }
前三个函数类似,就是如果准备好了图片就画东西上去(前面的三个ready函数派上了用场)。下面先定义了文字的style,然后计算出时间间隔last,然后画上去。
Check():
- var Check = function () {
- if (monsterSum != Math.floor(last / 5000)){//如果时间经过5秒就增加一个怪兽实例
- monsterSum ++;
- monsterList[monsterSum] = new monster();
- }
-
for (var i = 0; i <= monsterSum; i++) {
- if (
-
(monsterList[i].x - 32) <= hero.x
-
&& hero.x <= (monsterList[i].x + 32)
-
&& (monsterList[i].y - 32) <= hero.y
-
&& hero.y <= (monsterList[i].y + 32)
- ) {
-
end = Date.now();
- alert("你坚持了" + (end - start)/1000 + "秒");
- End();
- }
- }
- }
第一步是 如果经过5秒就增加一个怪兽,然后下面一个个判断怪兽与英雄是否接触。(这里用的是矩形,@小樟 说可以用圆心,感兴趣的可以试试: ) )
大家注意到了下面用到了一个end函数。下面补充,如果不停止一直刷新就浏览器就一直动了,故要有个结束函数。
End():
- var End = function () {
- if (bgReady) {
- ctx.drawImage(bgImage, 0 ,0); //留住背景
- }
- window.clearInterval(timer);
- return;
- }
用到的clearInterval()稍后会说到。
Step 4 程序入口
- var then = Date.now();
-
var start = then;
-
timer = setInterval(main, 1);
定义了初始的then和start,接下里用了setInterval(),意为每隔1ms就执行一次main函数。1ms是虚指,就是立即执行的意思。要想停止就用前面的clearInterval()函数。
到这里为止一个完整的游戏就写好了~ : )
后来 @志谦 实践出了一个bug,就是窗口如果最小化后,会一直计时,但不会被撞。问题在于高级的浏览器(当然没在说IE : ) ),默认如果最小化后,会终止interval、timeout这类函数的执行,以节约资源。但我们计时的方法是结束时间减去开始时间,所以就造成这个刷分的bug。感谢 @小樟 提供了main函数递归,全局变量表示是否停止的办法。
哦,第一次就那么没了~
源码下载地址:html5game
原文链接:http://billyellow.com/?p=10
分享到:
相关推荐
html5 canvas躲避小游戏是男人就撑过20秒躲避游戏源码
html5 canvas实现的疯狂赛车躲避游戏源码.zip
html5 canvas实现的圆点线条躲避小球类小游戏源码.zip
html5实现的飞机飞行躲避障碍物小游戏源码.zip
主要为大家详细介绍了JS实现躲避粒子小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
使用 js + html 实现的打飞机小游戏,玩家飞机和敌方飞机使用dom进行绘制,采用背景图填充div的方式生成飞机和子弹,在点击开始按钮后,页面上方会源源不断的出现飞机,并且攻击玩家飞机,玩家需要一边躲避敌机的...
它是一个 CSS,HTML 和 JS 的集合,它使用了最新的浏览器技术,给你的 Web 开发提供了时尚的版式; AJAX,创建交互式网页应用的网页开发技术。 前端游戏设计是游戏开发中至关重要的一部分,它涉及到游戏的外观、交互...
游戏界面设计:游戏界面采用了 HTML 和 CSS 进行设计,通过 ES6 语法实现了游戏逻辑和交互功能。游戏界面简洁明了,操作简单,适合各年龄段的玩家。 游戏画面绘制:Canvas 用于绘制游戏画面,包括敌机、子弹和背景等...
HTML5 Canvas元素:Canvas是HTML5中新增的一个元素,可以用于在网页上绘制图形和动画。在飞机大战游戏中,我们可以使用Canvas来绘制游戏中的飞机、敌机和子弹等元素。 JavaScript:JavaScript是一种强大的脚本语言,...
它是一个 CSS,HTML 和 JS 的集合,它使用了最新的浏览器技术,给你的 Web 开发提供了时尚的版式; AJAX,创建交互式网页应用的网页开发技术。 前端游戏设计是游戏开发中至关重要的一部分,它涉及到游戏的外观、交互...
之前也一直有用到事件,用到最多的就是onclick单击事件,还有填写表单信息时的用到的onfocus聚焦时间,和onblur事件,最近看到了onmousemove鼠标移动事件,觉得很神奇,就突然很想写一个小游戏,用到了setInterval...
这个是LibGDX实现的陨石撞地球游戏源码,为LibGDX评测写的DEMO,一个休闲小游戏,玩家操纵地球在黄道上躲避一脸坏笑的陨石,成功闪避100个陨石则胜利。我的DEMO用一个极便捷的方法实现了LibGDX项目中随意增加汉字而...
已经具备了游戏的基本要素,扩展一下可以变成一个不错的 HTML5 游戏。 演示效果如下: 完整代码如下: <!DOCTYPE html> <html class=" -webkit- js flexbox canvas canvastext webgl no-touch geolocation ...
使用箭头键(▲▼ :reverse_button: :play_button: ) 躲避穿越地图的传入机器人在游戏中使用空格键暂停/恢复精心制造: 用于2D图像渲染的画布逻辑JavaScript HTML和CSS的视觉结构追逐机器人: 我想让其中一个机器人...
这是一款基于HTML5+three.js实现的横穿马路小游戏源码。画面中有随机出现的各种街道以及在接到中穿行的车辆,画面下方的白色立方体可通过键盘的方向按键控制其前后左右移动,玩家通过方向键控制白色立方体移动、躲避...
该项目提供了面向对象的 Javascript 和 HTML5 Canvas 的经验。 相关的 Udacity 课程包括:项目目标: 游戏运行无错误(玩家不能离开屏幕,敌人穿过屏幕,敌对玩家碰撞重置游戏)。 游戏对象(玩家和敌人)是使用 ...