使用 ink + react 製做一個命令行的在線五子棋遊戲客戶端

背景

InkReact 在命令行中渲染系統的一個實現, 在 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

clipboard.png

這個時候你須要使用方向鍵來控制焦點, 而後輸入用戶名和密碼再將焦點移動到 Go 上按回車鍵登陸, 或者不輸入用戶名和密碼直接按 Anonymous 進行匿名登陸, 目前註冊接口彷佛有問題, 只支持匿名登陸.api

登陸成功後, 會跳轉到房間列表頁面:bash

clipboard.png

這個頁面會展現5個房間, 你可使用上下鍵來選擇一個房間進入(若是有的話), 或者點擊 New 來建立一個房間並進入. 按 R 能夠手動刷新房間列表.session

進入房間後, 會自動跳轉到房間頁面:

clipboard.png

這個時候你首先須要按 Ready 鍵(或者按鍵盤 R)來準備, 長時間未準備會被踢出, 雙方均準備後遊戲自動開始. 這個時候若是該你落子的話能夠經過方向鍵來選擇要落子的位置, 而後按回車落子, 長時間未落子會自動判負:

clipboard.png

技術實現

主要有兩個難點:

一個是鍵盤控制, 這個 ink 並無提供一個有效的方案來進行操做, 只提供了一個 StdinContext 來暴露了標準輸入, 而經過按鍵來控制焦點則須要自行實現, 本項目中的實現是經過一個 Focusable 組件來實現的, 具體能夠查看該文件: Focusable.ts.

另外一個是性能問題, Ink 的組件每一次刷新(render)都會觸發一次全量渲染, 這個和 react-dom 不同, react-dom 作了大量的優化(主要是 diff 算法與 patch update). 在繪製棋盤界面的過程當中, 至少須要有255(15 * 15)個元素, 所以必需要嚴格控制每一個 Piece 的刷新過程, 絕對不能出現一個狀態變動致使全部 Piece 都渲染的狀況, 所以只能經過元素局部狀態來控制, 而不能經過 props.

此外, 本項目中使用 mobx 來管理狀態, mobx-sync 來持久化狀態到文件系統, 還實現了一個快捷鍵系統, 具體能夠查看該文件: KeyboardReceiver.

TODO

  • 優化性能: 目前的渲染性能實在太糟糕, 只能說是勉強能用的狀態, 這個須要 ink 自身作大量的優化
  • 優化體驗: 目前只完成了基礎的交互功能, 可是外觀至關醜

源代碼地址: https://github.com/acrazing/g...
npm 包地址: https://www.npmjs.com/package...

相關文章
相關標籤/搜索