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 相关文章推荐
javascript Array.remove() 数组删除
Aug 06 Javascript
Javascript下IE与Firefox下的差异兼容写法总结
Jun 18 Javascript
如何使用JS获取IE上传文件路径(IE7,8)
Jul 08 Javascript
jquery 中ajax执行的优先级
Jun 22 Javascript
AngularJS入门教程之服务(Service)
Jul 27 Javascript
使用webpack搭建react开发环境的方法
May 15 Javascript
jQuery获取随机颜色的实例代码
May 21 jQuery
对layui中表单元素的使用详解
Aug 15 Javascript
layer弹出层全屏及关闭方法
Aug 17 Javascript
如何在Node和浏览器控制台中打印彩色文字
Jan 09 Javascript
微信小程序文章详情功能完整实例
Jun 03 Javascript
微信小程序input抖动问题的修复方法
Mar 03 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函数的常用方法及注意之处小结
2011/07/10 PHP
PHP笔记之:日期函数的使用介绍
2013/04/24 PHP
简单的php新闻发布系统教程
2014/05/09 PHP
PHP基于接口技术实现简单的多态应用完整实例
2017/04/26 PHP
详解thinkphp中的volist标签
2018/01/15 PHP
PHP7.1实现的AES与RSA加密操作示例
2018/06/15 PHP
YII分模块加载路由的实现方法
2018/10/01 PHP
重写javascript中window.confirm的行为
2012/10/21 Javascript
javascript限制用户只能输汉字中文的方法
2014/11/20 Javascript
简单的JS时钟实例讲解
2016/01/13 Javascript
jQuery之简单的表单验证实例
2016/07/07 Javascript
JQuery Ajax WebService传递参数的简单实例
2016/11/02 Javascript
Node学习记录之cluster模块
2017/05/31 Javascript
详解webpack异步加载业务模块
2017/06/23 Javascript
基于node.js express mvc轻量级框架实践
2017/09/14 Javascript
浅谈Vue Element中Select下拉框选取值的问题
2018/03/01 Javascript
Angular5中状态管理的实现
2018/09/03 Javascript
详解Vue中数组和对象更改后视图不刷新的问题
2018/09/21 Javascript
Vue中的Props(不可变状态)
2018/09/29 Javascript
解析原来浏览器原生支持JS Base64编码解码
2019/08/12 Javascript
NodeJS 文件夹拷贝以及删除功能
2019/09/03 NodeJs
ES6之Proxy的get方法详解
2019/10/11 Javascript
[52:57]2014 DOTA2国际邀请赛中国区预选赛 LGD-CDEC VS HGT
2014/05/21 DOTA
Python操作MongoDB数据库的方法示例
2018/01/04 Python
Python使用遗传算法解决最大流问题
2018/01/29 Python
python二进制读写及特殊码同步实现详解
2019/10/11 Python
python plotly画柱状图代码实例
2019/12/13 Python
Python-opencv 双线性插值实例
2020/01/17 Python
Python如何使用vars返回对象的属性列表
2020/10/17 Python
python 检测图片是否有马赛克
2020/12/01 Python
Pandas中两个dataframe的交集和差集的示例代码
2020/12/13 Python
办公室打字员岗位职责
2014/04/16 职场文书
应届本科毕业生求职信
2014/07/23 职场文书
幸福终点站观后感
2015/06/04 职场文书
MyBatis核心源码深度剖析SQL语句执行过程
2022/05/20 Java/Android
python热力图实现的完整实例
2022/06/25 Python