js实现贪吃蛇小游戏


Posted in Javascript onOctober 29, 2019

本文实例为大家分享了js实现贪吃蛇小游戏的具体代码,供大家参考,具体内容如下

index.html

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>贪吃蛇</title>
 <link rel="stylesheet" href="style.css" >
</head>
<body>
 <div id="game">
  <div id="explain">
   <div>操作WASD 空格开始/暂停 R重新开始</div>
   <div>当前分数:<span id="grade">0</span>分</div>
  </div>
  <canvas id="snakegame" width="500" height="500">
  </canvas>
 </div>
 <script type="text/javascript" src="main.js" charset="UTF-8"></script>
</body>
</html>

style.css

*{
 padding: 0;
 margin: 0;
}
#game {
 width: 500px;
 margin: auto;
}
#explain {
 width: 500px;
}
#explain div{
 width: 500px;
 height: 30px;
}
#snakegame {
 background: green;
}

main.js

/**
 * el 挂载的元素
 * attribute 贪吃蛇的属性
 */
class Game {
 constructor (el, attribute) {
  this.el = document.getElementById(el);
  // 获取画布的宽高
  this.el.elW = parseInt(window.getComputedStyle(this.el).width);
  this.el.elH = parseInt(window.getComputedStyle(this.el).height);
  this.init(attribute);
  this.keyListening();
 }
 // 初始化
 init(attribute) {
  this.attribute = {
   color: "red", // 颜色
   direction: "rigth", // 移动方向
   state: "pause", // 状态 run pause end
   grade: 0, // 分数
   body: [{x: 20, y: 0}, {x: 0, y: 0}], // 贪吃蛇身体
   wh: 20, // 矩形的宽高
   speed: 200 // 速度
  };
  if (attribute) {
   this.newAttribute = attribute;
   Object.keys(attribute).forEach(key => {
    this.attribute[key] = attribute[key];
   });
  }
  this.food ={
   x: 0,
   y: 0,
   color: 'red'
  }
  this.draw();
  this.foodDraw();
 }
 // 绘制贪吃蛇
 draw() {
  let el = this.el;
  let { body, wh, color } = this.attribute;
  // 确定浏览器是否支持canvans元素
  if (el.getContext) {
   let context = snakegame.getContext("2d");
   context.fillStyle = color;
   body.forEach( key => {
    context.fillRect(key.x, key.y, wh, wh);
   });
  }
 }
 // 随机生成食物
 foodDraw() {
  let el = this.el, wh = this.attribute.wh;
  this.food.x = Math.floor(Math.random()*(el.elW - wh)),
  this.food.y = Math.floor(Math.random()*(el.elH - wh));
  while (this.isOverlap()) {
   this.food.x = Math.floor(Math.random()*(el.elW - wh)),
   this.food.y = Math.floor(Math.random()*(el.elH - wh));
  }
  if (el.getContext) {
   let context = snakegame.getContext("2d");
   context.fillStyle = this.food.color;
   context.fillRect(this.food.x, this.food.y, wh, wh);
  }
 }
 // 判断食物是否与贪吃蛇的身体重叠
 isOverlap() {
  let { wh } = this.attribute;
  let food = this.food;
  let flag = false;
  function isIn(key, x, y) {
   if (key.x <= x && key.x + wh >= x && key.y <= y && key.y + wh >= y) {
    return true;
   } else {
    return false;
   }
  }
  this.attribute.body.forEach(key => {
   // 食物的上下左右四个点一个点在贪吃蛇的身体内就判断为重叠
   if (isIn(key, food.x, food.y) || isIn(key, food.x, food.y + wh) || isIn(key, food.x + wh, food.y) || isIn(key, food.x + wh, food.y + wh)) {
    flag = true;
   }
  });
  return flag;
 }
 // 清除图形
 clear(x, y, width, height) {
  // 确定浏览器是否支持canvans元素
  if (this.el.getContext) {
   let context = snakegame.getContext("2d");
   context.clearRect(x, y, width, height);
  }
 }
 // 游戏状态更新
 updateState(state) {
  this.attribute.state = state;
  if (state === "run") {
   this.run();
  } 
 }
 // 游戏线程
 run() {
  let { body, wh, speed} = this.attribute;
  let time = setInterval(() => {
   // 判断游戏线程是否在运行
   if (this.attribute.state !== 'run') {
    clearInterval(time);
   }
   let obj = {};
   switch(this.attribute.direction) {
    case 'left':
     obj['x'] = body[0].x - wh;
     obj['y'] = body[0].y;
     break;
    case 'rigth':
     obj['x'] = body[0].x + wh;
     obj['y'] = body[0].y;
     break;
    case 'up':
     obj['x'] = body[0].x;
     obj['y'] = body[0].y - wh;
     break;
    case 'down':
     obj['x'] = body[0].x;
     obj['y'] = body[0].y + wh;
     break;
   }
   body.unshift(obj);
   // 判断是否吃到食物 
   if (this.isOverlap()) {
    this.clear(this.food.x, this.food.y, wh, wh);
    this.attribute.grade++; 
    this.foodDraw();
    this.draw();
   } else {
    if (this.end()) {
     alert("游戏结束");
     this.updateState('end');
     clearInterval(time);
    } else {
     let item = body.pop();
     this.clear(item.x, item.y, wh, wh);
     this.draw();
    }
   }
  }, speed);
 }
 // 键盘事件监听
 keyListening() {
  document.onkeydown = (event) => {
   let e = event || window.event || arguments.callee.caller.arguments[0];
   if (e && e.keyCode === 87 && this.attribute.direction !== 'down') { // 按下W
    this.attribute.direction = 'up';
   }
   if (e && e.keyCode === 65 && this.attribute.direction !== 'rigth') { // 按下A
    this.attribute.direction = 'left';
   }
   if (e && e.keyCode === 68 && this.attribute.direction !== 'left') { // 按下D
    this.attribute.direction = 'rigth';
   }
   if (e && e.keyCode === 83 && this.attribute.direction !== 'up') { // 按下W
    this.attribute.direction = 'down';
   }
   if (e && e.keyCode === 32) { // 按下空格 
    let state;
    if (this.attribute.state === 'pause') {
     state = 'run';
    } 
    if (this.attribute.state === 'run') {
     state = 'pause';
    }
    this.updateState(state);
   }
   if (e && e.keyCode === 82) { // 按下R键
    this.reStart();
   }
  } 
 }
 // 是否死亡
 end() {
  let body = [...this.attribute.body];
  let obj = body.shift();
  let flag = false;
  if (obj.x < 0 || obj.x >= this.el.elW || obj.y < 0 || obj.y >= this.el.elH) {
   flag = true;
  }
  body.forEach(key => {
   if (key.x === obj.x && key.y === obj.y) {
    flag = true;
   }
  });
  return flag;
 }
 // 重新开始
 reStart() {
  // 清除整个画布
  this.clear(0, 0, this.el.elW, this.el.elH);
  // 重新开始
  this.init(this.newAttribute);
 }
}
let game = new Game("snakegame", {color: "yellow"});
let grade = document.getElementById("grade");
let oldGrade = game.attribute.grade;
setInterval(() => {
 if (oldGrade !== game.attribute.grade) {
  oldGrade = game.attribute.grade;
  grade.innerText = game.attribute.grade;
 }
})

截图

js实现贪吃蛇小游戏

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

Javascript 相关文章推荐
JS 获取span标签中的值的代码 支持ie与firefox
Aug 24 Javascript
js 数组实现一个类似ruby的迭代器
Oct 27 Javascript
js对象数组按属性快速排序
Jan 31 Javascript
Node.js中对通用模块的封装方法
Jun 06 Javascript
基于jQuery实现点击列表加载更多效果
May 31 Javascript
jQuery图片渐变特效的简单实现
Jun 25 Javascript
javascript中call,apply,bind函数用法示例
Dec 19 Javascript
详解Webpack DLL用法以及功能
Jul 11 Javascript
小程序图片长按识别功能的实现方法
Aug 30 Javascript
个人小程序接入支付解决方案
May 23 Javascript
使用vue-router在Vue页面之间传递数据的方法
Jul 15 Javascript
p5.js临摹动态图形实现方法详解
Oct 23 Javascript
浅谈vue异步数据影响页面渲染
Oct 29 #Javascript
详解vue中多个有顺序要求的异步操作处理
Oct 29 #Javascript
vue实现设置载入动画和初始化页面动画效果
Oct 28 #Javascript
vue设置一开始进入的页面教程
Oct 28 #Javascript
Vue调用后端java接口的实例代码
Oct 28 #Javascript
原生js实现商品筛选功能
Oct 28 #Javascript
使用Vue实现调用接口加载页面初始数据
Oct 28 #Javascript
You might like
基于php上传图片重命名的6种解决方法的详细介绍
2013/04/28 PHP
基于MySQL到MongoDB简易对照表的详解
2013/06/03 PHP
PHP安装threads多线程扩展基础教程
2015/11/17 PHP
PHP的mysqli_ssl_set()函数讲解
2019/01/23 PHP
Laravel6.0.4中将添加计划任务事件的方法步骤
2019/10/15 PHP
音乐播放用的的几个函数
2006/09/07 Javascript
在你的网页中嵌入外部网页的方法
2007/04/02 Javascript
基于jQuery的合并表格中相同文本的相邻单元格的代码
2011/04/06 Javascript
JS对img进行操作(换图片/切图/轮换/停止)
2013/04/17 Javascript
jquery默认校验规则整理
2014/03/24 Javascript
5种处理js跨域问题方法汇总
2014/12/04 Javascript
Bootstrap作品展示站点实战项目2
2016/10/14 Javascript
js 实现一些跨浏览器的事件方法详解及实例
2016/10/27 Javascript
JavaScript实现同一个页面打开多张图片
2016/12/29 Javascript
JS交互点击WKWebView中的图片实现预览效果
2018/01/05 Javascript
vue使用Font Awesome的方法步骤
2019/02/26 Javascript
js实现小球在页面规定的区域运动
2020/06/16 Javascript
解决element-ui的下拉框有值却无法选中的情况
2020/11/07 Javascript
Python for Informatics 第11章之正则表达式(二)
2016/04/21 Python
requests和lxml实现爬虫的方法
2017/06/11 Python
TensorFlow损失函数专题详解
2018/04/26 Python
Python实现点阵字体读取与转换的方法
2019/01/29 Python
Flask配置Cors跨域的实现
2019/07/12 Python
对django的User模型和四种扩展/重写方法小结
2019/08/17 Python
VSCode中自动为Python文件添加头部注释
2019/11/14 Python
Pytorch中膨胀卷积的用法详解
2020/01/07 Python
keras实现VGG16方式(预测一张图片)
2020/07/07 Python
捷克原创男装和女装购物网站:Bolf.cz
2018/04/28 全球购物
杰夫·班克斯男士服装网上商店:Jeff Banks
2019/10/24 全球购物
求职推荐信范文
2013/12/01 职场文书
学雷锋志愿服务月活动总结
2014/03/09 职场文书
产品销售计划书
2014/05/04 职场文书
学校清洁工岗位职责
2015/04/15 职场文书
清明节文明祭祀倡议书
2015/04/28 职场文书
学校捐书活动总结
2015/05/08 职场文书
新年晚会主持词开场白
2015/05/28 职场文书