如何基于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 相关文章推荐
showModalDialog模态对话框的使用详解以及浏览器兼容
Jan 11 Javascript
在easyUI开发中,出现jquery.easyui.min.js函数库问题的解决办法
Sep 11 Javascript
JavaScript的History API使搜索引擎抓取AJAX内容
Dec 07 Javascript
js 实现数值的千分位及保存小数方法(推荐)
Aug 01 Javascript
Node.js与Sails redis组件的使用教程
Feb 14 Javascript
JavaScript分步实现一个出生日期的正则表达式
Mar 22 Javascript
layui实现点击按钮给table添加一行
Aug 10 Javascript
Vue 报错TypeError: this.$set is not a function 的解决方法
Dec 17 Javascript
微信小程序wxs实现吸顶效果
Jan 08 Javascript
vue iview实现动态新增和删除
Jun 17 Javascript
微信小程序实现导航栏和内容上下联动功能代码
Jun 29 Javascript
微信小程序实现拼图小游戏
Oct 22 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
114啦源码(114la)不能生成地方房产和地方报刊问题4级页面0字节的解决方法
2012/01/12 PHP
laravel异步监控定时调度器实例详解
2019/06/21 PHP
关于document.cookie的使用javascript
2008/04/11 Javascript
在JavaScript中获取请求的URL参数[正则]
2010/12/25 Javascript
Javascript调用C#代码
2011/01/17 Javascript
jquery异步请求实例代码
2011/06/21 Javascript
JavaScript 学习笔记之基础中的基础
2015/01/13 Javascript
javascript实现3D变换的立体圆圈实例
2015/08/06 Javascript
js表单中选择框值的获取及表单的序列化
2015/12/17 Javascript
JavaScript的Number对象的toString()方法
2015/12/18 Javascript
BootStrap Table后台分页时前台删除最后一页所有数据refresh刷新后无数据问题
2016/12/28 Javascript
深入理解ES6学习笔记之块级作用域绑定
2017/08/19 Javascript
详解使用element-ui table组件的筛选功能的一个小坑
2018/11/02 Javascript
vue 实现微信浮标效果
2019/09/01 Javascript
JS实现纵向轮播图(初级版)
2020/01/18 Javascript
JavaScript实现拖拽盒子效果
2020/02/06 Javascript
JavaScript实现通讯录功能
2020/12/27 Javascript
python使用mysqldb连接数据库操作方法示例详解
2013/12/03 Python
Python提示[Errno 32]Broken pipe导致线程crash错误解决方法
2014/11/19 Python
python获取当前用户的主目录路径方法(推荐)
2017/01/12 Python
python实现微信跳一跳辅助工具步骤详解
2018/01/04 Python
Python使用Dijkstra算法实现求解图中最短路径距离问题详解
2018/05/16 Python
Python秒算24点实现及原理详解
2019/07/29 Python
Django中create和save方法的不同
2019/08/13 Python
Python 字符串类型列表转换成真正列表类型过程解析
2019/08/26 Python
Python创建一个元素都为0的列表实例
2019/11/28 Python
CSS3教程(4):网页边框和网页文字阴影
2009/04/02 HTML / CSS
机械专业毕业生推荐信范文
2013/11/25 职场文书
2014年社区植树节活动方案
2014/02/28 职场文书
讲解员培训方案
2014/05/04 职场文书
主持人开幕词
2015/01/29 职场文书
师德师风个人总结
2015/02/06 职场文书
党员带头倡议书
2015/04/29 职场文书
2015年酒店销售部工作总结
2015/07/24 职场文书
2019开业庆典剪彩仪式主持词!
2019/07/22 职场文书
浅谈Java父子类加载顺序
2021/08/04 Java/Android