前端基础学习之js-贪吃蛇游戏(面向对象思维)

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<style>
		.map{
			width: 800px;
			height: 600px;
			background-color: #ccc;
			position: relative;
		}
	</style>
</head>
<body>
<!-- 地图初始化 -->
<div class="map"></div>
<script>
// //函数的自调用1
// (function () {
// 	console.log("yoyoyo");
// })();
// //函数的自调用2
// (function () {
// 	console.log("哟,我是第二个")
// }());

// (function () {
// 	function Random() {
		
// 	}
// 	Random.prototype.getRandom=function (min,max) {
// 		return Math.floor(Math.random()*(max-min))+min;
// 	}
// 	window.Random=new Random();
	
// }())
// console.log("==============随机x坐标:");
// console.log(Random.getRandom(0,40));
// 函数的自调用---食物小方块的函数自调用
(function () {
	// 声明一个存放食物的数组,以备后面删除食物
	let elements=[];

	//创建一个食物的构造函数
	//食物有哪些特征和行为呢
	//特征/属性:宽、高、背景色、横坐标、纵坐标
	function Food(width,height,color,x,y) {
		this.width=width || 20;
		this.height=height || 20;
		this.color=color || "green";
		this.x=x || 0;
		this.y=y || 0;
	}

	//食物有哪些行为
	//行为/方法:可能需要共享,因此将这些方法放在构造函数的原型对象中实现共享,节省内存
	//1.需要初始化的方法,否则无法在地图页面中显示
	//因为是需要在地图中显示,因此需要参数map地图
	Food.prototype.init=function (map) {
		//在初始化之前先删除原来的
		remove();
		let dvObj=document.createElement("div");

		dvObj.style.width=this.width+"px";
		dvObj.style.height=this.height+"px";
		dvObj.style.backgroundColor=this.color;

		//食物需要随机动态显示,因此是脱标的
		dvObj.style.position="absolute";
		//xy的随机获取,可以用上一个随机构造函数
		//也可以用下面这种============获取坐标刻度==========================再乘以每一个刻度坐标对应的宽度=====
		// dvObj.style.left=parseInt(Math.random()*(map.offsetWidth/this.width))*this.width+"px";
		// dvObj.style.top=parseInt(Math.random()*(map.offsetHeight/this.height))*this.height+"px";
		this.x=parseInt(Math.random()*(map.offsetWidth/this.width))*this.width;
		this.y=parseInt(Math.random()*(map.offsetHeight/this.height))*this.height;
		dvObj.style.left=this.x+"px";
		dvObj.style.top=this.y+"px";

		map.appendChild(dvObj);
		elements.push(dvObj);
	}


	//创建一个私有函数 --删除小方块食物的功能
	//此时就需要用到elements数组--即通过里面的元素找到父级元素来删除子元素
	function remove() {
		for(let i=0;i<elements.length;i++){
			let element=elements[i];
			element.parentElement.removeChild(element);
			//删除数组中的这个元素
			elements.splice(i,1);
		}
	}

	//这个构造函数在自调用函数内部,因为如果外部想要调用这个构造函数,需要用全局变量window
	window.Food=Food;

}());


//小蛇的自调用函数
(function () {
	//创建一个小蛇的元素数组
	let elements=[];
	//创建小蛇的构造函数
	//把初始化的小蛇分成三个小方块
	//第一个方块是蛇头,后面俩个是蛇的身体部分
	//width和height是每个小方块的宽高,因为都是等宽等高
	function Snake(width,height,direction) {
		this.width=width || 20;
		this.height=height || 20;
		this.snakeBody=[
			{x:3,y:2,color:"red"},
			{x:2,y:2,color:"orange"},
			{x:1,y:2,color:"orange"},
		];
		this.direction=direction || "right";
	}
	//给小蛇初始化方法
	//因为需要在地图中显示,因此需要传入地图参数
	Snake.prototype.init=function (map) {
		remove();
		//遍历小蛇的身体来创建每一块的div
		for(let i=0;i<this.snakeBody.length;i++){
			let snakeObj=this.snakeBody[i];
			let divObj=document.createElement("div");
			divObj.style.width=this.width+"px";
			divObj.style.height=this.height+"px";
			divObj.style.backgroundColor=snakeObj.color;
			divObj.style.left=snakeObj.x * this.width+"px";
			divObj.style.top=snakeObj.y * this.height+"px";
			divObj.style.position="absolute";
			map.appendChild(divObj);

			//方向
			//push进数组中
			elements.push(divObj);
		}
	};

	Snake.prototype.move=function (food,map) {
		// 移动小蛇
		// 小蛇的身体 和蛇头区分开
		// 身体部分 移动都是后面一个拿前一个的坐标轴
		let i=this.snakeBody.length-1;
		for(;i>0;i--){
			this.snakeBody[i].x=this.snakeBody[i-1].x;
			this.snakeBody[i].y=this.snakeBody[i-1].y;
		}
		//头部-区分方向
		switch(this.direction){
			case 'left':
			   this.snakeBody[0].x-=1;
			   break;
			case 'right':
			    this.snakeBody[0].x+=1;
			    break;
			case 'top':
			    this.snakeBody[0].y-=1;
			    break;
			case 'bottom':
			   this.snakeBody[0].y+=1;
			    break;
		}

		//吃到食物时候的处理
		//即判定当前蛇头的坐标和食物的坐标是否一直
		let headX=this.snakeBody[0].x*this.width;
		let headY=this.snakeBody[0].y*this.height;
		console.log(food.x+"======="+food.width);
		console.log(food.y+"======="+food.height);
		if(headX == food.x &&  headY == food.y){
			//代表吃到食物了
			//此时将蛇尾复制一份给蛇body,然后重新初始化食物
			let lastBd=this.snakeBody[this.snakeBody.length-1];
			this.snakeBody.push({
				x:lastBd.x,
				y:lastBd.y,
				color:lastBd.color
			})
			food.init(map);
		}
	}

	//小蛇元素删除方法
	function remove() {
		let i=elements.length-1;
		//从身体最末尾开始删除
		for(;i>=0;i--){
			let ele=elements[i];
			ele.parentElement.removeChild(ele);
			elements.splice(i,1)
		}
	}

	//把snake构造函数暴露给window
	window.Snake=Snake;
}());

//游戏的自调用函数
(function () {
	//创建构造函数
	let _this=null;
	function Game(map) {
		this.food=new Food();
		this.snake=new Snake();
		this.map=map;
		_this=this;
	}
	Game.prototype.init=function () {
		this.food.init(this.map);
		this.snake.init(this.map);
		//在这里调用run方法实现小蛇自动跑
		this.run();
		//调用绑定键盘事件
		this.bindKey();
		// setInterval(function () {
		// 	_this.snake.move();
		// 	_this.snake.init(_this.map);
		// },150)
	};

	Game.prototype.run=function () {
		let timerId=setInterval(function () {
			//调用bind 把that赋值给当前的this
			this.snake.move(this.food,this.map);
			this.snake.init(this.map);

			let maxX=this.map.offsetWidth/this.snake.width;
			let maxY=this.map.offsetHeight/this.snake.height;
			let snakeObj=this.snake.snakeBody[0];
			if(snakeObj.x<0 || snakeObj.x>=maxX){
				alert("you are lose");
				clearInterval(timerId);
			}
			if(snakeObj.y<0 || snakeObj.y>=maxY){
				alert("you are lose");
				clearInterval(timerId);
			}

		}.bind(_this),150)
	};

	Game.prototype.bindKey=function () {
		// 绑定键盘事件
		document.addEventListener("keydown",function (e) {
			switch(e.keyCode){
				case 37 :
					this.snake.direction="left";
					break;
				case 38 :
					this.snake.direction="top";
					break;
				case 39 :
					this.snake.direction="right";
					break;
				case 40 :
					this.snake.direction="bottom";
					break;
			}
		}.bind(_this),false)
	}


	window.Game=Game;
}())
	let gm=new Game(document.querySelector(".map"));
	gm.init();
	//如下所写不如再封装一个游戏的对象,在游戏对象中调用food和snake,这样代码更加简炼如上
	//调用Food构造函数
	// let fd=new Food();
	// fd.init(document.querySelector(".map"));
	// // fd.init(document.querySelector(".map"));

	// //初始化snake
	// let snake=new Snake();
	// snake.init(document.querySelector(".map"));
	// // snake.move();
	// // snake.init(document.querySelector(".map"));
	// // snake.move();
	// // snake.init(document.querySelector(".map"));
	// // snake.move();
	// // snake.init(document.querySelector(".map"));
	// setInterval(function () {
	// 	snake.move();
	// 	snake.init(document.querySelector(".map"));
	// },150)

	//测试一下这个fd有没有正常实例化
	// console.log(fd.width+"====="+fd.x);//ok

</script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值