资讯专栏INFORMATION COLUMN

回归原生,使用javascript编写小游戏 --- 贪食蛇

AlienZHOU / 3162人阅读

摘要:将应用抽象成一个对象。地图使用一个二维数组作为结构。生成食物的范围。蛇碰到墙壁计算出穿过墙的范围蛇碰到自己的身体蛇吃到食物,长度加一并生成新的食物监听键盘事件。对上下左右移动做出反应。

需求分析

生成地图。

将应用抽象成一个对象。

地图使用一个二维数组作为结构。

生成食物。

生成食物的范围。

食物不能和身体生成位置重合。

生成蛇,开始移动。

蛇碰到墙壁,计算出穿过墙的范围.

蛇碰到自己的身体,Game Over .

蛇吃到食物,长度加一,并生成新的食物

监听键盘事件。

对上下左右移动做出反应。

代码实现(也可以查看 github ) html (index.html)

</>复制代码

  1. Document
css (./style/index.css)

</>复制代码

  1. * {
  2. margin: 0;
  3. padding: 0;
  4. }
  5. .wrap{
  6. display: flex;
  7. justify-content: center;
  8. align-content: center;
  9. }
  10. #container{
  11. width: 100%;
  12. text-align: center;
  13. }
  14. #container div{
  15. /* width: 20px;
  16. height: 20px; */
  17. float: left;
  18. border: 1px solid #000;
  19. }
js(./js/index.js)

</>复制代码

  1. (function(self){
  2. function GreedySnake(gridXN,gridYN){
  3. // 地图
  4. this.gridXN = gridXN >= 10 ? gridXN : 10;
  5. this.gridYN = gridYN >= 10 ? gridYN : 10;
  6. this.gridSize = 20; //每个格子的固定大小
  7. this.map = []; //保存地图中dom对象的二维数组
  8. this.container = document.getElementById("container");
  9. // 食物属性
  10. this.food = null;
  11. this.foodX = null;
  12. this.foodY = null;
  13. // 蛇
  14. this.snake = [];//将蛇抽象成一个二维列表,列为身体长度,排为坐标数组
  15. this.snakeLen = null ; //默认蛇长为3
  16. // 初始蛇头坐标
  17. this.snakeHead = []
  18. // 蛇的移动方向
  19. this.direction = "top"
  20. // 速度
  21. this.speed = 1 ;
  22. this.timer = null
  23. }
  24. GreedySnake.prototype.init = function(){
  25. this.initMap();
  26. this.createSnake();
  27. this.createFood();
  28. this.snakeMove()
  29. this.listenKeyBoardEvents()
  30. }
  31. GreedySnake.prototype.restart = function(gridXN,gridYN){
  32. // 地图
  33. this.gridXN = null
  34. this.gridYN = null
  35. this.gridSize = null
  36. this.map = null
  37. this.container = null
  38. // 食物属性
  39. this.food = null;
  40. this.foodX = null;
  41. this.foodY = null;
  42. // 蛇
  43. this.snake = null;
  44. this.snakeLen = null;
  45. // 初始蛇头坐标
  46. this.snakeHead = null;
  47. // 蛇的移动方向
  48. this.direction = null;
  49. // 速度
  50. this.speed = null;
  51. }
  52. // 初始化地图
  53. GreedySnake.prototype.initMap = function(){
  54. var gridYN = this.gridYN,
  55. gridXN = this.gridXN,
  56. w = gridXN * this.gridSize + gridXN + 1 ,
  57. h = gridYN * this.gridSize + gridYN + 1;
  58. this.container.style.width = w + "px";
  59. this.container.style.height = h + "px";
  60. for(let y = 0 ; y < gridXN ; y++){
  61. this.map[y] = [] //初始化二维数组
  62. for(let x = 0 ; x < gridYN ; x++){
  63. this.createGrid(x,y)
  64. }
  65. }
  66. }
  67. // 创建每一个格子,x轴格子索引,y轴格子索引
  68. GreedySnake.prototype.createGrid = function(idxX,idxY){
  69. // 当idxY > 0 时,对应的grid的向左移动1px,将格子之间的线重合;
  70. // 当idxX > 0 时,对应的grid的向上移动1px,将格子之间的线重合;
  71. let grid = document.createElement("div");
  72. grid.style.width = this.gridSize + "px";
  73. grid.style.height = this.gridSize + "px";
  74. this.map[idxY][idxX] = grid
  75. if(idxX > 0 ){
  76. grid.style.marginLeft = "-1px";
  77. }
  78. if(idxY > 0 ){
  79. grid.style.marginTop = "-1px";
  80. }
  81. this.container.appendChild(grid);
  82. }
  83. // 创建食物:原理就是根据在范围内的格子数,生成两个随机数,作为元素的坐标
  84. GreedySnake.prototype.createFood = function(){
  85. var gridYN = this.gridYN,
  86. gridXN = this.gridXN,
  87. temp = null ,
  88. flag = true;
  89. this.foodX = Math.floor(Math.random() * gridXN); //缓存
  90. this.foodY = Math.floor(Math.random() * gridYN);
  91. for(var i = 0 ; i= 0; i--){
  92. this.snake.push([this.gridYN - 1 - i ,this.gridXN - 1 - 3])
  93. this.map[this.gridYN - 1 - i][this.gridXN - 1 - 3].style.backgroundColor = "blue"
  94. }
  95. // 初始蛇头坐标
  96. this.snakeHead = this.snake[0]
  97. // console.log(this.snake)
  98. }
  99. // 开始移动,移动后蛇头坐标 +-1
  100. GreedySnake.prototype.snakeMove = function(){
  101. let _this = this,
  102. sH = this.snakeHead,
  103. y = null,
  104. x = null,
  105. tempH = null,
  106. last = null,
  107. alive = true
  108. function common(){
  109. _this.map[tempH[0]][tempH[1]].style.backgroundColor = "blue"
  110. _this.snake.unshift(tempH);
  111. _this.snakeHead = tempH;
  112. // 检测蛇头是否和蛇的身体相撞
  113. for(var i = 1 ; i < _this.snake.length;i++){
  114. if(_this.snakeHead[0] == _this.snake[i][0] && _this.snakeHead[1] == _this.snake[i][2]){
  115. alert("GAME OVER");
  116. alive = false
  117. return false
  118. }
  119. }
  120. // 当蛇吃到食物后再重新创建食物
  121. if(sH[0] === _this.foodY && sH[1] === _this.foodX){
  122. _this.createFood()
  123. return false
  124. }
  125. last = _this.snake.pop();
  126. _this.map[last[0]][last[1]].style.backgroundColor = ""
  127. }
  128. switch(this.direction){
  129. case "top":
  130. y = sH[0] //缓存
  131. tempH = [--y , sH[1] ];
  132. if(tempH[0] < 0){
  133. tempH = [this.gridYN - 1 , sH[1]]
  134. }
  135. common();
  136. break;
  137. case "bottom":
  138. y = sH[0]
  139. tempH = [++y , sH[1] ];
  140. // 边界判断
  141. if(tempH[0] > this.gridYN - 1){
  142. tempH = [ 0 , sH[1]]
  143. }
  144. common()
  145. break;
  146. case "left":
  147. x = sH[1]
  148. tempH = [sH[0] , --x ];
  149. if(tempH[1] < 0){
  150. tempH = [ sH[0] , this.gridXN - 1]
  151. }
  152. common()
  153. break;
  154. case "right":
  155. x = sH[1]
  156. tempH = [sH[0] , ++x ];
  157. if(tempH[1] > this.gridXN - 1){
  158. tempH = [ sH[0] , 0 ]
  159. }
  160. common()
  161. break;
  162. }
  163. alive && setTimeout(function(){
  164. _this.snakeMove()
  165. },500 / this.speed)
  166. }
  167. // 注册键盘事件
  168. GreedySnake.prototype.listenKeyBoardEvents = function(){
  169. let _this = this
  170. self.onkeyup = function(e){
  171. let dir = _this.direction
  172. switch(e.keyCode){
  173. case 37:
  174. if(dir != "right"){
  175. _this.direction = "left";
  176. }
  177. break;
  178. case 38:
  179. if(dir != "bottom"){
  180. _this.direction = "top";
  181. }
  182. break;
  183. case 39:
  184. if(dir != "left"){
  185. _this.direction = "right";
  186. }
  187. break;
  188. case 40:
  189. if(dir != "top"){
  190. _this.direction = "bottom";
  191. }
  192. break;
  193. }
  194. }
  195. }
  196. GreedySnake.prototype.print = function(){
  197. return this.map
  198. }
  199. // 参数含义:x轴,y轴上的格子数量
  200. var greedySnake = new GreedySnake(20,20);
  201. greedySnake.init()
  202. })(window)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94456.html

相关文章

  • python完成简单的贪吃蛇游戏附编号

      此篇文章主要是详细介绍了python完成简单的贪吃蛇小游戏附编号,文章内容紧扣主题进行详尽的基本介绍,具有很强的参考意义,需用的朋友可以学习一下  序言:  不知道有没有同学们和我一样,最开始触碰程序编程的动机就是为了做一个游戏打?  接下来要跟大家分享是指一个pygame所写的贪食蛇手机游戏:  贪食蛇这一个手机游戏在编程设计里的熟客,由于:  简易,最基本游戏情节你只需要蛇和食物2个就可以...

    89542767 评论0 收藏0
  • 给你的网页游戏添加游戏手柄支持

    摘要:自从买了手柄后一直想试试给自己写的小游戏增加手柄支持。表示该对象所表示的手柄是否还保持连接。。连接事件浏览器提供了两个手柄相关的事件。。完笔者给自己的贪食蛇小游戏增加了手柄摇杆控制蛇头方向功能之前笔者还写过俄罗斯方块之类的,代码找不到了 自从买了 Switch 手柄后一直想试试给自己写的小游戏增加手柄支持。今天终于抽出时间搞了一把。以下是笔记 ;) navigator.getGamep...

    stdying 评论0 收藏0
  • 曾探:爱JavaScript再多,它也只是生活的一部分

    摘要:拿足球比赛的例子来说,我们的目标只是进球,下底传中这种模式仅仅是达到进球目标的一种手段。但在这种动态解释型语言中,给对象动态添加职责是再简单不过的事情。这就造成了语言的装饰者模式不再关注于给对象动态添加职责,而是关注于给函数动态添加职责。 非商业转载请注明作译者、出处,并保留本文的原始链接:http://www.ituring.com.cn/article/199456 曾探...

    cyqian 评论0 收藏0
  • JavaScript 就要统治世界了?

    摘要:欢迎使用中文文档架构概览是网易项目团队开发的一个基于进行开发的应用层框架,提供了一个轻量级的容器来编写简单可维护的。 JavaScript 可以……嘛,不就是操作一下 DOM,可以让元素飞来飞去吗JavaScript 是……不就是用 jQuery 让网页动起来,顶多就是再用用 Ajax 和后端进行一下数据交换吗JavaScript 是一门……最讨厌和鄙视这种弱类型不需要编译的脚本语言...

    AbnerMing 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<