【HTML】【实践】使用Canvas制作网页小游戏

HTML5中新增了Canvas元素,这个元素非常好玩,使用Canvas,我们可以使用代码绘制出我们想要的图形,用代码绘图,光是想想就兴奋啊。

于是我在学习了Canvas的部分内容后,动手制作了一款小游戏,这也是本人第一次独立开发web项目,所以内行人看到细节肯定忍不住吐槽,希望大家批评指正,给出宝贵意见,我们共同进步。

一、游戏介绍:

这个游戏的界面非常简单,左边一块用Canvas绘制的画布,右边有4个按钮,左边的画布上有一个红色的方块和一个黑色的方块,红色的方块是我们操作的对象,它是一个1×1×2的长方体,现在它正立在画布上,将1×1的面朝向玩家,我们可以点击右侧的四个按钮操作这个长方体,让这个长方体在画布上滚动,根据用户的点击,这个长方体会将不同的面朝向玩家,而玩家的目标就是通过操作这个长方体将它插入到画布上黑色方块所代表的洞中,另外,如果玩家的操作会导致长方体的任何部位悬空,那操作是无法执行的,会提示“无法前进”!目前这个游戏的功能比较简单,难度也不大,如果经过后期修改完善,增加更多无法前进的区域,这个游戏是很有挑战性的。

    按下向下按钮,长方体向下滚动,原来的图案变成了这样:

如果此时按左键,会弹出错误警告:

按下右键,也会导致长方体的部分悬空,所以也会弹出同样的警告

最终我们要将长方体完整无误地插入洞中,也就是大概做到这样:

这时,只要按下向上,就能将长方体插入洞中,完成目标:

下面来谈谈具体实现。

二、设计思路及代码实现

游戏的实现主要是利用了Csnvas元素的绘图方法,通过用户点击按钮,产生指令,将指令传递给特定的函数,通过函数判断长方体是否可以前进,将会产生怎样的结果,然后通过Canvas重绘图形。

1、首先,我们将游戏界面绘制出来,

<canvas id="map" style="border:3px solid;float:left" width="500px" height="500px">你的浏览器不支持canvas</canvas>
<!--按钮-->
<br />
<div id="control">
<div class="up"  onClick="oTangle.moveUp()"><img src="arrow_up_128px_1137748_easyicon.net.png" /></div>
<br />
<div class="left" onClick="oTangle.moveLeft()"><img src="arrow_left_128px_1137746_easyicon.net.png" /></div>
<div class="down" onClick="oTangle.moveDown()"><img src="arrow_down_128px_1137745_easyicon.net.png" /></div>
<div class="right" onClick="oTangle.moveRight()"><img src="arrow_right_128px_1137747_easyicon.net.png" /></div>

</div>

以上代码制作了界面的主体布局,包括一张画布,和包含4个作为按钮的div的控制区域。

然后为以上元素添加样式:

<style>
div#control {
	float:left;
	width:500px;
	height:500px;
	position:absolute;
	left:500px;
	top:0;
}
div#control div {
	width:100px;
	height:100px;
	border-radius:25px;
	text-align:center;
	padding : 0px;
	box-shadow:2px 2px 1px #CCC;
}
div.up {
position:absolute;
left:200px;
top:80px;
}
div.left {
position:absolute;
left:80px;
top:200px;
}
div.right {
position:absolute;
left:320px;
top:200px;
}
div.down {
position:absolute;
left:200px;
top:320px;
}
img {
opacity:0.2;
filter:alpha(opacity=40); 
}
img:hover
{
opacity:1.0;
filter:alpha(opacity=100);
}
</style>

然后,使用以下代码绘制地图和黑洞:

var oLines = document.getElementById("map").getContext("2d");

for(var i =0;i<4; i++)
{
oLines.moveTo(100+100*i,0);
oLines.lineTo(100+100*i,500);
oLines.stroke();
oLines.moveTo(0,100+100*i);
oLines.lineTo(500,100+100*i);
oLines.stroke();
}
oLines.save();
oLines.fillStyle="#000000";
oLines.fillRect(100,100,100,100);
oLines.restore();

将以上代码封装到一个map()函数中,用于以后调用

然后,绘制我们操作的长方体,初始状态下,长方体是立着的,代码如下:

var tangle = document.getElementById("map").getContext("2d");
tangle.fillStyle = "#FF00FF";
tangle.fillRect(0,0,100,100);

至此,我们绘制出了游戏所需要的游戏界面,下面我们通过代码实现游戏的操作

2、定义对象

我们可以定义一个对象来代表这个长方体,这个对象应该包含以下属性:

状态:表示长方体当前是直立、横躺还是竖躺的字符串变量。

坐标:表示长方体在画布上的位置(这里用长方形左上角的点)的Number类型变量。

长、宽、高:用于重绘时进行计算的数字常量。

对象还应包含表示向各个方向滚动的4个方法,与四个按钮的响应事件向对应

具体如下:

var oTangle = new Object;
oTangle.sErect = "erect";  /*长方体的状态*/
oTangle.x = 2;			/*当前坐标x*/
oTangle.y = 2;			/*当前坐标y*/
/*代表的显示在地图上的长方形的左上角的坐标*/
oTangle.length = 100;
oTangle.width = 100;
oTangle.height = 200;

oTangle.moveRight = function()/*长方体的4个方法*/
{
	move(oTangle.x,oTangle.y,oTangle.sErect,"right");
};
oTangle.moveLeft = function()
{
	move(oTangle.x,oTangle.y,oTangle.sErect,"left");
};
oTangle.moveUp = function()
{
	move(oTangle.x,oTangle.y,oTangle.sErect,"up");
};
oTangle.moveDown = function()
{
	move(oTangle.x,oTangle.y,oTangle.sErect,"down");
};

然后,我们要抽象化这张画布,方便长方体对象进行路径判定,这里可以使用一个数组表示:

var mapArray = new Array();
mapArray[0] = new Array(0,0,0,0,0,0,0,0,0);
mapArray[1] = new Array(0,0,0,0,0,0,0,0,0);
mapArray[2] = new Array(0,0,1,1,1,1,1,0,0);
mapArray[3] = new Array(0,0,1,1,1,1,1,0,0);
mapArray[4] = new Array(0,0,1,1,1,1,1,0,0);
mapArray[5] = new Array(0,0,1,1,1,1,1,0,0);
mapArray[6] = new Array(0,0,1,1,1,1,1,0,0);
mapArray[7] = new Array(0,0,0,0,0,0,0,0,0);
mapArray[8] = new Array(0,0,0,0,0,0,0,0,0);

在这里,除了画布本身的5×5个坐标,我还把外围2层也加入到数组中去了,这样是为了应对向外翻滚两格的情况,当然,也可以使用instanceof运算符,判断坐标是否为number类型,这样就只需要建立一个5×5的二维数组就可以了,如果翻滚导致坐标变成数组的length以外,将会返回Undefined,以此进行判定。

3、对象的方法——move()函数

我们创建一个函数,接受oTangle对象的属性作为参数,然后将参数传递到其他子程序中

function move(posiX,posiY,state,direction) {
if(state=="erect")
	{

		if(ifSuspend(posiX,posiY,"erect",direction))
		{

			draw(posiX,posiY,"erect",direction);
			map();

			posiX=oTangle.x;
			posiY=oTangle.y;

		}
		else
		{
			alert("无法前进!");
		}
	}
其他情况的判定...

在这个move()函数中,函数接受从对象的方法传递来的参数,调用一个判定前方是否为路径的函数,然后判断函数的返回值是否为true,即路径合法,如果路径合法,执行draw()函数和map()函数重绘图形,并让posiX、posiY与被修改的oTangle对象的坐标属性同步,如果路径不合法,则弹窗报错。根据长方体状态的不同,共有3种判定情况,这里只给出竖直情况的方法。

4、路径判定函数——ifSuspend()函数

此函数接受从move()函数传递过来的oTangle对象属性值,根据对象状态的不同使用其坐标(不是当前坐标,而是玩家点击操作后的坐标值)和表示地图的二维数组进行判定:

function ifSuspend(posiX2,posiY2,state2,direction2){

var arrX=posiX2,arrY=posiY2;	

	if(state2=="erect")
	{

		if(direction2=="left")
		{
			if(mapArray[arrX-2][arrY])
			{
				if((posiX2==4 && posiY2==3)||(posiX2==5 && posiY2==3))
				{
					return 0;
				}
				else
				{
					return 1;
				}
			}
			else
			{
				return 0;
			}
		}
		if(direction2=="right")
		{

			if(mapArray[arrX+2][arrY])
			{

				if((posiX2==1 && posiY2==3)||(posiX2==2 && posiY2==3))
				{
					return 0;
				}
				else
				{
					return 1;
				}
			}
			else
			{
				return 0;
			}
		}
		if(direction2=="up")
		{
			if(mapArray[arrX][arrY-2])
			{
				if((posiX2==3 && posiY2==4)||(posiX2==3 && posiY2==5))
				{
					return 0;
				}
				else
				{
					return 1;
				}
			}
			else
			{
				return 0;
			}
		}

		if(direction2=="down")
		{
			if(mapArray[arrX][arrY+2])
			{
				if((posiX2==3 && posiY2==2)||(posiX2==3 && posiY2==1))
				{
					return 0;
				}
				else
				{
					return 1;
				}
			}
			else
			{
				return 0;
			}
		}
	}
	其他判断情况。。。

在函数的开始,新建了2个变量,将传递来的参数的值赋值给它们,因为参与判定的是oTangle对象操作后的坐标(此时还未判定是否允许操作),而不是当前的坐标。

上面给出了竖直情况下的判定,竖直状态下,向左和向上滚动会导致长方形左上角的坐标发生2个单位的偏移,而向右和向下滚动则会产生1个单位的偏移。如图:

红色的点是当前坐标,其他四个点的是将因玩家操作导致变化的结果,黑点相对红点左移2个单位(arrX-2),黄点相对红点右移2个单位(arrX+2),绿点相对红点上移2个单位(arrY-2),紫点相对红点下移1个单位(arrY-1).

在横躺和竖躺的情况下,还要考虑插入黑洞的情况,如果操作将导致长方形的坐标等于黑洞的坐标,将退出判定,弹窗告诉玩家游戏结束。

5、重绘图形——draw()函数

draw()函数使用JavaScript代码绘制图形,这里要调用前面绘制的tangle图形对象。

首先调用save()方法保存当前状态,主要是避免下次绘图时改变原点的位置

然后调用clearRect()方法清除现在的图形,接受4个参数,表示要清除的图形的区域坐标,(会一并清除地图上的网格线,所以在上面的move()函数中再次调用了map(),事实上,在下面的代码中,在clear()方法后面紧接着调用map(),就不会出现游戏中网格线在长方体上的BUG了,不过,不要在意这些细节是不是?)

重绘的实现:首先,清除的区域是

((posiX4-2)*oTangle.width,(posiY4-2)*oTangle.width,oTangle.width,oTangle.length)

这个区域表示长方体当前的图形,posiX4-2是因为初始的坐标是(2,2)(如果是用instanceof来判定,就不用这样了,罪孽啊)

fillRect()方法重绘矩形,同样接受4个参数,表示描绘矩形的区域,不同的状态,不同的方法,作为参数的公式也不相同,这里只给出竖直状态下左滚情况下的公式。

然后,回到前一个save()方法的状态,避免绘图导致原点偏移。

最后,修改长方体对象当前的坐标,修改长方体对象当前的状态,滚动完成。

function draw(posiX3,posiY3,state3,direction3)
{
var posiX4=oTangle.x,posiY4=oTangle.y;
if(state3=="erect")
{
if(direction3=="left")
{
tangle.save();
tangle.clearRect((posiX4-2)*oTangle.width,(posiY4-2)*oTangle.width,oTangle.width,oTangle.length);
tangle.fillRect((posiX4-4)*oTangle.width,(posiY4-2)*oTangle.width,oTangle.height,oTangle.width);
tangle.restore();
oTangle.x-=2;
oTangle.sErect="cross";
}
其他判断情况。。。

使用以上代码,就实现了游戏流程,这个游戏也就完成了

三、学习心得

这个游戏功能(我实现的部分)很简单,流程也不复杂,主要是使用了Canvas的绘制矩形的功能,很好理解,可以改进的地方也非常多,包括BUG也不少,不过毕竟这只是一个小小的作业,还有很多东西要学,所以后续的开发智能搁浅了。。。。

时间: 2024-10-07 05:15:17

【HTML】【实践】使用Canvas制作网页小游戏的相关文章

使用AxureRP7.0制作经典小游戏"大家来找茬"

本案例是<网站蓝图AxureRP7.0从入门到精通视频教程>中的最后一节,适用于对Axure基础知识掌握比较熟练的同学:教程由axure原型库网站录制,转载请注明出处!相信很多刚接触Axure或者学习了一段时间但并没有深入的同学们,看到这个案例一定很惊讶,使用Axure竟然能做出如此逼真的交互效果!通过此案例也可以激发广大同学们学习Axure的热情和信心!试想一下,如果你有情侣的话,把你们珍藏的合影拿出来处理几张,做成大家来找茬的小游戏,不但锻炼了自己的技能,还能给对方一个惊喜,岂不是一举两得

翻转拼图网页小游戏制作

咱们学东西的时候,往往喜欢玩点有趣的,这次就参考别人的创意,做了一个小游戏,虽然在css和JavaScript上我都算是新手,不过辛苦一天还是还超哥和各位师兄的帮助下弄出来了,就把这次开发分享一下吧. 先上最终成品 http://luyishisi.github.io/test.html 在准备写这个之前至少要有html,css和JavaScript的知识,如果会jQuery最好. 首先贴上一开始想的开发规划: 逐步实现:1:点击按钮实现变色,2:点击按钮实现旁边按钮的变色3:实现变色的重复性,

【网时】网页小游戏为什么如此盛行

现在市面上各种游戏纵横,细心观察就会发现,几乎只要你打开一个网页,下方就会出现一些小广告,以一些不可描述的图片和夸大事实的文字来吸引网友的注意. 你可能会疑惑,那种靠博人眼球获得点击率的小广告真的赚得到钱吗?答案是肯定的,甚至比客户端游戏简单得多.一位做网页游戏的代理在交流心得时提到,网页游戏虽然设计比较低端,但有一个特点就是,只要用户迷上游戏之后就会无法自拔.所谓升级打怪爆装备,都是为了用户充值做铺垫,或为了爆装备而充值,或为了高等级充面子而充值,但不管是为了什么,只要用户开始充值,就是运营商

Qt 制作2048小游戏

相信大家都玩过2048把,下面是我用qt写得2048小游戏. 2048.pro HEADERS += Widget.h SOURCES += Widget.cpp main.cpp QT += widgets gui RESOURCES += ico.qrc RC_ICONS = 2048.ico widget.h #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QKeyEvent> #include &

极客学院前端实战开发 网页小游戏/网页布局/导航/标签页/语音识别

===============课程目录===============<实战开发教程>├<1 围住神经猫-HTML5实战游戏开发教程>│  ├1. 围住神经猫-游戏玩法.mp4│  ├2.围住神经猫-使用createjs.mp4│  ├3. 围住神经猫-绘制页面元素.mp4│  ├4.围住神经猫-添加监听事件.mp4│  ├5.围住神经猫-简单的逻辑实现游戏效果.mp4│  ├6. 围住神经猫-完整游戏效果实现.mp4│  └<source>├<10 回到顶部功能实

jquery制作打地鼠小游戏

效果图: 素材: bg.jpg hole.pngmole.png <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scal

MFC制作打地鼠小游戏

游戏说明如下: 打中老鼠加一分,一局时间为60秒,上面有个进度条和文字进行计时. 难度可以自己选择,难度低是老鼠每一秒出现一次,难度中是老鼠每0.6秒出现一次,难度高是老鼠每0.2秒出现一次. 效果图(背景.美化可以自己去改进): 代码如下: 1. // y10Dlg.h : header file// #if !defined(AFX_Y10DLG_H__8D9895CE_53DF_4FA0_823C_1B5C468F422E__INCLUDED_)#define AFX_Y10DLG_H__

[从零开始]使用Vue.js制作俄罗斯方块小游戏(四)ui实现

STEP ONE:设计游戏规则. 作为一个合格的游戏,我们肯定要设计一个合理的游戏规则. 以下是我的方案: 得分=已固定的方块数*1+已消除的行数*50 方块掉落速度=1+已消除的行数*0.05 方块下落的时间间隔=500/方块掉落速度 ok! STEP TWO:ui实现. 这一步我们放在Index.vue里实现. // 当一个方块固定 squareOk () { this.data.cur_points++ if (this.data.cur_points > this.data.max_po

[从零开始]使用Vue.js制作俄罗斯方块小游戏(一)创建项目

一.创建项目 开发环境:win10 开发的前置操作:安装npm. 首先在命令行里进入一个文件夹A,然后输入vue init webpack tetris tetris是文件夹的名字,可以随便定义,但不能有大写字母 接下来全部按回车就好. 接下来,我们进入tetris,并运行 cd tetris npm run dev 就会出现这样一个界面. 然后我们根据提示打开浏览器,在地址栏输入http://localhost:8080 就会出现如下界面. 这样我们的项目就搭建好了! 原文地址:https:/