純JS實現貪吃蛇遊戲 —— 可能是全網程式碼最優雅的實現。
在網上看了許多的貪吃蛇這類遊戲,效果基本還可以,功能也實現了,不過看程式碼大都是冗餘或雜亂不堪的,難以維護。
所以花了點時間,對整個遊戲重構了一下,也算是站在各位前輩的肩膀上做的最佳化,希望對大家有幫助。
功能描述
生成一條蛇,可以上下左右移動,目標只有一個:吃食物。吃到一個食物蛇的身體增加一節,然後生成下一個食物,撞到地圖就 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部落格 ” ,連結:http://blog.itpub.net/69992957/viewspace-2750856/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- OpenGL實現貪吃蛇程式碼
- js+jquery實現貪吃蛇經典小遊戲JSjQuery遊戲
- python實現貪吃蛇Python
- Java實現貪吃蛇Java
- 100行Python程式碼實現貪吃蛇小遊戲(超詳細)Python遊戲
- (完整原始碼)貪吃蛇小遊戲——HTML+CSS+JavaScript實現原始碼遊戲HTMLCSSJavaScript
- Python實現貪吃蛇大作戰Python
- h5+js實現單機版貪吃蛇H5JS
- C語言實現桌面貪吃蛇C語言
- 利用python實現簡易版的貪吃蛇遊戲(面向python小白)Python遊戲
- c/c++實現簡單的貪吃蛇視覺化遊戲C++視覺化遊戲
- Python:遊戲:貪吃蛇Python遊戲
- 貪吃蛇jsJS
- Android-貪吃蛇小遊戲-分析與實現-Kotlin語言描述Android遊戲Kotlin
- [譯] RxJS 遊戲之貪吃蛇JS遊戲
- html+js 實現 推箱子 貪吃蛇和簡單的飛機大戰HTMLJS
- 貪吃蛇
- 貪吃蛇c原始碼原始碼
- 裝逼的最高境界---一行js程式碼完成一個簡易版的貪吃蛇遊戲JS遊戲
- 【Python】 Python小遊戲-貪吃蛇大冒險Python遊戲
- 04 貪吃蛇
- [WebAssembly 入門] 實現數獨遊戲 - 如何優雅的組織Rust程式碼Web遊戲Rust
- C語言小遊戲------貪吃蛇----小白專用C語言遊戲
- 開發Windows貪吃蛇遊戲——(一)前期準備Windows遊戲
- GUI 基於Swing製作貪吃蛇小遊戲GUI遊戲
- C語言貪吃蛇原始碼C語言原始碼
- 《貪吃蛇巴士》:《貪吃蛇》和《瘋狂計程車》的「完美結晶」
- arduino uno+LCD12864(ST7735S)+藍芽模組實現貪吃蛇UI藍芽模組
- JavaScript-開發一個簡單的貪吃蛇小遊戲JavaScript遊戲
- 優雅的實現動態載入 css、jsCSSJS
- Python3 貪吃蛇Python
- js實現翻牌遊戲JS遊戲
- 貪吃蛇大作戰JavaFx版完整原始碼Java原始碼
- 《動物餐廳》湯庭泉:如何優雅的實現遊戲調優遊戲
- 能用js實現的最終用js實現,Shell指令碼也不例外JS指令碼
- JS實現24點遊戲JS遊戲
- Python程式碼實現“FlappyBird”小遊戲PythonAPP遊戲
- 純JS實現走馬燈JS