纯JS实现面向对象版贪吃蛇游戏

基本思路

1.开始游戏
 1-1.初始化游戏空间
 1-2.初始化蛇
 1-3.初始化食物
2.让蛇移动
 2-1.判断蛇头下一步位置
 2-2.检测碰撞
  2-2-1.碰撞食物?
  2-2-2.碰撞自己?
  2-2-3.碰撞边界?
  2-2-4.正常游走
3.添加键盘的事件监听

再来一张思维导图说明一下
在这里插入图片描述
下面代码实现:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			*{
				margin: 0;
			}
			td{
				padding: 10px;
			}
			td.snake{
				background: #000000;
			}
			td.food{
				background: #FF0000;
			}
		</style>
	</head>
	<body>
		<table id="game" border="1" cellspacing="0" cellpadding="0">
			
		</table>
	</body>
	<script type="text/javascript">
		function Game(){
			this.init();
		}
		Game.prototype = {
			//初始化游戏空间
			init() {
				this.tab = document.getElementById("game");
				for(let i = 0; i < 28; i++){
					let tr = document.createElement("tr");
					for (let j = 0; j < 62; j++) {
						let td = document.createElement("td");
						tr.appendChild(td);
					}
					this.tab.appendChild(tr);
				}
			},
			// 开始游戏:初始化游戏空间->初始化蛇->初始化食物
			start() {
				// this.init();
				//创建蛇
				this.snake = new Snake(this);
				this.snake.show();
				//初始化食物,在print中调用打印
				this.createFood();
				//让蛇移动
				this.snake.run();
				this.addControl();
			},
			//游戏空间内生成食物
			createFood() {
				if(this.food){
					this.tab.children[this.food.row].children[this.food.col].className = "";
				}
				let pos = {row : parseInt(Math.random()*28), col : parseInt(Math.random()*62)};
				while(this.test(pos) == Snake.Constant.NEXT_POSISTION_TYPE_SELF){
					pos = {row : parseInt(Math.random()*28), col : parseInt(Math.random()*62)};
				}
				this.tab.children[pos.row].children[pos.col].className = "food";
				this.food = pos;//记住食物的位置
				// console.log(pos);
			},
			//添加键盘监听,控制蛇的移动
			addControl() {
				// console.log("control")
				document.addEventListener("keydown",(e)=>{
					e = e || event;
					if(this.snake.stepcount > 0){
						switch(e.keyCode){
							case 37 : {//向左移动
								if(this.snake.dir != Snake.Constant.DIR_RIGHT){
									this.snake.dir = Snake.Constant.DIR_LEFT;
									this.snake.stepcount = 0;
								}
								break;
							}
							case 38 : {//上移
								if(this.snake.dir != Snake.Constant.DIR_DOWN){
									this.snake.dir = Snake.Constant.DIR_UP;
									this.snake.stepcount = 0;
								}
								break;
							}
							case 39 : {//右移
								if(this.snake.dir != Snake.Constant.DIR_LEFT){
									this.snake.dir = Snake.Constant.DIR_RIGHT;
									this.snake.stepcount = 0;
								}
								break;
							}
							case 40 : {//下移
								if(this.snake.dir != Snake.Constant.DIR_UP){
									this.snake.dir = Snake.Constant.DIR_DOWN;
									this.snake.stepcount = 0;
								}
								break;
							}
						}
					}
					
				})
			},
			//让蛇和食物在游戏空间内显示
			print() {
				this.clear();
				let pos = this.snake.position();//接收【snakeStep-3】返回的蛇身body
				pos.forEach((p)=>{//画出蛇
					this.tab.children[p.row].children[p.col].className = "snake";
				})
				if(this.food){
					this.tab.children[this.food.row].children[this.food.col].className = "food";
				}
			},
			clear() {//清空当前游戏空间
				for(let i=0; i<28; i++) {
					for(let j=0; j<62; j++) {
						this.tab.children[i].children[j].className = "";
					}
				}
			},
			test(pos) {//检测碰撞
				if(pos.row == 28 || pos.row < 0 || pos.col == 62 || pos.col < 0){
					return Snake.Constant.NEXT_POSISTION_TYPE_RANGE;
				}
				let td = this.tab.children[pos.row].children[pos.col];
				
				if(td.className == "food") return Snake.Constant.NEXT_POSISTION_TYPE_FOOD;
				if(td.className == "snake") return Snake.Constant.NEXT_POSISTION_TYPE_SELF;
				return Snake.Constant.NEXT_POSISTION_TYPE_NORMAL;
			},
			gameover() {
				alert("you have died");
			}
			
		}
		function Snake(game){
			this.game = game;
			this.init();
		}
		//蛇的相关变量
		Snake.Constant = {
			DIR_LEFT : Symbol(),
			DIR_RIGHT : Symbol(),
			DIR_UP : Symbol(),
			DIR_DOWN : Symbol(),
			NEXT_POSISTION_TYPE_FOOD : Symbol(),//检测碰撞点是食物
			NEXT_POSISTION_TYPE_RANGE : Symbol(),//检测碰撞点是边界
			NEXT_POSISTION_TYPE_SELF : Symbol(),//检测碰撞点是自己身体
			NEXT_POSISTION_TYPE_NORMAL : Symbol()//检测正常游走无碰撞
		}
		Snake.prototype = {
			//初始化蛇
			init() {
				this.body = [ { row : parseInt(Math.random()*28), col : parseInt(Math.random()*62) } ];//用数组存储蛇身的每一部分
				this.dir = Snake.Constant.DIR_RIGHT;//初始活动方向
				this.stepcount = 1;//记录步数
				this.speed = 400;//游走速度
			},
			//画出蛇
			show() {
				this.game.print();
			},
			// 返回蛇身给game使用
			position() {
				return this.body;
			},
			//让蛇移动,判断蛇头的下一位置
			run() {
				console.log("run")
				let that = this;
				let timer = setInterval(function(){
					//判断蛇头下一个位置
					switch(that.dir){
						case Snake.Constant.DIR_LEFT : {
							that.next = {
								row : that.body[0].row,
								col : that.body[0].col-1,
							}
							break;
						}
						case Snake.Constant.DIR_RIGHT : {
							that.next = {
								row : that.body[0].row,
								col : that.body[0].col+1,
							}
							break;
						}
						case Snake.Constant.DIR_UP : {
							that.next = {
								row : that.body[0].row-1,
								col : that.body[0].col,
							}
							break;
						}
						case Snake.Constant.DIR_DOWN : {
							that.next = {
								row : that.body[0].row+1,
								col : that.body[0].col,
							}
							break;
						}
					}
					// that.nextStep();
					//走的过程检测碰撞
					 let res = that.game.test(that.next);
					 switch(res){
						 case Snake.Constant.NEXT_POSISTION_TYPE_FOOD:{
							 that.eat();
							 that.stepcount++;
							 break;
						 }
						 case Snake.Constant.NEXT_POSISTION_TYPE_RANGE:{
							 that.stop();
							 that.game.gameover();
							 break;
						 }
						 case Snake.Constant.NEXT_POSISTION_TYPE_SELF:{
							 that.stop();
							 that.game.gameover();
							 break;
						 }
						 case Snake.Constant.NEXT_POSISTION_TYPE_NORMAL:{
							 that.nextStep();
							 that.stepcount++;
							 break;
						 }
					 }
				},that.speed);
			},
			nextStep() {//下一步
				this.body.pop();
				this.body.unshift(this.next);
				this.game.print();
			},
			eat() {//吃掉食物
				this.body.unshift(this.next);
				this.game.createFood();
				this.game.print();
			},
			stop() {//碰撞边界或自己,死亡,关闭定时器
				clearInterval(this.timer);
			}
		}
		new Game().start();
	</script>
</html>

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值