首頁 web前端 H5教程 H5開發:實現消滅星星遊戲的詳細內容

H5開發:實現消滅星星遊戲的詳細內容

Jul 27, 2018 am 10:25 AM

這篇文章要跟大家介紹的文章內容是關於H5實現消滅星星遊戲的詳細內容,有很好的參考價值,希望可以幫助到有需要的朋友。

「消滅星星」是一款很經典的「消除類遊戲」,它的玩法很簡單:消除相連的同色磚塊。

H5開發:實現消滅星星遊戲的詳細內容

1. 遊戲規則

「消滅星星」存在多個版本,不過它們的規則除了「關卡分數」有些出入外,其它的規則都是一樣的。作者介紹的版本的遊戲規則整理如下:

1. 色磚分佈

10 x 10 的表格

5種顏色- 紅、綠、藍,黃,紫

每類色磚個數在指定區間內隨機

5類色磚在10 x 10 表格中隨機分佈

#2. 消除規則

#兩個或兩個以上同色磚塊相連通即是可被消除的磚塊。

3. 分數規則

消除總分值= n * n * 5

獎勵總分值= 2000 – n * n * 20

#“n”表示磚塊數量。上面是「總」分數的規則,還有「單」個磚塊的分數規則:

消除磚塊得分值= 10 * i 5

剩餘磚塊扣分值= 40 * i 20

“i”表示磚塊的索引值(從0 開始)。簡單地說,單一磚塊「得分值」和「扣分值」是一個等差數列。

4. 關卡分數

關卡分數 = 1000 (level – 1) * 2000;「level」即目前關卡數。

5.通關條件

可消除色塊不存在

累計分數>= 目前關卡分數

上面兩個條件同時成立遊戲才可以通關。

2. MVC 設計模式

筆者這次又是使用了 MVC 模式來寫「消滅星星」。星星「磚塊」的資料結構與各種狀態由Model 實現,遊戲的核心在Model 中完成;View 映射Model 的變化並做出對應的行為,它的任務主要是展示動畫;用戶與遊戲的交互由Control 完成。

從邏輯規劃來看,Model 很重而View 與 Control 很輕,不過,從程式碼量上看,View 很重而 Model 與 Control 相對很輕。

3. Model

10 x 10 的表格以長度為 100 的陣列可完美地繪製遊戲的星星「磚塊」。

[
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P,
R, R, G, G, B, B, Y, Y, P, P
]
登入後複製

R – 紅色,G – 綠色,B – 藍色,Y – 黃色,P – 紫色。 Model 的核心任務是以下四個:

產生磚牆

#消除磚塊(產生磚塊分數)

夯實磚牆

清除殘磚(產生獎勵分數)

3.1 產生磚牆

磚牆分兩步驟產生:

色磚數量分配

打散色磚塊

理論上,可以將100 個格子可以均分到5 類顏色,不過筆者玩過的「消滅星星」都不使用均分策略。透過分析幾款「消滅星星」,其實可以發現一個規律 —— 「色磚之間的數量差在一個固定的區間內」。

如果把傳統意義上的均分稱作「完全均分」,那麼「消滅星星」的分配是一種在均分線上下波動的「不完全均分」。 H5開發:實現消滅星星遊戲的詳細內容

筆者把上面的「不完全均分」稱作「波動均分」,演算法的具體實現可以參見「波動均分演算法」。

「打散色磚」其實就是將陣列亂序的過程,筆者推薦使用「 費雪耶茲亂序演算法」。

以下是偽代碼的實作:

// 波动均分色砖
waveaverage(5, 4, 4).forEach(
// tiles 即色墙数组
(count, clr) => tiles.concat(generateTiles(count, clr));
);
// 打散色砖
shuffle(tiles);
登入後複製

3.2 消除磚塊

「消除磚塊」的規則很簡單— 相鄰相連通相同色即可以消除。

H5開發:實現消滅星星遊戲的詳細內容
前兩個組合符合「相鄰相連通相同色即可以消除」,所以它們可以被消除;第三個組合雖然「相鄰相同色」但是不「相連通」所以它不能被消除。

「消除磚塊」的同時有一個重要的任務:產生磚塊對應的分數。在「遊戲規則」中,筆者已經提供了對應的數學公式:「消除磚塊得分值 = 10 * i 5」。

「消除磚塊」演算法實作如下:

function clean(tile) {
let count = 1;
let sameTiles = searchSameTiles(tile);
if(sameTiles.length > 0) {
deleteTile(tile);
while(true) {
let nextSameTiles = [];
sameTiles.forEach(tile => {
nextSameTiles.push(...searchSameTiles(tile));
makeScore(++count * 10 + 5); // 标记当前分值
deleteTile(tile); // 删除砖块
});
// 清除完成,跳出循环
if(nextSameTiles.length === 0) break;
else {
sameTiles = nextSameTiles;
}
}
}
}
登入後複製

清除的演算法使用「遞迴」邏輯上會清晰一些,不過「遞迴」在瀏覽器上容易「堆疊溢出」,所以筆者沒有使用「遞歸」實作。

3.3 夯實磚牆

磚牆在消除了部分磚塊後,會出現空洞,此時需要對牆體進行夯實:

H5開發:實現消滅星星遊戲的詳細內容H5開發:實現消滅星星遊戲的詳細內容

向下夯实 向左夯实

H5開發:實現消滅星星遊戲的詳細內容

向左下夯实(先下后左)

一种快速的实现方案是,每次「消除砖块」后直接遍历砖墙数组(10×10数组)再把空洞夯实,伪代码表示如下:

   
for(let row = 0; row < 10; ++row) {
for(let col = 0; col < 10; ++col) {
if(isEmpty(row, col)) {
// 水平方向(向左)夯实
if(isEmptyCol(col)) {
tampRow(col);
}
// 垂直方向(向下)夯实
else {
tampCol(col);
}
break;
}
}
}
登入後複製

But… 为了夯实一个空洞对一张大数组进行全量遍历并不是一种高效的算法。在笔者看来影响「墙体夯实」效率的因素有:

定位空洞

砖块移动(夯实)

扫描墙体数组的主要目的是「定位空洞」,但能否不扫描墙体数组直接「定位空洞」?

墙体的「空洞」是由于「消除砖块」造成的,换种说法 —— 被消除的砖块留下来的坑位就是墙体的空洞。在「消除砖块」的同时标记空洞的位置,这样就无须全量扫描墙体数组,伪代码如下:

function deleteTile(tile) {
// 标记空洞
markHollow(tile.index);
// 删除砖块逻辑
...
}
登入後複製

在上面的夯实动图,其实可以看到它的夯实过程如下:

空洞上方的砖块向下移动

空列右侧的砖块向左移动

墙体在「夯实」过程中,它的边界是实时在变化,如果「夯实」不按真实边界进行扫描,会产生多余的空白扫H5開發:實現消滅星星遊戲的詳細內容

如何记录墙体的边界?
把墙体拆分成一个个单独的列,那么列最顶部的空白格片段就是墙体的「空白」,而其余非顶部的空白格片段即墙体的「空洞」。

H5開發:實現消滅星星遊戲的詳細內容

笔者使用一组「列集合」来描述墙体的边界并记录墙体的空洞,它的模型如下:

/*
@ count - 列砖块数
@ start - 顶部行索引
@ end - 底部行索引
@ pitCount - 坑数
@ topPit - 最顶部的坑
@ bottomPit - 最底部的坑
*/
let wall = [
{count, start, end, pitCount, topPit, bottomPit},
{count, start, end, pitCount, topPit, bottomPit},
...
];
登入後複製

这个模型可以描述墙体的三个细节:

空列

列的连续空洞

列的非连续空洞

// 空列
if(count === 0) {
...
}
// 连续空洞
else if(bottomPit - topPit + 1 === pitCount) {
...
}
// 非连续空洞
else {
...
}
登入後複製

砖块在消除后,映射到单个列上的空洞会有两种分布形态 —— 连续与非连续。

H5開發:實現消滅星星遊戲的詳細內容

「连续空洞」与「非连续空洞」的夯实过程如下:

H5開發:實現消滅星星遊戲的詳細內容

其实「空列」放大于墙体上,也会有「空洞」类似的分布形态 —— 连续与非连续H5開發:實現消滅星星遊戲的詳細內容

它的夯实过程与空洞类似,这里就不赘述了。

3.4 消除残砖

上一小节提到了「描述墙体的边界并记录墙体的空洞」的「列集合」,笔者是直接使用这个「列集合」来消除残砖的,伪代码如下:

function clearAll() {
let count = 0;
for(let col = 0, len = this.wall.length;  col < len; ++col) {
let colInfo = this.wall[col];
for(let row = colInfo.start; row <= colInfo.end; ++row) {
let tile = this.grid[row * this.col + col];
tile.score = -20 - 40 * count++; // 标记奖励分数
tile.removed = true;
}
}
}
登入後複製

4. View

View 主要的功能有两个:

UI 管理

映射 Model 的变化(动画)

UI 管理主要是指「界面绘制」与「资源加载管理」,这两项功能比较常见本文就直接略过了。View 的重头戏是「映射 Model 的变化」并完成对应的动画。动画是复杂的,而映射的原理是简单的,如下伪代码:

update({originIndex, index, clr, removed, score}) {
// 还没有 originIndex 或没有色值,直接不处理
if(originIndex === undefined || clr === undefined) return ;
let tile = this.tiles[originIndex];
// tile 存在,判断颜色是否一样
if(tile.clr !== clr) {
this.updateTileClr(tile, clr);
}
// 当前索引变化 ----- 表示位置也有变化
if(tile.index !== index) {
this.updateTileIndex(tile, index);
}
// 设置分数
if(tile.score !== score) {
tile.score = score;
}
if(tile.removed !== removed) {
// 移除或添加当前节点
true === removed ? this.bomb(tile) : this.area.addChild(tile.sprite);
tile.removed = removed;
}
}
登入後複製

Model 的砖块每次数据的更改都会通知到 View 的砖块,View 会根据对应的变化做对应的动作(动画)。

5. Control

Control 要处理的事务比较多,如下:

绑定 Model & View

生成通关分值

判断通关条件

对外事件

用户交互

初始化时,Control 把 Model 的砖块单向绑定到 View 的砖块了。如下:

Object.defineProperties(model.tile, {
    originIndex: {
        get() {...},
        set(){
            ...
            view.update({originIndex})
        }
    },  
    index: {
        get() {...},
        set() {
            ...
            view.update({index})
        }
    },
    clr: {
        get() {...},
        set() {
            ...
            view.update({clr})
        }
    },
    removed: {
        get() {...},
        set() {
            ...
            view.update({removed})
        }
    },  
    score: {
        get() {...},
        set() {
            ...
            view.update({score})
        }
    }
})
登入後複製

「通关分值」与「判断通关条件」这对逻辑在本文的「游戏规则」中有相关介绍,这里不再赘述。

对外事件规划如下:

#gameover
name detail
#pass 
  通關  
#pause   
暫停 
resume     恢復  
    恢復  
   遊戲結束  

#nametypedeltail    method    methodenter    method     method   暫停   resume  恢復   destroy銷毀遊戲 
使用者互動APIs 規劃如下:

#init
   初始化遊戲  
next
   進入下一關  


  進入指定關卡   ##pause


   method 


    method   

6. 問題

#在有一個關於有一個關於「消滅星星」的話題:popstar關卡是如何設計的? H5開發:實現消滅星星遊戲的詳細內容

這個主題在最後提出了一個問題 —— 「無法消除和最大得分不滿足過關條件的矩陣」。


「無法消除的矩陣」其實就是最大得分為0的矩陣,本質上就是「最大得分不滿足過關條件的矩陣」。

最大得分不滿足過關條件的矩陣

求「矩陣」的最大得分是一個「背包問題」,求解的演算法不難:對當前矩陣用「遞歸」的形式把所有的消滅分支都執行一次,並取最高分值。但是 javascript 的“遞歸”極易“棧溢出”導致演算法無法執行。

其實在知乎的話題中提到一個解決方案:

網上查到有程式提出做個工具隨機生成關卡,自動計算,把符合得分條件的關卡篩選出來

這個解決方案代價是昂貴的!筆者提供有源碼並沒有解決這個問題,而是用一個比較取巧的方法:進入遊戲前檢查是事為“無法消除矩陣”,如果是重新生成關卡矩陣。 相關推薦:

HTML5 Canvas API製作簡單的猜字遊戲

######使用canvas實作迷宮遊戲######

以上是H5開發:實現消滅星星遊戲的詳細內容的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

h5項目怎麼運行 h5項目怎麼運行 Apr 06, 2025 pm 12:21 PM

運行 H5 項目需要以下步驟:安裝 Web 服務器、Node.js、開發工具等必要工具。搭建開發環境,創建項目文件夾、初始化項目、編寫代碼。啟動開發服務器,使用命令行運行命令。在瀏覽器中預覽項目,輸入開發服務器 URL。發布項目,優化代碼、部署項目、設置 Web 服務器配置。

如何使用視口元標記來控制移動設備上的頁面縮放? 如何使用視口元標記來控制移動設備上的頁面縮放? Mar 13, 2025 pm 08:00 PM

本文討論了使用視口元標記來控制移動設備上的頁面縮放,重點是寬度和初始尺度之類的設置,以獲得最佳響應和性能。

H5頁面製作究竟指什麼 H5頁面製作究竟指什麼 Apr 06, 2025 am 07:18 AM

H5 頁面製作是指使用 HTML5、CSS3 和 JavaScript 等技術,創建跨平台兼容的網頁。其核心在於瀏覽器解析代碼,渲染結構、樣式和交互功能。常見技術包括動畫效果、響應式設計和數據交互。為避免錯誤,應使用開發者工具調試;而性能優化和最佳實踐則包括圖像格式優化、減少請求和代碼規範等,以提高加載速度和代碼質量。

如何使用HTML5頁面可見性API檢測頁面何時可見? 如何使用HTML5頁面可見性API檢測頁面何時可見? Mar 13, 2025 pm 07:51 PM

本文討論了使用HTML5頁面可見性API來檢測頁面可見性,提高用戶體驗並優化資源使用情況。關鍵方麵包括暫停媒體,減少CPU負載以及基於可見性變化管理分析。

如何使用地理位置API處理用戶位置隱私和權限? 如何使用地理位置API處理用戶位置隱私和權限? Mar 18, 2025 pm 02:16 PM

本文討論了使用GeOlocation API管理用戶位置隱私和權限,並強調要求權限,確保數據安全性並遵守隱私法律的最佳實踐。

如何將HTML5拖放API用於交互式用戶界面? 如何將HTML5拖放API用於交互式用戶界面? Mar 18, 2025 pm 02:17 PM

本文介紹瞭如何使用HTML5拖放API來創建交互式用戶界面,詳細介紹了使元素可拖動的步驟,處理關鍵事件並通過自定義反饋來增強用戶體驗。它還討論了一個常見的陷阱

H5頁面製作是否需要持續維護 H5頁面製作是否需要持續維護 Apr 05, 2025 pm 11:27 PM

H5頁面需要持續維護,這是因為代碼漏洞、瀏覽器兼容性、性能優化、安全更新和用戶體驗提升等因素。有效維護的方法包括建立完善的測試體系、使用版本控制工具、定期監控頁面性能、收集用戶反饋和製定維護計劃。

H5頁面製作適合哪些應用場景 H5頁面製作適合哪些應用場景 Apr 05, 2025 pm 11:36 PM

H5(HTML5)適合應用於輕量級應用,如營銷活動頁面、產品展示頁面和企業宣傳微網站。它優勢在於跨平台性和豐富的交互性,但局限性在於復雜的交互和動畫、本地資源訪問和離線功能。

See all articles