如何基于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 相关文章推荐
javascript最常用与实用的创建类的代码
Aug 12 Javascript
JS验证日期的格式YYYY-mm-dd 具体实现
Jun 29 Javascript
JavaScript中的分号插入机制详细介绍
Feb 11 Javascript
探讨JavaScript标签位置的存放与功能有无关系
Jan 15 Javascript
javascript小数精度丢失的完美解决方法
May 31 Javascript
聊一聊Vue.js过渡效果
Sep 07 Javascript
Angular2  NgModule 模块详解
Oct 19 Javascript
jQuery 出现Cannot read property ‘msie’ of undefined错误的解决方法
Nov 23 Javascript
webpack学习--webpack经典7分钟入门教程
Jun 28 Javascript
vue element upload组件 file-list的动态绑定实现
Oct 11 Javascript
vue 实现把路由单独分离出来
Aug 13 Javascript
jQuery插件实现图片轮播效果
Oct 19 jQuery
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
跟我学小偷程序之成功偷取首页(第三天)
2006/10/09 PHP
php的ddos攻击解决方法
2015/01/08 PHP
PHP程序中使用adodb连接不同数据库的代码实例
2015/12/19 PHP
关于php几种字符串连接的效率比较(详解)
2017/02/22 PHP
getElementsByTagName vs selectNodes效率 及兼容的selectNodes实现
2010/02/26 Javascript
JavaScript自定义方法实现trim()、Ltrim()、Rtrim()的功能
2013/11/03 Javascript
利用window.name实现windowStorage代码分享
2014/01/02 Javascript
javascript转换日期字符串为Date日期对象的方法
2015/02/13 Javascript
javascript去除空格方法小结
2015/05/21 Javascript
jQuery实现iframe父窗体和子窗体的相互调用
2016/06/17 Javascript
Javascript实现图片懒加载插件的方法
2016/10/20 Javascript
jQuery图片轮播(二)利用构造函数和原型创建对象以实现继承
2016/12/06 Javascript
微信页面弹出键盘后iframe内容变空白的解决方案
2017/09/20 Javascript
Vue组件之极简的地址选择器的实现
2018/05/31 Javascript
解决使用layui对select append元素无效或者未及时更新的问题
2019/09/18 Javascript
解决vue 子组件修改父组件传来的props值报错问题
2019/11/09 Javascript
Python实现获取网站PR及百度权重
2015/01/21 Python
python实现通过代理服务器访问远程url的方法
2015/04/29 Python
在Python程序中操作文件之flush()方法的使用教程
2015/05/24 Python
python实现实时监控文件的方法
2016/08/26 Python
在numpy矩阵中令小于0的元素改为0的实例
2019/01/26 Python
使用Django简单编写一个XSS平台的方法步骤
2019/03/25 Python
python global关键字的用法详解
2019/09/05 Python
python Pillow图像处理方法汇总
2019/10/16 Python
基于HTML5 Canvas的3D动态Chart图表的示例
2017/11/02 HTML / CSS
Expedia泰国:预订机票、酒店和旅游包(航班+酒店)
2016/09/27 全球购物
巴西网上药店:Drogaria Araujo
2021/01/06 全球购物
UNIX文件系统分类
2014/11/11 面试题
中学生学习生活的自我评价
2013/10/26 职场文书
管理科学大学生求职信
2013/11/13 职场文书
建筑专业毕业生求职信
2014/09/30 职场文书
党的群众路线教育实践活动党员个人剖析材料
2014/10/08 职场文书
自查自纠工作总结
2014/10/15 职场文书
化工见习报告范文
2014/10/31 职场文书
2015年驾驶员工作总结
2015/04/29 职场文书
Django debug为True时,css加载失败的解决方案
2021/04/24 Python