Canvas实现贪吃蛇小游戏(面向对象)

Canvas实现贪吃蛇小游戏

我们常常在网页上制作的小游戏都是通过Canvas实现的,虽然我们也可以使用DOM来实现,但是这样会更加的节约资源。

我们书写这个小游戏的目的主要是为了适应js中关于面向对象的设计模式,由于js的面向对象有些特殊所以更加应该引起我们的注意。

其实网上已经有很多关于贪吃蛇这样小游戏的教学,每个人都有每个人的实现方法,也都有所不同,在这其中最需要学习的是面向对象的思维方式,那么下面我直接讲代码粘贴在下面,代码之中有很多注解能够帮助大家理解一些细节的地方。

简单的讲一下代码的思路:因为是对canvas画图小游戏的实现所以我们将最大最外层的构造函数取名为Draw,Drew中接收一个参数是dom的canvas元素,Drew包含两个私有方法是check和main,check主要用于判断用于运行的浏览器是否支持Canvas,main里面主要用于调用其他所有的方法。

我们创建一个用于画图的一个构造函数Rect,并给Rect设置一个公有方法drew用于绘画,创建另一个构造函数snack创建对象画出蛇头和蛇身,创建一个randFood用于随机创建出食物,当然还有很多的关于蛇对象snake的很多公有方法,例如是否吃到食物和方向等。

其实下面的方法还有很多没有完善的地方,有些方法没有加入到构造函数里面,还有一些缺陷,大家借鉴的时候可以稍作修改。

像这样这么多函数放在一起是非常难看的,如果使用模块化以后,那么面向对象的代码就会变的更加完善,更加的容易维护和修改。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			canvas{
				margin: 10px auto;
				display: block;
				box-shadow: 0 0 10px #000;
			}
		</style>
		<script src="http://cdn.bootcss.com/jquery/3.4.0/jquery.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<canvas id="canvas" width="800" height="600"></canvas>
	</body>
	<script type="text/javascript">
		$(function(){
			/**
			 * [Draw description] canvas 绘图的构造函数
			 * @param {[type]} canvas [description]
			 * */
		function Draw(canvas){ //绘图的构造函数
			this.canvas = canvas;
			/**
			 * [check description]检测浏览器是否支持canvas
			 * @return bool false 表示不支持 true 表示支持
			 * */
			this.check = function(){//检测浏览器是否支持canvas
				if(!this.canvas.getContext){
					return false;//返回false
				}
				else{
					return true;//返回true
				}
			}
			/**
			 * [main description]canvas 绘图的主函数
			 * @return {[type]}[description]
			 * */
			this.main = function(){//检测兼容性
				if(!this.check()){
					console.log('浏览器不支持');//显示浏览器不支持
					return false	//返回false
				}
				Draw.prototype.xt = this.canvas.getContext('2d');//用2维样式显示
				//......
				//绘制蛇的初始图形
				var snake = new Snake(this);//创建蛇
				snake.draw();//画出一条蛇
				//随机产生一个食物
				var food = randFood(snake);
				food.draw();
				//做一个动画的定时器,
				Draw.prototype.timer = setInterval(function(){
					//清除旧的图像
					Draw.prototype.xt.clearRect(0,0,this.canvas.width,this.canvas.height);
					//改变蛇 的位置
					if(!snake.move()){
						clearInterval(Draw.prototype.timer);
						alert('游戏结束');
					};
					//重新绘制图形
					snake.draw();
					food.draw();
					if(isRectHit(food,snake.head)){
						//判断当前食物有没有与蛇头发生碰撞
						Snake.prototype.isEatFood = true;
						//重新随机产生食物
						food = randFood(snake);
					}
				},150)
			}
		}
			
		function Rect(x,y,width,height,color){//创建
			this.x = x;//x 矩形的起始点x坐标
			this.y = y;//y 矩形的起始点y坐标
			this.width = width;//width 矩形的宽
			this.height = height;//height 矩形的高
			this.color = color;//color 矩形的颜色
		}
		Rect.prototype.draw = function(){//创造一些公有方法  画矩形
			Draw.prototype.xt.beginPath();//画笔开始
			Draw.prototype.xt.fillStyle = this.color;//填充矩形的颜色
			Draw.prototype.xt.fillRect(this.x,this.y,this.width,this.height);//用画笔填充矩形
			Draw.prototype.xt.strokeRect(this.x,this.y,this.width,this.height);	//用画笔画出矩形的边框
		}
		
		
		function Snake(obj){//创建蛇的对象
		
			this.head = new Rect(obj.canvas.width/2,obj.canvas.height/2+20,40,40,'red');	//画蛇头
			//蛇身
			this.body = [];//表示多个身体
			var x = this.head.x - 40;//身体的x坐标
			var y = this.head.y;//身体的y坐标
			
			for(var i =0;i<3;i++){//循环创建身体
				var rect = new Rect(x,y,40,40,'gray');//在身体坐标处创建宽高为40的方块
				this.body.push(rect);//把创建出来的方块放入身体
				x-=40;//新创建的方块的横坐标往后移动40
			}
			
		}
		//添加蛇默认的移动方向是向右的,公有的属性,任何的地方能够修改访问,
		//并且和实例共享
		Snake.prototype.direction = 1;
		//定义一个是否吃到食物的标记
		Snake.prototype.isEatFood = false;
		Snake.prototype.draw = function(){//画蛇的方法
			
			this.head.draw();//画蛇头
			
			for(var i = 0;i<this.body.length;i++){//利用循环画蛇的身体
				this.body[i].draw();//在当前身体的后面再画一个
			}
				}
		Snake.prototype.move = function(){//控制移动
		//检测蛇头与蛇身
		for(item in this.body){
			if(isRectHit(this.head,this.body[item])){
				return false;
			}
		}
		//蛇头与墙的碰撞检测
		if(this.head.x < 40|| this.head.y < 40 || this.head.x > $('#canvas')[0].width-40-40 || this.head.y > $('#canvas')[0].height-40-40){
			return false;
		}
		//给身体加一个头
			var rect = new Rect(this.head.x,this.head.y,40,40,'gray');
			//添加到身体开始的地方
			this.body.splice(0,0,rect);
			//去掉一个尾巴,
			if(Snake.prototype.isEatFood){
				Snake.prototype.isEatFood = false;
				//重新随机产生食物	
			}else{
				this.body.pop();
			}
			
			switch(this.direction){
				case 0:
					this.head.y -=40; 
					break;
				case 1:
					this.head.x +=40; 
					break;
				case 2:
					this.head.y +=40; 
					break;
				case 3:
					this.head.x -=40; 	
					break;
			}
			return true;
			}
			//添加键盘监听
			$(window).keydown(function(e){
				switch(e.keyCode){
					case 37://如果当前的方向是向右的不能改为向左
					if(Snake.prototype.direction ==1){
						return;
					}
					Snake.prototype.direction = 3;
						break;
					case 38://如果当前的方向是向下的不能改为向上
					if(Snake.prototype.direction ==2){
						return;
					}
					Snake.prototype.direction = 0;
						break;
					case 39://如果当前的方向是向左的不能改为向右
					if(Snake.prototype.direction ==3){
						return;
					}
					Snake.prototype.direction = 1;
						break;
					case 40://如果当前的方向是向上的不能改为向下
					if(Snake.prototype.direction ==0){
						return;
					}
					Snake.prototype.direction = 2;
						break;
				}
			})
		//随机产生食物的方法
		function randFood(snake){
			//是否在蛇身上
			isInSnake = true;
			//产生两个位置,x,y
			while(isInSnake){
				var x = getRandPosition(0,($('#canvas')[0].width-40)/40)*40;
				var y = getRandPosition(0,($('#canvas')[0].height-40)/40)*40;
				//创建食物矩形
				var food = new Rect(x,y,40,40,'green');
				isInSnake = false;
				//判断这个位置是否在蛇上
					
					//是否是蛇头
					if(isRectHit(food,snake.head)){
						isInSnake =true;
						continue;
					}
					// 是否是蛇身
					for(var i = 0;i<snake.body.length;i++){
							if(isRectHit(food,snake.body[i])){
								isInSnake =true;
								break;
							}			
				}
			}
			return food;
		}
		//产生随机数的函数
		function getRandPosition(min,max){
			return Math.round(Math.random()*(max-min)+min);
		}
		//判断矩形是否重合
		function isRectHit(rect1,rect2){
			var R1_min_x = rect1.x;
			var R2_min_x = rect2.x;
			var R1_min_y = rect1.y;
			var R2_min_y = rect2.y;
			var R1_max_x = rect1.x+40;
			var R2_max_x = rect2.x+40;
			var R1_max_y = rect1.y+40;
			var R2_max_y = rect2.y+40;
			var min_x = Math.max(R1_min_x,R2_min_x);
			var max_x = Math.min(R1_max_x,R2_max_x);
			var min_y = Math.max(R1_min_y,R2_min_y);
			var max_y = Math.min(R1_max_y,R2_max_y);
			if(min_x<max_x && min_y<max_y){
				return true;
			}else{
				return false;
			}
		}
		
		var draw = new Draw($('#canvas')[0]);//创建一个绘图的实例对象
		draw.main();//调用main绘制图像
		var rect1= new Rect(0,0,40,40);
		var rect2= new Rect(41,0,40,40);
		})
	</script>
</html>

希望能给大家带来帮助
如有错误请评论指出,将及时修改

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值