用JavaScript写的贪吃蛇游戏(很简单,很详细)

效果

编写外部框架

<!DOCTYPE html>
<html>
	<head lang="en">
		<meta charset="UTF-8">
		<title></title>
		<style>
*{
    margin: 0;
    padding: 0;
}
#box{
	width:620px;
	height:450px;
	position:absolute;
	margin:0 auto;
	left:0;
	top:20px;
	right:0;
	bottom:0;
	background:gray;
	border-radius:10px;
}
#snakeDiv{
	width:600px;
	height:400px;
	position:absolute;
	margin:0 auto;
	left:0;
	top:10px;
	right:0;
	bottom:0;
}
.bottom{
	width:600px;
    height:30px;
	position:absolute;
	bottom:1px;
	right:1px;
}
.bottom .button1{
	position: absolute;
    right: 90px;
    width: 50px;
    font-size: 14px;
}
.bottom .button2{
	position: absolute;
    right: 30px;
    width: 50px;
    font-size: 14px;
}
.bottom .span1{
	position: absolute;
    left: 10px;
    color: white;
}
.bottom .span2{
	position: absolute;
    left: 200px;
    color: white;
}
</style>
	</head>
	<body>
		<div id='box'>
			<div id='snakeDiv'>
			</div>
			<div class='bottom'>
				<span id='score' class='span1'>分数:0</span>
				<span id='time' class='span2'>时间:0</span>
				<button onclick='start()' class='button1'>开始</button>
				<button onclick='stop()' class='button2'>结束</button>
			</div>
		</div>
		
	<script type="text/javascript" src='snake.js'></script>
	
	</body>
</html>

效果:

添加内部画布,以及绘制地图

首先创建线的构造函数Line

function Line(ctx,o){
		this.x=0,//x坐标
		this.y=0,//y坐标
		this.startX=0,//开始点x位置
		this.startY=0, //开始点y位置
		this.endX=0,//结束点x位置
		this.endY=0;//结束点y位置
		this.thin=false;//设置变细系数
		this.ctx=ctx;
		
		this.init(o);
	}
	Line.prototype.init=function(o){
		for(var key in o){
			this[key]=o[key];
		}
	}
	Line.prototype.render=function(){
		innerRender(this);
		
		function innerRender(obj){
			var ctx=obj.ctx;
			ctx.save()
			ctx.beginPath();
			ctx.translate(obj.x,obj.y);
			if(obj.thin){
				ctx.translate(0.5,0.5);
			}
			if(obj.lineWidth){//设定线宽
				ctx.lineWidth=obj.lineWidth;
			}
			if(obj.strokeStyle){
				ctx.strokeStyle=obj.strokeStyle;
			}
			//划线
		  	ctx.moveTo(obj.startX, obj.startY);
		  	ctx.lineTo(obj.endX, obj.endY);
		  	ctx.stroke();
		  	ctx.restore();
		}
	  	
	  	return this;
	}

设定参数、执行绘制等相关方法

function SnakeProxy(el){
		this.renderArr=[];//待渲染对象存储数组
		this.snakeDir=4;//蛇行走方向
		this.snakeArr=[];//用来存蛇头、蛇身、蛇尾的数组
		this.snakePosArr=[];//存蛇头、蛇身、蛇尾分别对应的位置
		this.score=0;//分数
		this.time=0;//时间
		this.moveCount=1;//计时控制器
	}
	
	SnakeProxy.prototype.init=function(el,score,time){
		if(!el) return ;
		this.el=el;
		this.scoreEL=score;
		this.timeEL=time;
		var canvas = document.createElement('canvas');//创建画布
		canvas.style.cssText="background:darkgrey;border:1px solid grey;border-radius:10px;";//设置样式
		var W = canvas.width = 600; //设置宽度
		var H = canvas.height = 400;//设置高度
		
		el.appendChild(canvas);//添加到指定的dom对象中
		
		this.ctx = canvas.getContext('2d');
		this.canvas=canvas;
		this.w=W;
		this.h=H;
		
		this.disX=20;//每个格子的x方向大小
		this.disY=20;//每个格子的y方向大小
		this.maxX=30;//x方向格子总数
		this.maxY=20;//y方向格子总数
		this.draw();//绘制
	}
	
	SnakeProxy.prototype.createMap=function(){
		var renderArr = this.renderArr;
		var disX = this.disX;
		var disY = this.disY;
		var maxX=this.maxX;
		var maxY=this.maxY;
		var rectW = this.w;
		var rectH = this.h;
		var rect=null;
		var color;
		
		for(var i=1;i<maxY;i++){//20行
			var line = new Line(this.ctx,{
				x:0,
				y:0,
			 	startX:0,
			 	startY:i*disY,
			 	endX:this.w,
			 	endY:i*disY,
			 	thin:true,
			 	strokeStyle:'white',
			 	lineWidth:0.2
			})
			renderArr.push(line);
		}
		
		for(var i=1;i<maxX;i++){//30列
			var line = new Line(this.ctx,{
				x:0,
				y:0,
			 	startX:i*disX,
			 	startY:0,
			 	endX:i*disX,
			 	endY:this.h,
			 	thin:true,
			 	strokeStyle:'white',
			 	lineWidth:0.2
			})
			renderArr.push(line);
		}
	}
	
	SnakeProxy.prototype.draw=function(){
		this.createMap();//绘制地图

		this.render();//渲染
	}
	

此时游戏区域的格子以及绘制如下:

再来绘制蛇和食物(这里都是以圆形来做的)

创建Ball构造函数

//构造函数
	function Ball(o){
		this.x=0,//圆心X坐标
		this.y=0,//圆心Y坐标
		this.r=0,//半径
		this.startAngle=0,//开始角度
		this.endAngle=0,//结束角度
		this.anticlockwise=false;//顺时针,逆时针方向指定
		this.stroke=false;//是否描边
		this.fill=false;//是否填充
		this.scaleX=1;//缩放X比例
		this.scaleY=1;//缩放Y比例
		
		this.init(o);
	}
	//初始化
	Ball.prototype.init=function(o){
		for(var key in o){
			this[key]=o[key];
		}
	}
	//绘制
	Ball.prototype.render=function(context){
		var ctx=context;
		ctx.save();
		ctx.beginPath();
		ctx.translate(this.x,this.y);
		ctx.scale(this.scaleX,this.scaleY);//设定缩放
		ctx.arc(0,0,this.r,this.startAngle,this.endAngle);//画圆
		if(this.lineWidth){//线宽
			ctx.lineWidth=this.lineWidth;
		}
		if(this.fill){//是否填充
			this.fillStyle?(ctx.fillStyle=this.fillStyle):null;
			ctx.fill();
		}
		if(this.stroke){//是否描边
			this.strokeStyle?(ctx.strokeStyle=this.strokeStyle):null;
			ctx.stroke();
		}	
		ctx.restore();
		
		return this;
	}

绘制蛇头

SnakeProxy.prototype.createHead=function(){
		var renderArr = this.renderArr;
		var disX = this.disX;
		var disY = this.disY;
		var x=1,y=0;
		var head = new Ball({
		 	x:x*disX+disX/2,
			y:y*disY+disY/2,
			r:disX/2-2,
			startAngle:0,
			endAngle:2*Math.PI,
			fill:true,
			fillStyle:'#F5DC10',
			lineWidth:1.2
		 })
		 renderArr.push(head);
		 this.snakeArr.push(head);
		 this.snakePosArr.push({x:x,y:y});
	}

蛇身(先不绘制出来,先放代码)

	
	SnakeProxy.prototype.createBody=function(){
		var renderArr = this.renderArr;
		var disX = this.disX;
		var disY = this.disY;
		var x=1,y=0;
		var body = new Ball({
		 	x:x*disX+disX/2,
			y:y*disY+disY/2,
			r:disX/3,
			startAngle:0,
			endAngle:2*Math.PI,
			fill:true,
			fillStyle:'#F5DC10',
			lineWidth:1.2
		 })
		 renderArr.push(body);
		 this.snakeArr.splice(1,0,body);//在头部后面添加
	}
	

绘制蛇尾

SnakeProxy.prototype.createEnd=function(){
		var renderArr = this.renderArr;
		var disX = this.disX;
		var disY = this.disY;
		
		var x=0,y=0;
		var end = new Ball({
		 	x:x*disX+disX/2,
			y:y*disY+disY/2,
			r:disX/4,
			startAngle:0,
			endAngle:2*Math.PI,
			fill:true,
			fillStyle:'#F5DC10',
			lineWidth:1.2
		 })
		 renderArr.push(end);
		 this.snakeArr.push(end);
		 this.snakePosArr.push({x:x,y:y});
	}

绘制食物(蛋)

SnakeProxy.prototype.createEgg=function(){
		var renderArr = this.renderArr;
		var disX = this.disX;
		var disY = this.disY;
		
		var x=_.getRandom(0,30),y=_.getRandom(0,20);
		
		var egg = new Ball({
		 	x:x*disX+disX/2,
			y:y*disY+disY/2,
			r:disX/2-2,
			startAngle:0,
			endAngle:2*Math.PI,
			scaleY:0.8,
			fill:true,
			fillStyle:'#FCF6DB',
			lineWidth:1.2
		 })
		 renderArr.push(egg);
		 this.egg=egg;
		 this.eggPos={x:x,y:y};
		 
		 var that=this;
		 egg.update=function(){//update方法,蛋被吃以后,新随机出现在地图中
		 	var x=_.getRandom(0,30),y=_.getRandom(0,20);
		 	this.x=x*disX+disX/2,this.y=y*disY+disY/2;
		 	that.eggPos={x:x,y:y};
		 }
	}

蛋加多了一个方法,用来更新位置(当被蛇吃了后)

给开始、结束按钮加入事件

var snakeDiv = document.getElementById('snakeDiv');
	var score= document.getElementById('score');
	var time= document.getElementById('time');
	
	snake.init(snakeDiv,score,time);
	
	function start(){
		snake.start()
	}
	
	function stop(){
		snake.stop()
	}
	SnakeProxy.prototype.start=function(){
		if(this.timmer) return ;
		if(this.hasEnd){//如果是结束则需要重新开始,暂停的话就继续游戏
			this.restart();
		}
		this.hasEnd=false;
		this.timmer = setInterval(this.move.bind(this),250);//开始定时任务
	}
		
	SnakeProxy.prototype.stop=function(){
		if(!this.timmer) return ;
		clearInterval(this.timmer);//清除定时任务
		this.timmer=null;
	}

此时的效果如下:

加入方向控制

SnakeProxy.prototype.control=function(){
		var that=this;
		global.addEventListener('keydown',function(e){
			switch (e.keyCode){
				case 38:
					if(that.snakeDir==1||that.snakeDir==2){
						break;
					}
					that.snakeDir=1;//上
					break;
				case 40:
					if(that.snakeDir==1||that.snakeDir==2){
						break;
					}
					that.snakeDir=2;//下
					break;
				case 37:
					if(that.snakeDir==3||that.snakeDir==4){
						break;
					}
					that.snakeDir=3;//左
					break;
				case 39:
					if(that.snakeDir==3||that.snakeDir==4){
						break;
					}
					that.snakeDir=4;//右
					break;
			
			}
			console.log(that.snakeDir)
		});
	}

加入蛇的下一个坐标更新

SnakeProxy.prototype.update=function(){
		var posArr = this.snakePosArr,pos;
		var disX=this.disX,disY=this.disY;
		_.each(this.snakeArr,function(s,i){
			pos = posArr[i];
			s.x=pos.x*disX+disX/2;
			s.y=pos.y*disY+disY/2;
		})
	}
	
	SnakeProxy.prototype.computedNext=function(obj){
		var x =obj.x, y = obj.y;
		switch (this.snakeDir){
			case 1:
				y=obj.y-1;
				break;
			case 2:
				y=obj.y+1;
				break;
			case 3:
				x=obj.x-1;
				break;
			case 4:
				x=obj.x+1;
				break;
		}
		return {x:x,y:y}
	}

再加上吃食物、咬到自己、计算时间、计算分数、定时move函数就完成了

SnakeProxy.prototype.eat=function(head){
		var pos = this.eggPos;
		if(head.x===pos.x && head.y===pos.y){//如果头部与蛋整体重合的话就吃
			this.egg.update();//重新随机蛋的位置
			//添加蛇的身体
			this.createBody();
			
			this.calcuScore();//计算分数
			return true;
		}
		return false;
	}
	SnakeProxy.prototype.eatSelf=function(head){
		var snakePosArr=this.snakePosArr;
		for(var i=1;i<snakePosArr.length;i++){
			var s = snakePosArr[i];
			if(head.x==s.x && head.y==s.y){
				return true;
			}
		}
		return false;
	}
	SnakeProxy.prototype.end=function(head,oldHead){
		if(head.x>=this.maxX || head.x<0 || head.y>=this.maxY || head.y<0 ){//超出边界结束
			alert('结束了')
			return true;
		}
		if(this.eatSelf(oldHead)){//触碰到自己也结束
			alert('结束了1')
			return true;
		}
		
		return false
	}
	
	SnakeProxy.prototype.calcuScore=function(){
		this.score+=100;
		this.scoreEL.innerText='分数:'+this.score;
	}
	
	SnakeProxy.prototype.calcuTime=function(){
		if(this.moveCount%4==0){
			this.time++;
			this.time_flag=false;
			this.timeEL.innerText='时间:'+this.time;
		}
		
		this.moveCount++;
	}
	
	SnakeProxy.prototype.move=function(){
		this.calcuTime();
		
		var headPos = this.snakePosArr[0];
		//执行吃动作
		var eatFlag = this.eat(headPos);
		//计算下一个坐标
		var nextPos = this.computedNext(headPos);
		
		var endFlag = this.end(nextPos,headPos);
		if(endFlag) {
			this.stop();
			this.hasEnd=true;
			return ;
		} 
		
		if(!eatFlag){//如果吃了食物,则不行弹出最后一个
			this.snakePosArr.pop();
		}
		this.snakePosArr.unshift(nextPos);
		this.update();
		
		this.render();
	}

源码获取方式:
订阅我的专栏《【javascript精彩实例】》后,可以查看专栏内所有的文章,并且联系博主免费获取心仪的源代码,专栏的文章都是上过csdn热榜的,值得信赖,【了解一下我的专栏!

热门专栏推荐:
【1】Java小游戏(俄罗斯方块、飞机大战、植物大战僵尸等)
【2】JavaWeb项目实战(图书管理、在线考试、宿舍管理等)
【3】JavaScript精彩实例(飞机大战、贪吃蛇、验证码等)
【4】Java小白入门200例
【5】从零学Java、趣学Java
【6】Idea从零到精通

  • 130
    点赞
  • 460
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 64
    评论
好的,我可以给你提供一个简单贪吃蛇游戏代码,你可以在网页上运行它。 HTML 代码: ``` <!DOCTYPE html> <html> <head> <title>贪吃蛇游戏</title> <style> canvas { border: 1px solid #000; } </style> </head> <body> <h1>贪吃蛇游戏</h1> <canvas id="gameCanvas" width="400" height="400"></canvas> <script src="snake.js"></script> </body> </html> ``` JavaScript 代码: ```javascript // 获取 canvas 元素 var canvas = document.getElementById("gameCanvas"); var ctx = canvas.getContext("2d"); // 定义游戏参数 var blockSize = 10; // 方块大小 var widthInBlocks = canvas.width / blockSize; var heightInBlocks = canvas.height / blockSize; var score = 0; // 定义绘制方块的函数 var drawBlock = function(ctx, position) { var x = position[0] * blockSize; var y = position[1] * blockSize; ctx.fillRect(x, y, blockSize, blockSize); }; // 定义绘制分数的函数 var drawScore = function() { ctx.font = "20px Arial"; ctx.fillStyle = "Black"; ctx.textAlign = "left"; ctx.textBaseline = "top"; ctx.fillText("Score: " + score, blockSize, blockSize); }; // 定义清除画布的函数 var clearCanvas = function() { ctx.clearRect(0, 0, canvas.width, canvas.height); }; // 定义游戏结束的函数 var gameOver = function() { clearInterval(intervalId); ctx.font = "60px Arial"; ctx.fillStyle = "Black"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillText("Game Over", canvas.width / 2, canvas.height / 2); }; // 定义方块的构造函数 var Block = function(col, row) { this.col = col; this.row = row; }; // 定义判断方块是否在画布内的函数 Block.prototype.insideCanvas = function() { return (this.col >= 0 && this.col < widthInBlocks && this.row >= 0 && this.row < heightInBlocks); }; // 定义判断方块是否在同一个位置的函数 Block.prototype.equal = function(otherBlock) { return (this.col === otherBlock.col && this.row === otherBlock.row); }; // 定义蛇的构造函数 var Snake = function() { this.segments = [ new Block(7, 5), new Block(6, 5), new Block(5, 5) ]; this.direction = "right"; this.nextDirection = "right"; }; // 定义绘制蛇的函数 Snake.prototype.draw = function() { for (var i = 0; i < this.segments.length; i++) { drawBlock(ctx, this.segments[i].position()); } }; // 定义移动蛇的函数 Snake.prototype.move = function() { var head = this.segments[0]; var newHead; this.direction = this.nextDirection; if (this.direction === "right") { newHead = new Block(head.col + 1, head.row); } else if (this.direction === "down") { newHead = new Block(head.col, head.row + 1); } else if (this.direction === "left") { newHead = new Block(head.col - 1, head.row); } else if (this.direction === "up") { newHead = new Block(head.col, head.row - 1); } if (this.checkCollision(newHead)) { gameOver(); return; } this.segments.unshift(newHead); if (newHead.equal(apple.position())) { score++; apple.move(); } else { this.segments.pop(); } }; // 定义检查蛇是否碰到边界或自己的函数 Snake.prototype.checkCollision = function(head) { var leftCollision = (head.col === 0); var topCollision = (head.row === 0); var rightCollision = (head.col === widthInBlocks - 1); var bottomCollision = (head.row === heightInBlocks - 1); var wallCollision = leftCollision || topCollision || rightCollision || bottomCollision; var selfCollision = false; for (var i = 0; i < this.segments.length; i++) { if (head.equal(this.segments[i])) { selfCollision = true; } } return wallCollision || selfCollision; }; // 定义改变蛇的方向的函数 Snake.prototype.setDirection = function(newDirection) { if (this.direction === "up" && newDirection === "down") { return; } else if (this.direction === "right" && newDirection === "left") { return; } else if (this.direction === "down" && newDirection === "up") { return; } else if (this.direction === "left" && newDirection === "right") { return; } this.nextDirection = newDirection; }; // 定义苹果的构造函数 var Apple = function() { this.position = function() { var col = Math.floor(Math.random() * (widthInBlocks - 2)) + 1; var row = Math.floor(Math.random() * (heightInBlocks - 2)) + 1; return new Block(col, row); }; this.move = function() { this.block = this.position(); }; this.block = this.position(); }; // 创建蛇和苹果对象 var snake = new Snake(); var apple = new Apple(); // 定义游戏循环 var intervalId = setInterval(function() { clearCanvas(); drawScore(); snake.move(); snake.draw(); apple.draw(); }, 100); // 定义键盘按下事件 var directions = { 37: "left", 38: "up", 39: "right", 40: "down" }; document.addEventListener("keydown", function(event) { var newDirection = directions[event.keyCode]; if (newDirection !== undefined) { snake.setDirection(newDirection); } }); ``` 这个代码实现了一个简单贪吃蛇游戏,你可以在浏览器中打开 HTML 文件,就可以运行游戏了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程界小明哥

请博主喝瓶水,博主持续输出!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值