javascript 贪吃蛇(一)

snake怎么玩,这里就不做介绍,大家都应该知道。写这篇东西只是作为自己的一个学习测验跟记录用。因为俗话说的好,好记忆不如烂笔头,还是记下来比较好。
 
以前没有怎么用javascript写过小游戏。使用js的地方也仅仅是一些针对web页面的简单验证操作。知道网上有一大堆关于这个游戏的javascript实现,不过没怎么看,觉得还是用自己了解的javascript来写。这个过程虽然是在造轮子,但是对于一些概念的理解我想应该也是很有帮助的。起码可以直观的了解javascript面向对象的实现。
 
以下就是在写snake这个 js 实现的游戏中所想到的及最后的代码,存属自己学习使用,当然能有这样的想法也不是一下子就达到的,而是在不断的重构中才有了以下这些代码。其中涉及到的算法及代码如有雷同纯属巧合。

基本实现方式:

  • 用div+span+css的形式绘制一个20×20的方格画布canvas,并且对每一个span表示的格子有唯一的ID确定;
  • snake用canvas的方格表示;
  • snake的移动表示为当蛇头前进一格就改变snake head所在canvas格子的颜色,而改变snake tail所在canvas的颜色为背景色
  • snake身体是由符合规则所在每个span表示的格子ID所造成的一个数组。
  • 生成20×20画布的边缘即为snake运动边界;snake运动步长为一次一个格子。
  • snake水平运动head应为加减一;上线运动head为加减二十;
首先对于该游戏的目标定为:
  1. snake运动的画布canvas可以生成;
  2. 可以使用键盘方向键控制snake 的移动;
  3. 可以为snake生成食物food,不同级别的食物;
  4. 当snake获取food时,记分并改变snake的身体;
  5. 当snake撞墙或是吃到自己时重新生成游戏;
  6. 显示当前snake的得分及玩家的历史记录;
为了完成以上目标需要设立以下几个对象:
  1. 画布对象Canvas,用来标记蛇运动场所;
  2. 蛇对象Snake,用来显示一条蛇;
  3. 蛇的食物Food;
  4. 记分牌对象Scoreboard;
  5. 贪吃蛇游戏对象SnakeGame;
画布Canvas对象。
      首先画布如下形式:

      那么该对象具有属性为canvas所规定的四面墙,也就是snake运动范围的四个边界,以此定义为northWall(北)、eastWall(东)、southWall(南)、westWall(西);
      同时canvas对象应该具有两个方法,分别为:展示该画布的方法draw()及判断某快砖属于那面墙的方法whichWallForBrick(vBrick)。
    实现如下:
function Canvas() {
	this.northWall = new Array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
			16, 17, 18, 19);// 北
	this.eastWall = new Array(20, 40, 60, 80, 100, 120, 140, 160, 180, 200,
			220, 240, 260, 280, 300, 320, 340, 360, 380);// 东
	this.southWall = new Array(382, 383, 384, 385, 386, 387, 388, 389, 390,
			391, 392, 393, 394, 395, 396, 397, 398, 399);// 南
	this.westWall = new Array(21, 41, 61, 81, 101, 121, 141, 161, 181, 201,
			221, 241, 261, 281, 301, 321, 341, 361, 381);// 西
}
Canvas.prototype.whichWallForBrick = function(vBrick) {
	if (this.northWall.indexOf(vBrick) != -1) {
		return 'N';
	}
	if (this.southWall.indexOf(vBrick) != -1) {
		return 'S';
	}
	if (this.westWall.indexOf(vBrick) != -1) {
		return 'W';
	}
	if (this.eastWall.indexOf(vBrick) != -1) {
		return 'E';
	}
	return false;// 不属于任何一面墙
};
Canvas.prototype.draw = function() {
	var oDiv_canvas = document.getElementById("canvas");
	if (oDiv_canvas == null) {
		oDiv_canvas = createElement("div", "canvas", null);
	}
	var oFragment = document.createDocumentFragment();// 创建文档碎片
	for ( var i = 1; i <= 400; i++) {
		var oSpan = createElement("span", i, i);
		oFragment.appendChild(oSpan);
	}
	oDiv_canvas.appendChild(oFragment);
	document.body.appendChild(oDiv_canvas);
};
Snake对象:
      针对上图不难看出,定义一条snake需要制定该snake的head(图中绿色部分)及tail(图中灰色部分);snake的长度也就snake身体的所占span格子的个数.
      因此一条snake具有属性:head(蛇头)、tail(蛇尾)、body(身体)及direction(蛇的前进方向)
      snake应该具有的方法为:移动并且找到食物moveAndFindFood(oFood)、判断是否走出了canvas的方法isHitWall(oCanvas)以及在canvas上展示snake的方法draw()
实现如下:
function Snake(head, tail, direction) {
	this.head = head;// 头
	this.tail = tail;// 尾
	this.direction = direction;// 方向
	this.body = new Array(tail, head);// 按顺序依次存入蛇尾--蛇头
}
Snake.prototype.moveAndFindFood = function(oFood) {
	switch (this.direction) {
	case "up":
		this.head -= 20;// 蛇头朝北走20
		break;
	case "down":
		this.head += 20;// 蛇头朝南走20
		break;
	case "left":
		this.head -= 1;// 蛇头朝西走20
		break;
	case "right":
		this.head += 1;// 蛇头朝东走20
		break;
	default:
		break;
	}
	this.body.push(this.head);// 重新设则蛇头位
	if (oFood.iNo == this.head) {// 遇到食物
		oFood.bEat = true;// 食物已经被吃
	} else {
		this.body.shift();// 移除数组的第一个元素也就是蛇尾
		this.tail = this.body[0];// 将数组的第一个元素设置为蛇尾
	}
};
// 撞墙判断
Snake.prototype.isHitWall = function(oCanvas) {
	// 小于1或大于400为游戏地图块状区域编号;如果蛇的头部与身体上的其他区域有重复,则说明蛇将自己吃了
	if (this.head < 1 || this.head > 400 || this.body.sameItem(this.head) > 1) {
		return true;
	}
	// 蛇头当前位于画布的东边缘上并且蛇头后的位置[body.slice(-2,-1)取数组的倒数第二个元素]也位于画布的西边缘上,在游戏中是不运行的。定义为撞到西墙
	if (oCanvas.whichWallForBrick(this.head) == 'E'
			&& oCanvas.whichWallForBrick(this.body.slice(-2, -1)) == 'W') {
		return true;
	}
	// 蛇头当前位于画布的西边缘上并且蛇头后的位置[body.slice(-2,-1)取数组的倒数第二个元素]也位于画布的东边缘上,在游戏中是不运行的。定义为撞到东墙
	if (oCanvas.whichWallForBrick(this.head) == 'W'
			&& oCanvas.whichWallForBrick(this.body.slice(-2, -1)) == 'E') {
		return true;
	}
	return false;
};
Snake.prototype.draw = function() {
	for ( var i = 0; i < this.body.length; i++) {
		if (this.body[i] == this.head) {
			document.getElementById(this.body[i]).style.background = "green";
		} else if (this.body[i] == this.tail) {
			document.getElementById(this.body[i]).style.background = "gray";
		} else {
			document.getElementById(this.body[i]).style.background = "red";
		}
	}
};
Food对象:
     图中的黄色即为snake's food;
     Food对象很简单具有属性:iNo(食物位置编号)、iRank(食物等级)、bEat(是否被吃掉)及aColor(食物颜色);
     方法为:productionFoodForSnake(oSnake)(生产食物)
实现如下:
function Food() {
	this.iNo;
	this.iRank = 1;// 食物等级;分四个等级,从小到大0,1,2,3,4
	this.bEat = true;// 默认没有食物
	this.aColor = new Array("orange", "blue", "red", "#000000");
	if (typeof Food.__initialized == "undefined") {// 动态原型方法
		// 生产食物
		Food.prototype.productionFoodForSnake = function(oSnake) {
			this.iRank = RandomEventUtils.getIntRandomNumFromOneToN(4);
			do {
				this.iNo = RandomEventUtils.getIntRandomNumFromOneToN(20 * 20);
				// 当该随机数不属于snake's body时跳出循环
			} while (oSnake.body.indexOf(this.iNo) != -1);
			this.bEat = false;
			document.getElementById(this.iNo).style.background = this.aColor[this.iRank - 1];
		};
		// 清理剩余食物
		Food.__initialized = true;
	}
}
    至此,一些基本的准备工作就已经就绪了,下面我们将创建游戏对象,以便控制snake的移动及一些记分工作。javascript 贪吃蛇(二)

转载于:https://my.oschina.net/yeelee/blog/650914

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值