如何基于javascript实现贪吃蛇游戏


Posted in Javascript onFebruary 09, 2020

这篇文章主要介绍了如何基于javascript实现贪吃蛇游戏,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

html代码:

<div class="content">
  <div class="btn startBtn">       <!-- 开始按钮 -->  
    <button type="button"></button>
  </div>
  <div class="btn stopBtn">        <!-- 暂停按钮 -->
    <button type="button"></button>
  </div>
  <div id="snakeWrap"></div>     <!-- 主题内容 -->
</div>

css代码:

* {
  margin: 0;
  padding: 0;
}
body {
  background-color: #565F65;
  width: 100%;
  height: 10vh;
  overflow: hidden;
}

.content {
  width: 500px;
  height: 500px;
  position: absolute;
  top: 50%;
  left: 50%; 
  margin-top: -250px;
  margin-left: -250px;
  background-color: #565F65;
  border: 10px solid #E7E7E7;
  box-shadow: inset 0px 0px 5px 2px #000;
}
.btn {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  background-color: rgba(0, 0, 0, .3);  /*游戏未开始时和暂停时的遮罩*/
  z-index: 2;
}
.btn button {
  background: none;
  border: none;
  background-size: 100% 100%;
  cursor: pointer;
  outline: none;
  position: absolute;
  left: 50%;
  top: 50%;
}
.startBtn button{
  width: 170px;
  height: 80px;
  background-image: url(img/startbtn.png);
  margin-top: -40px;
  margin-left: -85px;
}
.stopBtn {
  display: none;
}
.stopBtn button{
  width: 70px;
  height: 70px;
  background-image: url(img/stopbtn.png);
  margin-top: -35px;
  margin-left: -35px;
}

#snakeWrap {
  width: 500px;
  height: 500px;
  position: relative;
}
.snakeHead { /*蛇头样式*/
  background-color: aqua;
  border-radius: 50%;
}
.snakeBody { /*蛇身样式*/      
  background-color: navajowhite;
  border-radius: 50%;
}
.food {  /*食物样式*/
  background-image: url(img/food.png);
  background-size: cover;
}

javascript 代码:

var sw = 20,  //一个方块的宽
   sh = 20,  //一个方块的高
    tr = 25,  //行数
    td = 25;  //列数
var snake = null,  //蛇的实例
    food = null,  //食物的实例
    game = null;  //游戏的实例
function Square(x, y, classname) {
  this.x = x * sw;     //方块实际的位置
  this.y = y * sh;     //方块实际的位置
  this.class = classname;
  
  this.viewContent = document.createElement('div');  //方块对应的DOM元素
  this.viewContent.className = this.class;
  this.parent = document.getElementById('snakeWrap'); //方块的父级
}

Square.prototype.create = function() {  //创建方块 DOM,并添加到页面里
  this.viewContent.style.position = 'absolute';
  this.viewContent.style.width = sw + 'px';
  this.viewContent.style.height = sh + 'px';
  this.viewContent.style.left = this.x + 'px';
  this.viewContent.style.top = this.y + 'px';
  
  this.parent.appendChild(this.viewContent);
};

Square.prototype.remove = function() {
  this.parent.removeChild(this.viewContent);
}

//蛇
function Snake() {
  this.head = null;  //存一下蛇头的信息
  this.tail = null;  //存一下蛇尾的信息
  this.pos = [];   //存储蛇身上的每一个方块的位置,二维数组
  
  this.directionNum = {  //存储蛇走的方向,用一个对象来表示
    left : {
      x : -1,
      y : 0,
      rotate : 180
    },
    right : {
      x : 1,
      y : 0,
      rotate : 0
    },
    up : {
      x : 0,
      y : -1,
      rotate : -90
    },
    down : {
      x : 0,
      y : 1,
      rotate : 90
    }
  }
}

Snake.prototype.init = function() {
  //创建蛇头
  var snakeHead = new Square(2, 0, 'snakeHead');
  snakeHead.create();
  this.head = snakeHead;    // 存储蛇头信息
  this.pos.push([2, 0]);    //把蛇头的位置存起来
  
  //创建蛇身体
  var snakeBody1 = new Square(1, 0, 'snakeBody');
  snakeBody1.create();
  this.pos.push([1, 0]);    //把蛇身1的位置存起来
  
  var snakeBody2 = new Square(0, 0, 'snakeBody');
  snakeBody2.create();
  this.tail = snakeBody2;    //把蛇尾的信息存起来
  this.pos.push([0, 0]);    //把蛇身1的位置存起来
  
  //让蛇头蛇身形成链表关系
  snakeHead.last = null;
  snakeHead.next = snakeBody1;
  
  snakeBody1.last = snakeHead;
  snakeBody1.next = snakeBody2;
  
  snakeBody2.last = snakeBody1;
  snakeBody2.next = null;
  
  //给蛇添加一条属性,用来表示蛇走的方向
  this.direction = this.directionNum.right; //默认让蛇往右走
  
}

//这个方法用来获取蛇头的下一个位置对应的元素, 要根据元素做不同的事情
Snake.prototype.getNextPos = function() {
  var nextPos = [             //蛇头要走的下一个点的坐标
    this.head.x/sw + this.direction.x,
    this.head.y/sh + this.direction.y
  ];
  
  //下一个点是自己,代表撞到了自己,游戏结束
  var selfCollind = false;   //是否撞到自己
  this.pos.forEach(function(value) {
    if(value[0] == nextPos[0] && value[1] == nextPos[1]) {
      //如果数组中的两个数据都相等,就说明下一个点在蛇身上里面能找到,代表撞到自己了
      selfCollind = true;
    }
  });
  if(selfCollind) {
    console.log('撞到自己了!');
    
    this.strategies.die.call(this);
    
    return;
  }
  
  //下一个点是墙,游戏结束
  if(nextPos[0] < 0 || nextPos[1] < 0 || nextPos[0] > td - 1 || nextPos[1] > tr - 1) {
    console.log('撞墙了!');
    
    this.strategies.die.call(this);
    
    return;
  }
  //下一个点是食物,吃
  if(food && food.pos[0] == nextPos[0] && food.pos[1] == nextPos[1]) {
    //如果这个条件成立说明现在蛇头要走的下一个点是食物的那个点
    console.log('撞到食物了了!');
    this.strategies.eat.call(this);
    return;
  }
  //下一个点什么都不是,走
  this.strategies.move.call(this);
};

//处理碰撞后要做的事 
Snake.prototype.strategies = {
  move : function(format) {  //这个参数用于决定要不要删除最后一个方块(蛇尾), 当传了这个参数后就表示要做的事情是吃
    //创建新身体(在蛇头位置)
    var newBody = new Square(this.head.x/sw, this.head.y/sh, 'snakeBody');
    //更新链表关系
    newBody.next = this.head.next;
    newBody.next.last = newBody;
    newBody.last = null;
    
    
    this.head.remove();  //旧舌头从原来的位置删除
    newBody.create();
    
    //创建一个新蛇头(蛇头下一个要走到的点)
    var newHead = new Square(this.head.x/sw + this.direction.x, this.head.y/sh + this.direction.y, 'snakeHead')
    //更新链表关系
    newHead.next = newBody;
    newHead.last = null;
    newBody.last = newHead;
    newHead.viewContent.style.transform = 'rotate('+this.direction.rotate+'deg)';
    newHead.create();
    
    
    //蛇身上每一个方块的坐标也要更新
    this.pos.splice(0,0, [this.head.x/sw + this.direction.x, this.head.y/sh + this.direction.y]);
    this.head = newHead;   //还要把this.head的信息更新一下
    
    if(!format) {  //如何format 的值为 false, 表示需要删除(除了吃之外的操作)
      this.tail.remove();
      this.tail = this.tail.last;
      
      this.pos.pop();
    }
    
  },
  eat : function() {
    this.strategies.move.call(this, true);
    createFood();
    game.score ++;
  },
  die : function() {
    game.over();
  }
}

snake = new Snake();

//创建食物
function createFood() {
  //食物小方块的随机坐标
  var x = null;
  var y = null;
  
  var include = true;  //循环跳出的条件, true表示食物的坐标在蛇身上(需要继续循环),false表示食物坐标不在蛇身上(不循环了)
  while(include) {
    x = Math.round(Math.random() * (td - 1)); //0-29
    y = Math.round(Math.random() * (tr - 1));
    
    snake.pos.forEach(function(value) {
      if(x != value[0] && y != value[1]) {
        //这个条件成立说明现在随机出来的这个坐标,在蛇身上并没有找到
        include = false;
      }
    });
    
  }
  //生成食物
  food = new Square(x, y, 'food');
  food.pos = [x,y]; //存储一下生成食物的坐标,用于跟蛇头要走的下一个点作对比
  var foodDom = document.querySelector('.food');
  if(foodDom) {
    foodDom.style.left = x*sw + 'px';
    foodDom.style.top = y*sh + 'px';
  }else {
    food.create();
  }
}



//创建游戏逻辑
function Game() {
  this.timer = null;
  this.score = 0;
  this.speed = 200;
}
Game.prototype.init = function() {
  snake.init();
  snake.getNextPos();
  createFood();
  
  document.onkeydown = function(ev) {  //用户按下方向键触发事件
    if(ev.which == 37 && snake.direction != snake.directionNum.right) { 
      //用户按下左键是,蛇不能是往右走
      snake.direction = snake.directionNum.left;
    }else if(ev.which == 38 && snake.direction != snake.directionNum.dowm) {
      snake.direction = snake.directionNum.up;
    }else if(ev.which == 39 && snake.direction != snake.directionNum.left) {
      snake.direction = snake.directionNum.right;
    }else if(ev.which == 40 && snake.direction != snake.directionNum.up) {
      snake.direction = snake.directionNum.down;
    }
  }
  
  this.start();
}

Game.prototype.start = function() { //开始游戏
  this.timer = setInterval(function() {
    snake.getNextPos();
    
  }, this.speed);
}
Game.prototype.pause = function() {
  clearInterval(this.timer);
}
Game.prototype.over = function() { //开始游戏
  clearInterval(this.timer);
  alert('你的得分为' + this.score);
  
  //游戏回到最初的状态
  var snakeWrap = document.getElementById('snakeWrap');
  snakeWrap.innerHTML = '';
  snake = new Snake();
  game = new Game();
  var startBtnWrap = document.querySelector('.startBtn');
  startBtnWrap.style.display = 'block'; 
}
//开启游戏
game = new Game();
var startBtn = document.querySelector('.startBtn button');
startBtn.onclick = function() {
  startBtn.parentNode.style.display = 'none';
  game.init();
};


//暂停
var snakeWrap = document.getElementById('snakeWrap');
var puseBtn = document.querySelector('.stopBtn button')
snakeWrap.onclick = function() {
  game.pause();
  puseBtn.parentNode.style.display = 'block';
}

puseBtn.onclick =function() {
  game.start();
  puseBtn.parentNode.style.display = 'none';
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
纯js代码实现简单计算器
Dec 02 Javascript
JavaScript图像延迟加载库Echo.js
Apr 05 Javascript
JS敏感词过滤代码
Dec 23 Javascript
JS中append字符串包含onclick无效传递参数失败的解决方案
Dec 26 Javascript
JS正则获取HTML元素的方法
Mar 31 Javascript
JavaScript瀑布流布局实现代码
May 06 Javascript
vue给input file绑定函数获取当前上传的对象完美实现方法
Dec 15 Javascript
p5.js入门教程之小球动画示例代码
Mar 15 Javascript
webpack中如何使用雪碧图的示例代码
Nov 11 Javascript
简单了解JS打开url的方法
Feb 21 Javascript
基于vue+element实现全局loading过程详解
Jul 10 Javascript
Vue中正确使用Element-UI组件的方法实例
Oct 13 Javascript
javascript浅层克隆、深度克隆对比及实例解析
Feb 09 #Javascript
通过javascript实现扫雷游戏代码实例
Feb 09 #Javascript
jQuery实现简单聊天室
Feb 08 #jQuery
jquery实现点击弹出对话框
Feb 08 #jQuery
jQuery实现简易聊天框
Feb 08 #jQuery
jquery添加div实现消息聊天框
Feb 08 #jQuery
js实现聊天对话框
Feb 08 #Javascript
You might like
分享下页面关键字抓取components.arrow.com站点代码
2014/01/30 PHP
codeigniter中测试通过的分页类示例
2014/04/17 PHP
php操作XML、读取数据和写入数据的实现代码
2014/08/15 PHP
PHP常用文件操作函数和简单实例分析
2016/06/03 PHP
js 加载时自动调整图片大小
2008/05/28 Javascript
js比较和逻辑运算符的介绍
2013/03/10 Javascript
jQuery中实现动画效果的基本操作介绍
2013/04/16 Javascript
JQuery onload、ready概念介绍及使用方法
2013/04/27 Javascript
js中widow.open()方法使用详解
2013/07/30 Javascript
JavaScript日期对象(Date)基本用法示例
2017/01/18 Javascript
JS中使用 after 伪类清除浮动实例
2017/03/01 Javascript
JS实现复选框的全选和批量删除功能
2017/04/05 Javascript
JS实现获取自定义属性data值的方法示例
2018/12/19 Javascript
Js实现复选框的全选、全不选反选功能代码实例
2020/02/28 Javascript
原理深度解析Vue的响应式更新比React快
2020/04/04 Javascript
微信小程序自定义底部弹出框动画
2020/11/18 Javascript
[47:50]Secret vs VP 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
[53:44]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Magma BO3 第一场 1月31日
2021/03/11 DOTA
pytorch中交叉熵损失(nn.CrossEntropyLoss())的计算过程详解
2020/01/02 Python
Python使用docx模块实现刷题功能代码
2020/02/13 Python
python库skimage给灰度图像染色的方法示例
2020/04/27 Python
使用pymysql查询数据库,把结果保存为列表并获取指定元素下标实例
2020/05/15 Python
python实现最短路径的实例方法
2020/07/19 Python
HTML5 canvas基本绘图之填充样式实现
2016/06/27 HTML / CSS
英国No.1文具和办公用品在线:Euroffice
2016/09/21 全球购物
存储过程的优点有哪些
2012/09/27 面试题
武汉东之林科技有限公司机试
2013/09/17 面试题
财务主管的岗位职责
2013/12/30 职场文书
小型女装店的创业计划书
2014/01/09 职场文书
项目合作意向书范本
2014/04/01 职场文书
支部书记四风对照材料
2014/08/28 职场文书
暑期社会实践证明书
2014/11/17 职场文书
门店店长岗位职责
2015/04/14 职场文书
停水通知
2015/04/16 职场文书
为什么 Nginx 比 Apache 更牛逼
2021/03/31 Servers
Java8利用Stream对列表进行去除重复的方法详解
2022/04/14 Java/Android