ITPub博客

首页 > 应用开发 > Javascript > 纯JS实现贪吃蛇游戏 —— 可能是全网代码最优雅的实现。

纯JS实现贪吃蛇游戏 —— 可能是全网代码最优雅的实现。

Javascript 作者:玻璃窗起雾了 时间:2021-01-18 17:31:36 0 删除 编辑

在网上看了许多的贪吃蛇这类游戏,效果基本还可以,功能也实现了,不过看代码大都是冗余或杂乱不堪的,难以维护。

所以花了点时间,对整个游戏重构了一下,也算是站在各位前辈的肩膀上做的优化,希望对大家有帮助。

功能描述

生成一条蛇,可以上下左右移动,目标只有一个:吃食物。吃到一个食物蛇的身体增加一节,然后生成下一个食物,撞到地图就 GG , game over 。

设计思路

1.  整体实现采用原生 JS ,使用 ES6 的 Class 类构造,完美的诠释了面向对象编程的编程思想。

2. JS 主体文件分成 food.js(食物类),snake.js(蛇类), game.js(游戏入口文件),util.js(工具函数)。讲道理,地图也需要用到一个map.js(地图类), 站长交易 由于这里的地图过分简单,所以不搞也罢。

1.  工具类设计  ( util.js )

目标功能点:

·         生成随机坐标

1.    export function getRandom(a, b){

2.        let max = Math.max(a, b);

3.        let min = Math.min(a, b);

4.        return parseInt(Math.random() * (max - min)) + min;

5.    }

2.  食物类设计( food.js )

目标功能点:

·         初始化食物(宽,高,颜色等)

·         在地图上随机生成

·         管理食物(删除)

1.    import { getRandom } from './util.js';

2.    //  食物类

3.    class Food {

4.         //  初始化

5.        constructor({x = 0, y = 0, width = 20, height = 20, color = 'green'} = {}){

6.             //  结构赋值   参数默认值

7.             // let options = {x = 0, y = 0, width = 20, height = 20, color = 'green'} || {};

8.             //  存储食物

9.            this.elements = [];

10.           //  坐标

11.          this.x = x;

12.          this.y = y;

13.   

14.          this.width = width;

15.          this.height = height;

16.          this.color = color;

17.      }

18.   

19.      render(map){

20.          this.remove();  //  删除之前创建的食物

21.   

22.           //  随机设置 x,y 的值

23.          this.x = getRandom(0, map.offsetWidth / this.width - 10) * this.width;

24.          this.y = getRandom(0, map.offsetHeight / this.height - 1) * this.height;

25.          console.log(this.x, this.y);

26.   

27.           //  创建食物  dom

28.          let div = document.createElement('div');

29.          map.appendChild(div);

30.          this.elements.push(div);

31.   

32.           //  设置 div 的样式

33.          div.style.position = 'absolute';

34.          div.style.left = this.x + 'px';

35.          div.style.top = this.y + 'px';

36.          div.style.width = this.width + 'px';

37.          div.style.height = this.height + 'px';

38.          div.style.backgroundColor = this.color;

39.      }

40.      remove() {

41.           //  从后往前

42.          for(let i = this.elements.length -1; i >= 0; i--){

43.              this.elements[i].parentNode.removeChild(this.elements[i]);  //  删除 div

44.              this.elements.splice(i, 1);  //  删除数组中的元素

45.          }

46.      }

47.  }

48.  export default Food;

3.  蛇类( snake.js )

目标功能点:

·         初始化蛇(宽,高,颜色、长度等)

·         在地图上初始定位

·         蛇的移动与管理(吃一个食物生成一个新的蛇对象)

·         判断是否吃到食物(蛇头的坐标与食物坐标重合)

1.    //  蛇类

2.    class Snake {

3.        constructor({ width = 20, height = 20, direction = 'right'  } = {}){

4.               //  存储蛇

5.              this.elements = [];

6.     

7.              this.width = width;

8.              this.height = height;

9.              this.direction = direction;

10.             //  蛇的身体   初始三节

11.            this.body = [

12.                {x: 3, y: 2, color: 'red'},

13.                {x: 2, y: 2, color: 'blue'},

14.                {x: 1, y: 2, color: 'blue'},

15.            ];

16.      }

17.   

18.      render(map){

19.          this.remove();  //  删除之前创建的蛇

20.          for(let i = 0, len = this.body.length; i <  len; i++ ){

21.              let object = this.body[i];

22.   

23.              let div = document.createElement('div');

24.              map.appendChild(div);

25.              this.elements.push(div);

26.   

27.                //  设置样式

28.               div.style.position = 'absolute';

29.               div.style.width = this.width + 'px';

30.               div.style.height = this.height + 'px';

31.               div.style.left = object.x * this.width + 'px';

32.               div.style.top = object.y * this.height + 'px';

33.               div.style.backgroundColor = object.color;

34.          }

35.      }

36.   

37.      move(food, map){

38.           //  控制蛇的移动  ( 当前蛇节   移动到上一个蛇节 )

39.          for(let i = this.body.length - 1; i > 0; i--){

40.              this.body[i].x = this.body[i - 1].x;

41.              this.body[i].y = this.body[i - 1].y;

42.          }

43.           //  蛇头

44.          let head = this.body[0];

45.   

46.           //  蛇头的行进方向

47.          switch(this.direction) {

48.              case 'right':

49.                  head.x += 1;

50.                  break;

51.              case 'left':

52.                  head.x -= 1;

53.                  break;

54.              case 'top':

55.                  head.y -= 1;

56.                  break;

57.              case 'bottom':

58.                  head.y += 1;

59.                  break;

60.          }

61.   

62.           //  蛇吃食物

63.           //  判断蛇头的位置是否与食物的位置重合

64.          let  headX = head.x * this.width;

65.          let  headY = head.y * this.height;

66.   

67.          if(headX === food.x && headY === food.y){

68.              let last = this.body[this.body.length -1 ];

69.              this.body.push({

70.                  x: last.x,

71.                  y: last.y,

72.                  color: last.color

73.              });

74.               //  重新生成一个食物

75.              food.render(map);

76.          }

77.      }

78.      remove() {

79.          for (let i = this.elements.length - 1; i >= 0; i--) {

80.               //  删除 div

81.              this.elements[i].parentNode.removeChild(this.elements[i]);

82.               //  删除数组中的元素

83.              this.elements.splice(i, 1);

84.          }

85.      }

86.  }

87.   

88.  export default Snake;

4.  游戏入口文件( game.js )

目标功能点:

·         实例化蛇与食物

·         让蛇动起来

·         绑定按键,控制方向

·         开始游戏

·         当蛇撞到地图边缘 GG ,显示  game over !

1.    import Food from "./food.js";

2.    import Snake from "./snake.js";

3.    //  游戏的入口文件

4.    class Game {

5.        constructor() {

6.             //  创建食物和蛇的实例

7.            this.food = new Food();

8.            this.snake = new Snake();

9.            this.map = map;

10.           //  定时器

11.          this.timerId = null;

12.      }

13.      start() {

14.           //  食物和蛇   渲染到地图上

15.          this.food.render(this.map);

16.          this.snake.render(this.map);

17.          this.runSnake();

18.          this.bindKey();

19.   

20.      }

21.       //  让蛇动起来

22.      runSnake() {

23.           this.timerId = setInterval( () => {

24.               //  要获取游戏对象中的蛇属性

25.              this.snake.move(this.food, this.map);

26.               // 2.2   当蛇遇到边界游戏结束

27.              var maxX = this.map.offsetWidth / this.snake.width;

28.              var maxY = this.map.offsetHeight / this.snake.height;

29.              var headX = this.snake.body[0].x;

30.              var headY = this.snake.body[0].y;

31.              if (headX < 0 || headX >= maxX || headY < 0|| headY >= maxY) {

32.                  console.log('Game Over');

33.                  clearInterval(this.timerId);

34.                  return

35.              }

36.              this.snake.render(this.map);   //  根据 body  的数据   重新渲染蛇在页面位置

37.          }, 150);

38.      }

39.       //  绑定键盘事件   控制蛇的方向

40.      bindKey() {

41.          document.addEventListener('keydown',  (e) => {

42.              switch (e.keyCode) {

43.                  case 37:

44.                      this.snake.direction = 'left';

45.                      break;

46.                  case 38:

47.                      this.snake.direction = 'top';

48.                      break;

49.                  case 39:

50.                      this.snake.direction = 'right';

51.                      break;

52.                  case 40:

53.                      this.snake.direction = 'bottom';

54.                      break;

55.              }

56.          });

57.      }

58.  }

59.  export default Game;

5.  调用( index.html )

1.    <!DOCTYPE html>

2.    <html>

3.     

4.    <head>

5.        <meta charset="UTF-8">

6.        <meta name="viewport" content="width=device-width, initial-scale=1.0">

7.        <title>Document</title>

8.    </head>

9.     

10.  <body>

11.      <div id="map" style="width:80%;height:400px;border: 1px solid orange;"></div>

12.      <script type="module">

13.          import Game from './game.js';

14.          //  全局的地图  map

15.          let map = document.getElementById('map');

16.          let game = new Game(map);

17.          //  调用开始方法

18.          game.start();

19.      </script>

20.  </body>

21.   

22.  </html>

FAQ :

由于整个项目采用 ES6 的模块设计,所以需要启动一个本地服务才可以跑,单独点开 index.html ,是没得用的。

 


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69992957/viewspace-2750856/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: 没有了~
请登录后发表评论 登录
全部评论
只有兴趣才能萌生出动力。

注册时间:2021-01-10

  • 博文量
    23
  • 访问量
    11574