css代码:
html代码:
"map">
"end">
游戏结束
得分:
分数:0
js代码:
<script>
function game() {
this.map=document.querySelector('.map')
this.span=document.querySelector('body>p>span')
this.span1=document.querySelector('.end span')
this.start=document.querySelector('.start')
this.end=document.querySelector('.end')
this.ok=document.querySelector('.ok')
var that=this
//地图的宽高
this.mpcw=this.map.clientWidth //不带边框
this.mpch=this.map.clientHeight //不带边框
//点击方向键改变方向
document.onkeydown=function(e){
var cod=e.keyCode
//w:87 a:65 s:83 d:68 ↑:38 ←:37 ↓:40 →:39
if(cod==87 || cod==38 ){
if(that.fx!='down'){
that.fx='up'
}
}else if(cod==65 ||cod==37){
if(that.fx!='right'){
that.fx='left'
}
}else if(cod==83 || cod==40){
if(that.fx!='up'){
that.fx='down'
}
}else if(cod==68 || cod==39){
if(that.fx!='left'){
that.fx='right'
}
}
}
//开始游戏
this.sta()
//游戏结束
this.ok.onclick=function(){
that.en()
}
}
//开始游戏
game.prototype.sta=function(){
//初始化蛇
this.reset()
this.bd=[]
var that=this
this.start.style.display='block'
this.start.onclick=function(){
that.start.style.display='none'
//创建食物
that.food()
//创建蛇
that.snake()
//蛇的移动
that.timer=setInterval(()=>{
that.fun()
},70)
}
}
//初始化
game.prototype.reset=function(){
this.arr=[
{x:this.mpcw/2, y:this.mpch/2},
{x:this.mpcw/2, y:this.mpch/2+10},
{x:this.mpcw/2, y:this.mpch/2+20},
]
this.fx='up'
this.timer=null
//分数
this.sp=0
this.span.innerText=this.sp
}
//设置样式
game.prototype.setStyle= function (elm,obj) {
for(var attr in obj){
elm.style[attr]=obj[attr];
}
}
//获取随机数
game.prototype.getRandom= function (a,b) {
var max=Math.max(a,b)
var min=Math.min(a,b)
return Math.round(Math.random()*(max-min)+min)
}
//创建食物
game.prototype.food=function(){
this.l=Math.round(this.getRandom(0,this.mpcw-10)/10)*10
this.t=Math.round(this.getRandom(0,this.mpch-10)/10)*10
this.fd=document.createElement('div')
this.setStyle(this.fd,{
width:'10px',
height:'10px',
borderRadius:'50%',
background:'green',
position:'absolute',
left:this.l+'px',
top:this.t+'px',
})
this.map.appendChild(this.fd)
}
//创建蛇
game.prototype.snake=function(){
if(this.bd.length!=0){
for(var i=0;i<this.bd.length;i++){
this.map.removeChild(this.bd[i])
}
this.bd=[]
}
for(var i=0;i<this.arr.length;i++){
var div=document.createElement('div')
this.setStyle(div,{
width:'10px',
height:'10px',
borderRadius:'50%',
background:'black',
position:'absolute',
left:this.arr[i].x+'px',
top:this.arr[i].y+'px',
})
if(i==0){
div.style.background='red'
}
this.map.appendChild(div)
this.bd.push(div)
}
}
//蛇的移动
game.prototype.fun=function(){
for(var i=this.arr.length-1;i>0;i--){
this.arr[i].x=this.arr[i-1].x
this.arr[i].y=this.arr[i-1].y
}
switch(this.fx){
case 'up':this.arr[0].y-=10;
break;
case 'down':this.arr[0].y+=10;
break;
case 'left':this.arr[0].x-=10;
break;
case 'right':this.arr[0].x+=10;
break;
}
//位置变后重新创建蛇
this.snake()
//吃到食物
this.eat()
//死亡判断
this.die()
}
//吃到食物
game.prototype.eat=function(){
if(this.arr[0].x==this.l && this.arr[0].y==this.t){
this.map.removeChild(this.fd)
this.food()
this.sp+=1
this.span.innerText=this.sp
this.arr.push({x:this.arr[this.arr.length-1].x, y:this.arr[this.arr.length-1].y})
}
}
//死亡判断
game.prototype.die=function(){
//撞墙
if(this.arr[0].x<0 || this.arr[0].x>this.mpcw-this.fd.offsetWidth || this.arr[0].y<0 || this.arr[0].y>this.mpch-this.fd.offsetHeight){
this.died()
}
//撞身体
for(var i=1;i<this.arr.length;i++){
if(this.arr[0].x==this.arr[i].x && this.arr[0].y==this.arr[i].y){
this.died()
}
}
}
//死亡函数
game.prototype.died=function(){
clearInterval(this.timer)
this.end.style.display='block'
this.span1.innerText=this.sp
this.span1.style.color='red'
}
//游戏结束
game.prototype.en=function(){
this.end.style.display='none'
this.reset()
this.map.removeChild(this.fd)
this.start.style.display='block'
for(var i=0;i<this.bd.length;i++){
this.map.removeChild(this.bd[i])
}
this.bd=[]
}
var a=new game()
</script>
定义一个构造函数,然后new它
首先获取需要操作的标签
在两个不相关的函数之间不能互相访问局部变量,所以可以把变量添加为对象的属性
因为在事件函数里 this 指向的是事件源,所以要在外面定义一个变量that,将 this 赋值给 that ,然后在事件函数里就可以用 that 来进行相关操作
定义一个变量,根据按的方向键变为对应的值
还要判断不能掉头,如果是向左走就不能按右方向键
接下来实现各项功能,实现功能一般是给构造函数的原型添加方法,这样new出来的对象也可以调用,而且不会被其他全局变量覆盖
首先添加一个获取随机数和设置样式的方法,为了后面写代码更方便
食物是随机出现在地图上的,可以用到上面获取随机数和设置样式的方法,不能超出地图
可以用初始化里的数组来创建身体,数组里面有几个对象身体就有几节,对象里放身体的坐标,初始化坐标在地图中间,代表蛇在地图中间出生
蛇的移动就是改变身体的坐标,然后重新创建一个身体,并把之前的身体移除
将第二节身体的坐标给第三节,第一节的给第二节,第一节的坐标再加上一节身体的长度,就完成了移动
判断方向决定第一节的坐标变化
因为重新创建蛇后要移除上一条蛇,所以要在创建蛇的方法里改成先移除蛇,再创建蛇
然后给蛇的移动方法放进一个定时器里,每隔多久调用一次,这样就能“移动”了
吃到食物就是判断蛇头的坐标和食物坐标一样
吃到食物后,要移除食物,然后创建一个新的食物,并给创建身体的数组添加一个对象,坐标是蛇尾的坐标,这样下次创建身体就增加了一节
撞墙和撞身体会死,就是判断蛇头的坐标有没有超出地图,有没有和身体的坐标相同
死亡后要干什么也添加一个方法
要清除定时器等等
判断死亡条件成立就调用这个方法
因为吃食物和判断死亡都是在蛇的移动里的,所以把它们放进移动方法里去调用
这样各项功能就差不多完成了,然后定义一个点击开始按钮的方法,把这些功能放进去
然后点击游戏结束按钮也添加一个方法,打扫战场,移除蛇和食物,初始化什么的
在构造函数里面调用开始和结束就行了
点击方向键改变方向也可以定义成一个方法然后在这调用