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 树控件 比较好用
Jun 11 Javascript
用console.table()调试javascript
Sep 04 Javascript
js表格排序实例分析(支持int,float,date,string四种数据类型)
May 06 Javascript
javascript实现的登陆遮罩效果汇总
Nov 09 Javascript
谈谈我对JavaScript DOM事件的理解
Dec 18 Javascript
jQuery实现的文字hover颜色渐变效果实例
Feb 20 Javascript
解决JS内存泄露之js对象和dom对象互相引用问题
Jun 25 Javascript
React native ListView 增加顶部下拉刷新和底下点击刷新示例
Apr 27 Javascript
Vue动态控制input的disabled属性的方法
Jun 26 Javascript
详解KOA2如何手写中间件(装饰器模式)
Oct 11 Javascript
vue实现点击隐藏与显示实例分享
Feb 13 Javascript
Vue全局loading及错误提示的思路与实现
Aug 09 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程序
2012/02/04 PHP
PHP通过session id 实现session共享和登录验证的代码
2012/06/03 PHP
header中Content-Disposition的作用与使用方法
2012/06/13 PHP
php正则表达式获取内容所有链接
2015/07/24 PHP
PHP简单实现断点续传下载的方法
2015/09/25 PHP
php集成开发环境详解
2019/09/24 PHP
图片上传即时显示缩略图的js代码
2009/05/27 Javascript
javascript 短路法代码精简
2009/08/20 Javascript
js 程序执行与顺序实现详解
2013/05/13 Javascript
js监听键盘事件示例代码
2013/07/26 Javascript
使用AngularJS和PHP的Laravel实现单页评论的方法
2015/06/19 Javascript
js获取一组日期中最近连续的天数
2017/05/25 Javascript
element ui里dialog关闭后清除验证条件方法
2018/02/26 Javascript
webpack css加载和图片加载的方法示例
2018/09/11 Javascript
JS原生带缩略图的图片切换效果
2018/10/10 Javascript
微信小程序云开发之使用云存储
2019/05/17 Javascript
vue 设置 input 为不可以编辑的实现方法
2019/09/19 Javascript
element-ui 远程搜索组件el-select在项目中组件化的实现代码
2019/12/04 Javascript
[02:35]DOTA2超级联赛专访XB 难忘一年九冠称王
2013/06/20 DOTA
布同 Python中文问题解决方法(总结了多位前人经验,初学者必看)
2011/03/13 Python
在VS Code上搭建Python开发环境的方法
2018/04/06 Python
TensorFlow打印tensor值的实现方法
2018/07/27 Python
Django REST Framework之频率限制的使用
2019/09/29 Python
将tensorflow模型打包成PB文件及PB文件读取方式
2020/01/23 Python
Python爬虫如何破解JS加密的Cookie
2020/11/19 Python
英国最大的百货公司:Harrods
2016/08/18 全球购物
优衣库美国官网:UNIQLO美国
2018/04/14 全球购物
Harman Audio官方商店:购买JBL、Harman Kardon、Infinity和AKG
2019/12/05 全球购物
韩语专业本科生求职信
2013/10/01 职场文书
关于毕业的广播稿
2014/01/10 职场文书
团拜会策划方案
2014/06/07 职场文书
机械工程及自动化专业求职信
2014/09/03 职场文书
党风廉正建设责任书
2015/01/29 职场文书
毕业实习证明范本
2015/06/16 职场文书
2019新学期家长会工作计划
2019/08/21 职场文书
Python标准库之typing的用法(类型标注)
2021/06/02 Python