javascript实现贪吃蛇经典游戏


Posted in Javascript onApril 10, 2020

js面向对象编程之贪吃蛇,供大家参考,具体内容如下

首先:面向对象编程,我们要找到项目中具体的对象,此处为(食物(food),蛇(snake),游戏本身(game))也可不把游戏本身作为对象,逻辑体现出来即可。

接着分析每个对象的具体的属性及方法:
1)food 对象:属性有:位置,大小,颜色;方法有:渲染在页面,随机不同位置生成;
2)snake对象:属性有:位置,大小,总节数(计分方便),颜色;方法有:渲染在页面,移动(移动过程中判断其它)。
3)game对象:游戏逻辑的编写;

ok 开敲:

1)简单的静态页面编写(地图)

(1)html

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <link rel="stylesheet" href="css/index.css" >
 <script src="js/food.js"></script>
 <script src="js/snake.js"></script>
 <script src="js/game.js"></script>
 <script src="js/main.js"></script>
 <title>贪吃蛇</title>
</head>
<body>
 <div class="map"></div>
</body>
</html>

(2)css(如果用边框来作为限制的边界,那么box-sizing属性是必不可少的(以免食物和蛇头坐标之间存在误差))

* {
 margin: 0;
 padding: 0;
}

.map {
 position: relative;
 height: 600px;
 width: 800px;
 border: 1px solid #333;
 margin: 0 auto;
 /* 盒子模型去除边框 */
 box-sizing: border-box;
}

2)food对象编写(细节处含注释)

//cwen加载页面所有元素
window.addEventListener('load', function() {

 //cwen自调用函数,开启一个新的作用域,避免命名冲突
 (function() {

 //cwen定义全局变量
 //实物数组
 var elements = [];
 //cwen实物
 function Food(options) {
  options = options || {};
  this.x = options.x || 0;
  this.y = options.y || 0;
  this.width = options.width || 20;
  this.height = options.height || 20;
  this.color = options.color || 'yellow';
 }


 //cwen随机数函数
 function getRandom(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
 }
 //cwen渲染
 Food.prototype.render = function(map) {
  //删除之前的食物
  remove();
  //todo动态创建div实物
  var div = document.createElement('div');
  map.appendChild(div);
  //把div添加给数组
  elements.push(div);
  //todo随机设置x,y的值(实物的位置)-----在map中生成随机位置
  // ! 值 = Math.floor(Math.random() * 可能值得总数 + 第一个可能的值)
  this.x = getRandom(0, map.offsetWidth / this.width - 1) * this.width;
  this.y = getRandom(0, map.offsetHeight / this.height - 1) * this.height;
  div.style.position = 'absolute';
  div.style.left = this.x + 'px';
  div.style.top = this.y + 'px';
  div.style.width = this.width + 'px';
  div.style.height = this.height + 'px';
  div.style.backgroundColor = this.color;
 }

 function remove() {
  //为了删除干净,从索引最大的开始循环删除
  for (var i = elements.length - 1; i >= 0; i--) {
  //删除遍历到的div
  elements[i].parentNode.removeChild(elements[i]);
  //删除数组中的元素1)第几个开始,2)要删除个数
  elements.splice(i, 1);
  }
 }

 //把Food开放出去
 window.Food = Food;
 })()
 
 //cwen测试
 // var map = document.querySelector('.map');
 // var options = { x: 20, y: 20, width: 30, height: 30, color: 'green' };
 // //todo不传值默认为自定义food
 // var food = new Food();
 // food.render(map);
})

3)snake对象编写()

window.addEventListener('load', function() {
 (function() {
 //记录蛇的每一节
 var elements = [];
 //cwen立即执行函数,开启新的作用于,避免命名冲突
 function Snake(options) {
  options = options || {};
  //对象(蛇)每节的大小
  this.width = options.width || 20;
  this.height = options.height || 20;
  //cwen蛇的总节数(计分)
  this.mark = options.mark || 0;
  //对象的移动方向
  this.direction = options.direction || 'right';
  //对象的身体(蛇节)
  this.kont = [{ x: 3, y: 2, color: 'red' }, { x: 2, y: 2, color: 'black' }, { x: 1, y: 2, color: 'black' }];
 }

 //cwen渲染对象
 Snake.prototype.render = function(map) {
  //移除之前的蛇
  remove();
  //循环输出对象的身体(蛇节)
  for (var i = 0, len = this.kont.length; i < len; i++) {
  var obj = this.kont[i];
  var div = document.createElement('div');
  map.appendChild(div);
  //将蛇节添加入数组
  elements.push(div);
  //添加样式
  div.style.position = 'absolute';
  div.style.width = this.width + 'px';
  div.style.height = this.height + 'px';
  div.style.left = obj.x * this.width + 'px';
  div.style.top = obj.y * this.height + 'px';
  div.style.backgroundColor = obj.color;
  }
 }

 //cwen控制蛇移动的方法
 //todo传参food,map 在game中调用move方法也要传入相应参数
 Snake.prototype.move = function(food, map) {
  //控制蛇节的移动(当前蛇节到下一个蛇节的位置)
  for (var i = this.kont.length - 1; i > 0; i--) {
  this.kont[i].x = this.kont[i - 1].x;
  this.kont[i].y = this.kont[i - 1].y;
  }

  //判断并控制蛇头移动,判断蛇头移动方向
  var head = this.kont[0];
  switch (this.direction) {
  case 'right':
   head.x += 1;
   break;
  case 'left':
   head.x -= 1;
   break;
  case 'top':
   head.y -= 1;
   break;
  case 'bottom':
   head.y += 1;
   break;
  }


  //蛇头碰到食物时处理
  // cwen判断蛇头是否和食物坐标重合
  var headX = head.x * this.width;
  var headY = head.y * this.height;
  if (headX == food.x && headY == food.y) {
  //1,增加蛇节(找到最后一根蛇节,然后添加给创建的蛇数组)
  var last = this.kont[this.kont.length - 1];
  this.kont.push({ x: last.x, y: last.y, color: last.color });
  //cwen求出蛇节的总个数(计分)
  var mark = this.mark++;
  //2,重新渲染食物
  food.render(map);
  }
 }


 //删除之前的蛇
 function remove() {
  for (var i = elements.length - 1; i >= 0; i--) {
  elements[i].parentNode.removeChild(elements[i]);
  elements.splice(i, 1);
  }
 }

 //把Snake构造函数暴露出去
 window.Snake = Snake;
 })()
 //测试
 // var map = document.querySelector('.map');
 // var snake = new Snake();
 // snake.render(map);
})

4)game对象编写,其中一个为无敌版(含细节注释)

window.addEventListener('load', function() {
 (function() {
 //改变计时器内this指向
 var that;

 function Game(map) {
  // var options = { x: 20, y: 20, width: 30, height: 30, color: 'green' };
  this.food = new Food();
  this.snake = new Snake();
  this.map = map;
  that = this;
 }
 //cwen渲染
 Game.prototype.start = function() {
  // 1.把食物和蛇渲染到页面
  this.food.render(this.map);
  this.snake.render(this.map);
  // 2.游戏逻辑编写
  //让蛇动起来
  //判断地图边界
  // runSnake();
  //todo判断玩法(两种模式,原理一样)
  goInput();
  //通过键盘控制蛇头方向
  //! keydown();
  //蛇头碰到食物时处理
  //在snake.js中判断
 }

 function goInput() {
  var it = prompt('try:\n 经典玩法请按1\n 无敌玩法请输入(博主最帅)\n')
  if (it == 1) {
  runSnake();
  keydown();
  } else if (it == '博主最帅') {
  runSnake1();
  keydown1();
  } else {
  alert('you input could not be found!!!');
  goInput();
  }
 }


 //让蛇动起来
 function runSnake() {
  var timeId = setInterval(function() {
  // var a = mark;
  that.snake.move(that.food, that.map);
  that.snake.render(that.map);

  //判断地图边界
  var maxX = (that.map.offsetWidth) / that.snake.width;
  var maxY = (that.map.offsetHeight) / that.snake.height;
  var headX = that.snake.kont[0].x;
  var headY = that.snake.kont[0].y;
  if (headX < 0 || headX >= maxX) {
   alert('Game Over ' + '得分为 ' + that.snake.mark);
   clearInterval(timeId);
  } else if (headY < 0 || headY >= maxY) {
   alert('Game Over ' + '成绩为 ' + that.snake.mark);
   clearInterval(timeId);
  }
  }, 150)
 }


 //无敌版本蛇运动
 function runSnake1() {
  var timeId1 = setInterval(function() {
  that.snake.move(that.food, that.map);
  that.snake.render(that.map);

  //判断地图边界
  var maxX = (that.map.offsetWidth - that.snake.width) / that.snake.width;
  var maxY = (that.map.offsetHeight - that.snake.height) / that.snake.height;
  var headX = that.snake.kont[0].x;
  var headY = that.snake.kont[0].y;

  if (headX < 0) {
   that.snake.kont[0].x = (that.map.offsetWidth - that.snake.width) / that.snake.width;
  } else if (headX > maxX) {
   that.snake.kont[0].x = 0;
  } else if (headY < 0) {
   that.snake.kont[0].y = (that.map.offsetHeight - that.snake.height) / that.snake.height;
  } else if (headY > maxY) {
   that.snake.kont[0].y = 0;
  }
  }, 50)
 }



 //通过键盘控制蛇头方向
 function keydown() {
  document.addEventListener('keydown', function(e) {
  //通过事件对象判断按了哪个键 37left,38top,39right,40bottom
  // console.log(e.keyCode);
  //其在走的同时按下反方向无用
  if (e.keyCode == 37 && that.snake.direction != 'right') {
   that.snake.direction = 'left';
  } else if (e.keyCode == 38 && that.snake.direction != 'bottom') {
   that.snake.direction = 'top';
  } else if (e.keyCode == 39 && that.snake.direction != 'left') {
   that.snake.direction = 'right';
  } else if (e.keyCode == 40 && that.snake.direction != 'top') {
   that.snake.direction = 'bottom';
  }
  });
 }


 function keydown1() {
  document.addEventListener('keydown', function(e) {
  //通过事件对象判断按了哪个键 37left,38top,39right,40bottom
  // console.log(e.keyCode);
  //无敌版本四面八方任你行
  if (e.keyCode == 37) {
   that.snake.direction = 'left';
  } else if (e.keyCode == 38) {
   that.snake.direction = 'top';
  } else if (e.keyCode == 39) {
   that.snake.direction = 'right';
  } else if (e.keyCode == 40) {
   that.snake.direction = 'bottom';
  }
  });
 }


 //把Game开放
 window.Game = Game;
 })()
})

5)main开启游戏

window.addEventListener('load', function() {
 (function(window, undefind) {
 //测试
 var map = document.querySelector('.map');
 var game = new Game(map);
 game.start();

 })(window, undefined)
})

last but not least
*建议把所有js文件写在同一个js文件中,可以大大提高加载速度。注意在每个立即执行函数前加上‘ ;',以免出错。

小编还为大家准备了精彩的专题:javascript经典小游戏汇总

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

Javascript 相关文章推荐
JS 实现Json查询的方法实例
Apr 12 Javascript
最短的IE判断var ie=!-[1,]分析
May 28 Javascript
浅谈Sizzle的“编译原理”
Apr 14 Javascript
bootstrap输入框组使用方法
Feb 07 Javascript
深入理解js 中async 函数的含义和用法
May 13 Javascript
vue2.0学习之axios的封装与vuex介绍
May 28 Javascript
js实现购物车功能
Jun 12 Javascript
vue如何进行动画的封装
Sep 26 Javascript
vue-cli中vue本地实现跨域调试接口
Jan 16 Javascript
浅谈一种让小程序支持JSX语法的新思路
Jun 16 Javascript
JavaScript arguments.callee作用及替换方案详解
Sep 02 Javascript
js实现3D粒子酷炫动态旋转特效
Sep 13 Javascript
javascript设计模式 ? 原型模式原理与应用实例分析
Apr 10 #Javascript
Quasar Input:type=&quot;number&quot; 去掉上下小箭头 实现加减按钮样式功能
Apr 09 #Javascript
vue中的过滤器及其时间格式化问题
Apr 09 #Javascript
微信小程序保存图片到相册权限设置
Apr 09 #Javascript
微信小程序仿通讯录功能
Apr 09 #Javascript
vue cli4下环境变量和模式示例详解
Apr 09 #Javascript
微信小程序实现组件顶端固定或底端固定效果(不随滚动而滚动)
Apr 09 #Javascript
You might like
php爬取天猫和淘宝商品数据
2018/02/23 PHP
javascript操作文本框readOnly
2007/05/15 Javascript
基于jQuery的实现简单的分页控件
2010/10/10 Javascript
json的前台操作和后台操作实现代码
2012/01/20 Javascript
到处都是jQuery选择器的年代 不了解它们的性能,行吗
2012/06/18 Javascript
javascript实现百度地图鼠标滑动事件显示、隐藏
2015/04/02 Javascript
JS针对浏览器窗口关闭事件的监听方法集锦
2016/06/24 Javascript
Node.js下自定义错误类型详解
2016/10/17 Javascript
H5移动端图片压缩上传开发流程
2016/11/09 Javascript
AngularJS服务service用法总结
2016/12/13 Javascript
jquery uploadify如何取消已上传成功文件
2017/02/08 Javascript
JavaScript学习总结(一) ECMAScript、BOM、DOM(核心、浏览器对象模型与文档对象模型)
2018/01/07 Javascript
微信小程序中实现手指缩放图片的示例代码
2018/03/13 Javascript
原生JS实现的碰撞检测功能示例
2018/05/18 Javascript
Vue SPA单页应用首屏优化实践
2018/06/28 Javascript
vue+Vue Router多级侧导航切换路由(页面)的实现代码
2018/12/20 Javascript
Postman无法正常返回结果问题解决
2020/08/28 Javascript
用实例说明python的*args和**kwargs用法
2013/11/01 Python
Python模拟登录12306的方法
2014/12/30 Python
Python选择排序、冒泡排序、合并排序代码实例
2015/04/10 Python
Python 性能优化技巧总结
2016/11/01 Python
python snownlp情感分析简易demo(分享)
2017/06/04 Python
python日期时间转为字符串或者格式化输出的实例
2018/05/29 Python
python用opencv批量截取图像指定区域的方法
2019/01/24 Python
使用python telnetlib批量备份交换机配置的方法
2019/07/25 Python
django将数组传递给前台模板的方法
2019/08/06 Python
使用CSS3来代替JS实现交互
2017/08/10 HTML / CSS
Desigual德国官网:在线购买原创服装
2018/03/27 全球购物
GMP办公室主任岗位职责
2014/03/14 职场文书
写求职信要注意什么问题
2014/04/12 职场文书
优秀班集体先进事迹材料
2014/05/28 职场文书
新闻稿格式范文
2015/07/18 职场文书
早上好问候语大全
2015/11/10 职场文书
MySQL8.0无法启动3534的解决方法
2021/06/03 MySQL
pytorch实现加载保存查看checkpoint文件
2022/07/15 Python
django项目、vue项目部署云服务器的详细过程
2022/07/23 Servers