效果

编写外部框架

<!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从零到精通

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

  1. python游戏贪吃蛇_Python写的贪吃蛇游戏例子_python

    这篇文章主要介绍了Python写的贪吃蛇游戏例子,练手作品,又好玩又可以学到东西,需要的朋友可以参考下 第一次用Python写这种比较实用且好玩的东西,权当练手吧 游戏说明: * P键控制" ...

  2. python写一个游戏多少代码-使用Python写一个贪吃蛇游戏实例代码

    我在程序中加入了分数显示,三种特殊食物,将贪吃蛇的游戏逻辑写到了SnakeGame的类中,而不是在Snake类中. 特殊食物: 1.绿色:普通,吃了增加体型 2.红色:吃了减少体型 3.金色:吃了回到 ...

  3. python游戏脚本实例-使用Python写一个贪吃蛇游戏实例代码

    我在程序中加入了分数显示,三种特殊食物,将贪吃蛇的游戏逻辑写到了SnakeGame的类中,而不是在Snake类中. 特殊食物: 1.绿色:普通,吃了增加体型 2.红色:吃了减少体型 3.金色:吃了回到 ...

  4. 好玩的c语言编程游戏,C语言写个贪吃蛇游戏

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 C语言写个贪吃蛇游戏 贪吃蛇是个非常经典的游戏,用C语言来实现也是一个好玩的事情.这个游戏我写完后放在知乎,竟然点赞的人数超级多.我觉得大家喜欢,一个方面 ...

  5. bat贪吃蛇游戏代码_C语言写个贪吃蛇游戏

    贪吃蛇是个非常经典的游戏,用C语言来实现也是一个好玩的事情.这个游戏我写完后放在知乎,竟然点赞的人数超级多.我觉得大家喜欢,一个方面是因为写得简单,大家都能看得懂,一个可扩展性还是非常强的. 我试了说 ...

  6. C语言写个贪吃蛇游戏

    贪吃蛇是个非常经典的游戏,用C语言来实现也是一个好玩的事情.这个游戏我写完后放在知乎,竟然点赞的人数超级多.我觉得大家喜欢,一个方面是因为写得简单,大家都能看得懂,一个可扩展性还是非常强的. 我试了说 ...

  7. 手机java做贪吃蛇_如何用Java写一个贪吃蛇游戏

    这是一位拓胜学员用Java写贪吃蛇游戏的心得:今天课程设计终于结束了自己学java没以前学C+那么用功了觉得我学习在哪里都是个开口向上的抛物线,现在应该在右半边吧,好了进入正题. 写java贪吃蛇也是 ...

  8. x x x x c程序语言,C语言写个贪吃蛇游戏

    贪吃蛇是个非常经典的游戏,用C语言来实现也是一个好玩的事情.这个游戏我写完后放在知乎,竟然点赞的人数超级多.我觉得大家喜欢,一个方面是因为写得简单,大家都能看得懂,一个可扩展性还是非常强的. 我试了说 ...

  9. 用c语言写一个贪吃蛇游戏代码

    首先,贪吃蛇是一个经典的游戏,主要通过控制一条蛇在地图上吃食物,不断长长身体,最终实现最高分数. 以下是使用C语言编写贪吃蛇游戏的示例代码: ``` #include<stdio.h> # ...

  10. java gui怎么做游戏_Java中关于GUI实现贪吃蛇游戏的简单方法

    这篇文章主要介绍了Java GUI编程之贪吃蛇游戏简单实现方法,详细分析了贪吃蛇游戏的具体实现步骤与相关注意事项,并附带demo源码供读者下载参考,需要的朋友可以参考下 本文实例讲述了Java GUI ...

最新文章

  1. 机器学习数据预处理之缺失值:前向填充
  2. Go中的Socket编程
  3. xce/mime/MimeMessage类接口的说明
  4. UBUNTU安装 Rabbitvsc可视化版本控制客户端软件
  5. include php 失效,为什么include(‘php:// input’)不起作用?
  6. 缓存目录的区别getCacheDir()、getFilesDir()、getExternalFilesDir()、getExternalCacheDir()的作用
  7. 揭开netty神秘面纱_Netty 源码(ChannelHandler 死磕)
  8. html怎么让图片自动动起来,css如何让图片动起来?
  9. 准备创建一个自己的校验提示Extender
  10. AD的小知识贴片的template
  11. java脚本封号_java中如何踢人下线?封禁某个账号后使其会话立即掉线!
  12. Vue源码:mustache模板引擎学习
  13. html2canvas提升像素,jspdf + html2canvas 实现html转pdf (提高分辨率版本)
  14. Linux开发环境——tftp服务器的搭建
  15. 用友NC系统安装部署指南
  16. Axure 制作过滤筛选栏
  17. 【NOIP practice】BSOJ 3140 冲出亚洲 模拟
  18. reactos操作系统实现(6)
  19. cutelyst教程_01 _简介
  20. 修改php-fpm监听端口,如何修改php fpm监听端口

热门文章

  1. 渥太华大学计算机科学COOP,渥太华大学专业哪个好
  2. 简单线性回归截距假设检验_统计推断——假设检验——简单线性回归分析
  3. VB 切换到指定的应用程序上
  4. Mac OS X 背后的故事(九)半导体的丰收(中)
  5. VLOOKUP函数的使用
  6. 易经六十四卦对照与简单实现卦象操作
  7. add git 指定类型文件夹_git add 命令
  8. Win部署Flask服务_NSSM
  9. 电驴搜索服务器正在连接,电驴未连接到服务器是什么原因?
  10. 28 | Pika:如何基于SSD实现大容量Redis?