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 相关文章推荐
选择TreeView控件的树状数据节点的JS方法(jquery)
Feb 06 Javascript
javascript权威指南 学习笔记之变量作用域分享
Sep 28 Javascript
JavaScript表达式:URL 协议介绍
Mar 10 Javascript
如何实现textarea里的不同文本显示不同颜色
Jan 20 Javascript
javascript中对变量类型的判断方法
Aug 09 Javascript
js的各种排序算法实现(总结)
Jul 23 Javascript
jQuery加载及解析XML文件的方法实例分析
Jan 22 Javascript
基于JavaScript实现焦点图轮播效果
Mar 27 Javascript
JS计算两个数组的交集、差集、并集、补集(多种实现方式)
May 21 Javascript
JavaScript箭头函数中的this详解
Jun 19 Javascript
vue动态绘制四分之三圆环图效果
Sep 03 Javascript
JavaScript setTimeout()基本用法有哪些
Nov 04 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 $_SERVER当前完整url的写法
2009/11/12 PHP
Yii框架中 find findAll 查找出制定的字段的方法对比
2014/09/10 PHP
php正则表达式验证(邮件地址、Url地址、电话号码、邮政编码)
2016/03/14 PHP
PHP利用百度ai实现文本和图片审核
2019/05/08 PHP
JavaScript 常用函数
2009/12/30 Javascript
禁止js文件缓存的代码
2010/04/09 Javascript
JavaScript 类的定义和引用 JavaScript高级培训 自定义对象
2010/04/27 Javascript
通过jquery还原含有rowspan、colspan的table的实现方法
2012/02/10 Javascript
jQuery实现 注册时选择阅读条款 左右移动
2013/04/11 Javascript
使用JavaScript获取地址栏参数的方法
2014/12/19 Javascript
javascript实现动态加载CSS
2015/01/26 Javascript
JavaScript对象反射用法实例
2015/04/17 Javascript
jQuery遮罩层效果实例分析
2016/01/14 Javascript
结合代码图文讲解JavaScript中的作用域与作用域链
2016/07/05 Javascript
KnockoutJS 3.X API 第四章之数据控制流component绑定
2016/10/10 Javascript
详解js跨域请求的两种方式,支持post请求
2018/05/05 Javascript
js实现带箭头的进度流程
2020/03/26 Javascript
JavaScript 实现自己的安卓手机自动化工具脚本(推荐)
2020/05/13 Javascript
JavaScript实现拖拽和缩放效果
2020/08/24 Javascript
python检测远程udp端口是否打开的方法
2015/03/14 Python
基于python实现简单日历
2018/07/28 Python
python多个模块py文件的数据共享实例
2019/01/11 Python
[机器视觉]使用python自动识别验证码详解
2019/05/16 Python
Python中filter与lambda的结合使用详解
2019/12/24 Python
python操作gitlab API过程解析
2019/12/27 Python
Python类反射机制使用实例解析
2019/12/30 Python
Interhome丹麦:在线预订度假屋和公寓
2019/07/18 全球购物
应届生高等护理求职信
2013/10/12 职场文书
公司委托书范本5篇
2014/09/20 职场文书
人事局接收函
2015/01/30 职场文书
2015年感恩节演讲稿(优选篇)
2015/03/20 职场文书
导游词之岳阳楼
2019/09/25 职场文书
JavaScript的function函数详细介绍
2021/11/20 Javascript
以MySQL5.7为例了解一下执行计划
2022/04/13 MySQL
Win11 21h2可以升级22h2吗?看看你的电脑符不符合要求
2022/07/07 数码科技
Win10开机修复磁盘错误怎么跳过?Win10关闭开机磁盘检查的方法
2022/09/23 数码科技