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 相关文章推荐
node.js中的fs.writeFileSync方法使用说明
Dec 14 Javascript
原生 JS Ajax,GET和POST 请求实例代码
Jun 08 Javascript
AngularJS控制器之间的数据共享及通信详解
Aug 01 Javascript
简述Angular 5 快速入门
Nov 04 Javascript
除Console.log()外更多的Javascript调试命令
Jan 24 Javascript
JavaScript引用类型Array实例分析
Jul 24 Javascript
vue组件之间通信方式实例总结【8种方式】
Feb 22 Javascript
vux-scroller实现移动端上拉加载功能过程解析
Oct 08 Javascript
js实现漂亮的星空背景
Nov 01 Javascript
vue中实现动态生成二维码的方法
Feb 21 Javascript
JavaScript中使用Spread运算符的八种方法总结
Jun 18 Javascript
浅谈es6中的元编程
Dec 01 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全概率运算函数(优化版) Webgame开发必备
2011/07/04 PHP
ThinkPHP模板输出display用法分析
2014/11/26 PHP
thinkphp微信开发(消息加密解密)
2015/12/02 PHP
PHP面向对象程序设计组合模式与装饰模式详解
2016/12/02 PHP
基于jquery自定义图片热区效果
2012/07/21 Javascript
js中一维数组和二位数组中的几个问题示例说明
2014/07/17 Javascript
jQuery随机密码生成的方法
2015/03/09 Javascript
javascript模拟命名空间
2015/04/17 Javascript
用JS实现图片轮播效果代码(一)
2016/06/26 Javascript
jQuery实现的checkbox级联选择下拉菜单效果示例
2016/12/26 Javascript
javascript实现二叉树的代码
2017/06/08 Javascript
自适应布局meta标签中viewport、content、width、initial-scale、minimum-scale、maximum-scale总结
2017/08/18 Javascript
JS获取url参数,JS发送json格式的POST请求方法
2018/03/29 Javascript
atom-design(Vue.js移动端组件库)手势组件使用教程
2019/05/16 Javascript
JS 数组和对象的深拷贝操作示例
2020/06/06 Javascript
Python中Iterator迭代器的使用杂谈
2016/06/20 Python
Python3编程实现获取阿里云ECS实例及监控的方法
2017/08/18 Python
Python 绘图库 Matplotlib 入门教程
2018/04/19 Python
Python中format()格式输出全解
2019/04/12 Python
基于python二叉树的构造和打印例子
2019/08/09 Python
python网络爬虫 Scrapy中selenium用法详解
2019/09/28 Python
Python3.7 基于 pycryptodome 的AES加密解密、RSA加密解密、加签验签
2019/12/04 Python
Python reques接口测试框架实现代码
2020/07/28 Python
Black Halo官方网站:购买连衣裙、礼服和连体裤
2018/06/13 全球购物
毕业生求职自荐书范文
2014/03/27 职场文书
建设投标担保书
2014/05/13 职场文书
幽默自我介绍演讲稿
2014/08/21 职场文书
暑假社会实践证明格式
2014/10/28 职场文书
教师党员学习十八届四中全会思想汇报
2014/11/03 职场文书
节约用电通知
2015/04/25 职场文书
幽默导游词开场白
2015/05/29 职场文书
宾馆安全管理制度
2015/08/06 职场文书
会议承办单位欢迎词
2019/07/09 职场文书
Python爬取某拍短视频
2021/06/11 Python
Oracle 临时表空间SQL语句的实现
2021/09/25 Oracle
 Redis 串行生成顺序编码的方法实现
2022/04/03 Redis