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 png图片(有含有透明)在IE6中为什么不透明了
Feb 07 Javascript
jQuery 学习第七课 扩展jQuery的功能 插件开发
May 17 Javascript
javascript获取flash版本号的方法
Nov 20 Javascript
使用mouse事件实现简单的鼠标经过特效
Jan 30 Javascript
Node.js中看JavaScript的引用
Apr 22 Javascript
深入解析Vue 组件命名那些事
Jul 18 Javascript
JS实现多物体运动的方法详解
Jan 23 Javascript
详解使用React.memo()来优化函数组件的性能
Mar 19 Javascript
js实现移动端tab切换时下划线滑动效果
Sep 08 Javascript
html+jQuery实现拖动滑块图片拼图验证码插件【移动端适用】
Sep 10 jQuery
jQuery实现手风琴效果(蒙版)
Jan 11 jQuery
node中短信api实现验证码登录的示例代码
Jan 20 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将html转成wml的WAP标记语言实例
2015/07/08 PHP
laravel创建类似ThinPHP中functions.php的全局函数
2016/11/26 PHP
tp5(thinkPHP5框架)captcha验证码配置及验证操作示例
2019/05/28 PHP
基于jquery实现的定时显示与隐藏div广告的实现代码
2013/08/22 Javascript
Jquery实现的tab效果可以指定默认显示第几页
2013/10/16 Javascript
js(jQuery)获取时间的方法及常用时间类搜集
2013/10/23 Javascript
浅谈下拉菜单中的Option对象
2015/05/10 Javascript
使用AngularJS制作一个简单的RSS阅读器的教程
2015/06/18 Javascript
JS实现点击按钮控制Div变宽、增高及调整背景色的方法
2015/08/05 Javascript
ClearTimeout消除闪动实例代码
2016/02/29 Javascript
带有定位当前位置的百度地图前端web api实例代码
2016/06/21 Javascript
Node.js连接MongoDB数据库产生的问题
2017/02/08 Javascript
js is_valid_filename验证文件名的函数
2017/07/19 Javascript
纯JS实现的读取excel文件内容功能示例【支持所有浏览器】
2018/06/23 Javascript
Vue Router去掉url中默认的锚点#
2018/08/01 Javascript
详解Vue.js使用Swiper.js在iOS
2018/09/10 Javascript
微信小程序模板消息推送的两种实现方式
2019/08/27 Javascript
JavaScript构造函数原理及实现流程解析
2020/11/19 Javascript
布同 Python中文问题解决方法(总结了多位前人经验,初学者必看)
2011/03/13 Python
谈谈如何手动释放Python的内存
2016/12/17 Python
python文件操作之批量修改文件后缀名的方法
2018/08/10 Python
处理python中多线程与多进程中的数据共享问题
2019/07/28 Python
python实现对服务器脚本敏感信息的加密解密功能
2019/08/13 Python
Python性能分析工具Profile使用实例
2019/11/19 Python
SHEIN香港:价格实惠的女性时尚服装
2018/08/14 全球购物
node中使用shell脚本的方法步骤
2021/03/23 Javascript
营销总经理的岗位职责
2013/12/15 职场文书
学生会主席就职演讲稿
2014/01/14 职场文书
模具数控专业自荐信
2014/01/27 职场文书
销售冠军获奖感言
2014/02/03 职场文书
新郎结婚保证书
2015/02/26 职场文书
春节晚会开场白
2015/05/29 职场文书
建党伟业电影观后感
2015/06/01 职场文书
2016高中社会实践心得体会范文
2016/01/14 职场文书
Python基础 括号()[]{}的详解
2021/11/07 Python
Java由浅入深通关抽象类与接口(上篇)
2022/04/26 Java/Android