基于 WebAssembly 的 Game of Life 交互實現

一、前言

在前期的實現中,我們使用 Rust 編寫核心邏輯,并通過 WebAssembly 將其引入到 Web 環境中,再利用 JavaScript 進行渲染。接下來,我們將在這一基礎上增加用戶交互功能,使模擬過程不僅能夠自動演化,還能支持用戶對細胞狀態進行手動修改。

二、實現暫停與恢復游戲

1. 在 HTML 中添加按鈕

首先,在 wasm-game-of-life/www/index.html 文件中,在 <canvas> 上方添加一個按鈕,用于控制游戲的暫停與恢復:

<button id="play-pause"></button>

2. 在 JavaScript 中管理動畫

為了控制動畫,我們需要保存 requestAnimationFrame 返回的標識符,以便后續通過 cancelAnimationFrame 取消動畫調用。在 wasm-game-of-life/www/index.js 中,新增如下代碼:

let animationId = null;// renderLoop 函數負責繪制網格、細胞并更新狀態
const renderLoop = () => {drawGrid();drawCells();universe.tick();animationId = requestAnimationFrame(renderLoop);
};// 判斷游戲是否暫停
const isPaused = () => {return animationId === null;
};const playPauseButton = document.getElementById("play-pause");// 開始游戲,設置按鈕圖標并啟動動畫
const play = () => {playPauseButton.textContent = "?";renderLoop();
};// 暫停游戲,更新按鈕圖標并取消下一幀動畫
const pause = () => {playPauseButton.textContent = "?";cancelAnimationFrame(animationId);animationId = null;
};// 根據當前狀態切換播放和暫停
playPauseButton.addEventListener("click", event => {if (isPaused()) {play();} else {pause();}
});// 初始化時調用 play() 啟動動畫
play();

通過這段代碼,我們可以根據 animationId 的狀態判斷游戲是否在播放,并相應地啟動或暫停動畫。同時,按鈕的圖標也會顯示對應的狀態。

三、實現點擊切換細胞狀態

為了讓用戶能直接在畫布上點擊修改細胞狀態,我們需要在 Rust 和 JavaScript 端分別進行處理。

1. Rust 端的修改

wasm-game-of-life/src/lib.rs 文件中,為 Cell 添加一個 toggle 方法,用于切換細胞狀態:

impl Cell {fn toggle(&mut self) {*self = match *self {Cell::Dead => Cell::Alive,Cell::Alive => Cell::Dead,};}
}

接著,在 Universe 的公開接口中添加 toggle_cell 方法,這樣 JavaScript 就能調用它來切換指定行列上的細胞狀態:

#[wasm_bindgen]
impl Universe {pub fn toggle_cell(&mut self, row: u32, column: u32) {let idx = self.get_index(row, column);self.cells[idx].toggle();}
}

通過 #[wasm_bindgen] 標注,該方法會被導出至 JavaScript 環境中。

2. JavaScript 端的處理

wasm-game-of-life/www/index.js 中,為 <canvas> 添加點擊事件監聽器,完成以下步驟:

  1. 獲取點擊事件相對于頁面的坐標;
  2. 將頁面坐標轉換為 <canvas> 內部的坐標;
  3. 根據坐標計算出對應的行和列;
  4. 調用 universe.toggle_cell 切換細胞狀態;
  5. 重新繪制網格和細胞以更新界面顯示。

具體實現如下:

canvas.addEventListener("click", event => {const boundingRect = canvas.getBoundingClientRect();const scaleX = canvas.width / boundingRect.width;const scaleY = canvas.height / boundingRect.height;const canvasLeft = (event.clientX - boundingRect.left) * scaleX;const canvasTop = (event.clientY - boundingRect.top) * scaleY;const row = Math.min(Math.floor(canvasTop / (CELL_SIZE + 1)), height - 1);const col = Math.min(Math.floor(canvasLeft / (CELL_SIZE + 1)), width - 1);universe.toggle_cell(row, col);drawGrid();drawCells();
});

通過以上代碼,當用戶點擊 <canvas> 時,就能實現對對應位置細胞狀態的即時切換,從而自由繪制自定義圖案。

四、效果預覽

完成上述步驟后,使用 wasm-pack build 重建項目,然后刷新 http://localhost:8080/。你將會看到:

  • 點擊頁面上的按鈕可以暫停或恢復游戲的動畫;
  • 在暫停狀態下,點擊畫布即可改變相應位置細胞的狀態,實現自定義圖案的繪制。

五、總結

通過本文,我們實現了基于 WebAssembly 的 Game of Life 模擬的交互功能:

  • 利用 JavaScript 控制動畫的暫停和恢復,使得用戶能夠在需要時停下演化過程進行編輯;
  • 通過點擊 <canvas> 切換細胞狀態,讓自定義圖案的繪制變得直觀便捷。

這種前后端技術的緊密結合展示了現代 Web 開發中多技術協作的魅力,為進一步擴展和優化應用提供了堅實基礎。希望這篇博客能為你提供有價值的參考,激發你探索更多有趣的功能擴展和優化方案。

Happy coding!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/75008.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/75008.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/75008.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【keil】單步調試

一、步驟 1、打開stc-isp軟件 2.打開keil仿真設置&#xff0c;選擇對應的單片機型號 3.點擊將所選目標單片機設置為仿真芯片&#xff0c;點擊下載&#xff0c;按一下單片機打下載按鈕 4.此時已經將仿真程序下載到單片機 5.此時點擊options,找到debug選擇STC Montor 51 Driv…

c++弱指針實現原理

在 C 中&#xff0c;弱指針&#xff08;std::weak_ptr&#xff09;是一種特殊的智能指針&#xff0c;其核心目標是?解決 std::shared_ptr 的循環引用問題?&#xff0c;同時不增加對象的引用計數。它的實現原理基于與 std::shared_ptr 共享的 ?控制塊&#xff08;Control Blo…

【ManiSkill】環境success條件和reward函數學習筆記

1. “PickCube-v1” info["success"]&#xff1a;用于指示任務是否成功完成 布爾型張量&#xff0c;在環境的evaluate()方法中計算并返回&#xff1a; "success": is_obj_placed & is_robot_static這確保了機器人不僅能將物體準確放置在目標位置&am…

用空閑時間做了一個小程序-二維碼生成器

一直在摸魚中賺錢的大家好呀~ 先向各位魚友們匯報一下情況&#xff0c;目前小程序已經有900的魚友注冊使用過。雖然每天都有新的魚友注冊&#xff0c;但是魚友增長的還很緩慢。自從國慶前的文字轉語音的工具上線到現在已經將近有1個月沒有更新小程序了。但是今天終終終終終于又…

31天Python入門——第14天:異常處理

你好&#xff0c;我是安然無虞。 文章目錄 異常處理1. Python異常2. 異常捕獲try-except語句捕獲所有的異常信息獲取異常對象finally塊 3. raise語句4. 自定義異常5. 函數調用里面產生的異常補充練習 異常處理 1. Python異常 Python異常指的是在程序執行過程中發生的錯誤或異…

PyQt6實例_批量下載pdf工具_使用pyinstaller與installForge打包成exe文件

目錄 前置&#xff1a; 步驟&#xff1a; step one 準備好已開發完畢的項目代碼 step two 安裝pyinstaller step three 執行pyinstaller pdfdownload.py&#xff0c;獲取初始.spec文件 step four 修改.spec文件&#xff0c;將data文件夾加入到打包程序中 step five 增加…

Axure項目實戰:智慧城市APP(完整交互匯總版)

親愛的小伙伴&#xff0c;在您瀏覽之前&#xff0c;煩請關注一下&#xff0c;在此深表感謝&#xff01; 課程主題&#xff1a;智慧城市APP 主要內容&#xff1a;主功能&#xff08;社保查詢、醫療信息、公交查詢等&#xff09;、活動、消息、我的頁面匯總 應用場景&#xff…

Appium Inspector使用教程

1.下載最新版本 https://github.com/appium/appium-inspector/releases 2.本地啟動一個Appium服務 若Android SDK已安裝Appium服務&#xff0c;則在任意terminal使用appium啟動服務即可 3.Appium Inspector客戶端配置連接到Appium服務 Configuring and Starting a Session…

Pycharm(七):幾個簡單案例

一.剪刀石頭布 需求&#xff1a;和電腦玩剪刀石頭布游戲 考察點&#xff1a;1.隨機數&#xff1b;2.判斷語句 import random # numrandom.randint(1,3) # print(num) # print(**30) #1.錄入玩家手勢 playerint(input(請輸入手勢&#xff1a;&#xff08;1.剪刀 2.石頭 3&…

Python Cookbook-4.13 獲取字典的一個子集

任務 你有一個巨大的字典&#xff0c;字典中的一些鍵屬于一個特定的集合&#xff0c;而你想創建一個包含這個鍵集合及其對應值的新字典。 解決方案 如果你不想改動原字典: def sub_dict(somedict,somekeys,default None):return dict([(k, somedict.get(k,default)) for k…

VMware Ubuntu 網絡配置全攻略:從斷網到暢通無阻

一、網絡連接模式選擇&#xff08;先搞懂原理&#xff09; VMware提供三種網絡模式&#xff0c;就像手機的不同網絡套餐&#xff1a; 模式適用場景特點類比NAT個人上網/新手首選虛擬機共享主機IP&#xff0c;能上網但隱身家用WiFi橋接服務器/需要被局域網訪問虛擬機會獲得獨立…

鏈表(C++)

這是本人第二次學習鏈表&#xff0c;第一次學習鏈表是在大一上的C語言課上&#xff0c;首次接觸&#xff0c;感到有些難&#xff1b;第二次是在大一下學習數據結構時&#xff08;就是這次&#xff09;&#xff0c;使用C再次理解鏈表。同時&#xff0c;這也是開啟數據結構學習寫…

【SPP】藍牙串口協議應用層深度解析:從連接建立到實戰開發

目錄 一、SPP應用層協議框架與角色模型 1.1 分層協議棧模型 1.2 設備角色模型&#xff08;DevA 與 DevB 交互&#xff09; 二、連接建立流程&#xff1a;從 SDP 到 RFCOMM 2.1 服務發現&#xff08;SDP&#xff09;流程&#xff08;SDP 記錄關鍵參數&#xff09; 2.2 連接…

Giteki 認證:無線產品進入日本市場的關鍵保障

目錄 適用產品認證范圍 認證項目及技術要求 認證流程 認證周期 與其他認證的對比 常見問題 注意事項 Giteki 認證&#xff0c;其名稱來源于日本語 “技適マーク”&#xff0c;羅馬字拼寫為 “GITEKI” &#xff0c;在行業內也常被稱為 Telec 認證、MIC 認證、RF 認證或技…

Ubuntu24.04 配置遠程桌面服務

一&#xff1a;安裝 sudo apt update sudo apt install vino 二&#xff1a;設置 gsettings set org.gnome.Vino require-encryption false # 關閉加密&#xff08;某些 VNC 客戶端不支持加密&#xff09; gsettings set org.gnome.Vino prompt-enabled false # 關閉連接…

人工智能與軟件工程結合的發展趨勢

AI與軟件工程的結合正在深刻改變軟件開發的流程、工具和方法&#xff0c;其發展方向涵蓋了從代碼生成到系統維護的整個生命周期。以下是主要的發展方向和技術趨勢&#xff1a; 1. 軟件架構體系的重構 從“面向過程”到“面向目標”的架構轉型&#xff1a; AI驅動軟件設計以目標…

轉發和重定向的區別詳解

轉發&#xff08;Forward&#xff09;和重定向&#xff08;Redirect&#xff09;是 Web 開發中兩種常用的請求處理方式&#xff0c;主要用于將客戶端請求從一個資源轉移到另一個資源。它們在實現機制、行為表現和應用場景上有顯著區別&#xff0c;以下是對兩者的詳細解析&#…

python專題1-----判斷一個變量是否是字符串類型

在 Python 中&#xff0c;可以使用 isinstance() 函數來判斷一個變量是否是字符串類型。字符串在 Python 中是以 str 類型表示的。下面是一些示例代碼&#xff0c;展示如何判斷一個變量是否是字符串類型&#xff1a; # 示例變量 var1 "Hello, World!" var2 12345 …

軟件工程之需求工程(需求獲取、分析、驗證)

一、需求獲取&#xff08;Requirements Elicitation&#xff09; 1. 定義與目標 需求獲取是通過與用戶、利益相關者等交互&#xff0c;識別并捕獲系統需求的過程&#xff0c;目標是明確用戶意圖與業務目標&#xff0c;避免后期因需求偏差導致返工。 2. 主要方法 問卷法&…

Java簡單生成pdf

生成這樣的PDF 直接上代碼 public static void main(String[] args) {String logoPath "Q:\\IdeaWork\\Demo\\src\\main\\webapp\\images\\logo.jpg"; // 替換為實際路徑String baseDir "E:/Demo/TEST/problem/Generate"; // 基礎目錄int year 2025; //…