Ink 是 React 在命令行中渲染系統的一個實現, 在 GitHub 上已經有 1w+ Star. 看着蠻好玩, 所以嘗試着寫了一個五子棋遊戲, 通過若干天的划水, 終於初見成效了!node
先來看個演示動畫(Gif 太大這裏放不下, 請移步 GitHub 觀看):react
須要聲明的是: 這個客戶端我已經開源在了 GitHub 上, 地址是 https://github.com/acrazing/g..., 可是這是一個在線遊戲的客戶端, 由於商業緣由, 服務端代碼沒有開源, 因此這篇文章主要描述 Ink + React 構建客戶端的過程, 後續若是有機會的話會考慮寫一篇文章來聊聊服務端的架構與思路.git
首先須要你在本地安裝 node + npm, 而後使用 npm 全局安裝本項目的 npm 包:github
npm i -g gomoku-terminal
這個時候全存在一個命令行入口 gomoku
, 其使用方法是:算法
$ gomoku --help gomoku [options] Options: --version Show version number [boolean] --api the api host [string] [default: "http://23.106.139.99:5001"] --store the config & session store file [string] [default: "~/.gomoku-terminal.json"] --help Show help [boolean]
若是隻啓動一個實例, 則不須要傳遞任何參數在命令行中直接調用便可, 可是若是要啓動多個實例, 則須要傳入 --store
參數, 指向不一樣的文件名, 來儲存會話信息.npm
第一次啓動或者 token 過時時, 會首先進入登陸界面:json
這個時候你須要使用方向鍵來控制焦點, 而後輸入用戶名和密碼再將焦點移動到 Go 上按回車鍵登陸, 或者不輸入用戶名和密碼直接按 Anonymous 進行匿名登陸, 目前註冊接口彷佛有問題, 只支持匿名登陸.api
登陸成功後, 會跳轉到房間列表頁面:bash
這個頁面會展現5個房間, 你可使用上下鍵來選擇一個房間進入(若是有的話), 或者點擊 New 來建立一個房間並進入. 按 R 能夠手動刷新房間列表.session
進入房間後, 會自動跳轉到房間頁面:
這個時候你首先須要按 Ready 鍵(或者按鍵盤 R)來準備, 長時間未準備會被踢出, 雙方均準備後遊戲自動開始. 這個時候若是該你落子的話能夠經過方向鍵來選擇要落子的位置, 而後按回車落子, 長時間未落子會自動判負:
主要有兩個難點:
一個是鍵盤控制, 這個 ink 並無提供一個有效的方案來進行操做, 只提供了一個 StdinContext
來暴露了標準輸入, 而經過按鍵來控制焦點則須要自行實現, 本項目中的實現是經過一個 Focusable
組件來實現的, 具體能夠查看該文件: Focusable.ts.
另外一個是性能問題, Ink 的組件每一次刷新(render)都會觸發一次全量渲染, 這個和 react-dom
不同, react-dom
作了大量的優化(主要是 diff 算法與 patch update). 在繪製棋盤界面的過程當中, 至少須要有255(15 * 15)個元素, 所以必需要嚴格控制每一個 Piece 的刷新過程, 絕對不能出現一個狀態變動致使全部 Piece 都渲染的狀況, 所以只能經過元素局部狀態來控制, 而不能經過 props.
此外, 本項目中使用 mobx
來管理狀態, mobx-sync
來持久化狀態到文件系統, 還實現了一個快捷鍵系統, 具體能夠查看該文件: KeyboardReceiver.
源代碼地址: https://github.com/acrazing/g...
npm 包地址: https://www.npmjs.com/package...