- golang Ver. 1.24.4 以降
リビジョン情報を渡しながら起動してみましょう。
go run -ldflags="-X 'main.Revision=$(git rev-parse --short HEAD)'" *.goタイトル画面にリビジョン情報を含むバージョン情報を表示していますので、以下のようにビルドします。
go build -ldflags="-X 'main.Revision=$(git rev-parse --short HEAD)'"WebAssembly形式へとビルドして、ブラウザで遊ぶこともできます。以下のようにビルドます。
GOOS=js GOARCH=wasm go build -ldflags="-X 'main.Revision=$(git rev-parse --short HEAD)'" -o public/kuronan-dash.wasmあとは、publicフォルダをブラウザで閲覧可能にすれば、ブラウザでゲームをプレイできます。Dockerコンテナのnginxでも良いですし、拙作のminiwebなどの小さなWebサービスでも良いです。
miniweb -p 9000 public上記を実行した場合、ブラウザで http://localhost:9000/ を開きましょう。
golang自体の更新によってファイルの置き場所や処理が変わる場合があるので、 公式のWiki をチェックしよう。
スマホにデプロイして遊んでみる場合は、gomobileを使うのが便利です。公式の手順を見ながらインストールします。
Android端末へのインストールは比較的簡単で、PCからアプリをインストール可能な状態にした端末をPCに接続し、以下を実行します。
gomobile install github.com/kemokemo/kuronan-dash非常に低スペックな環境でも動作することを想定しているため、極力ローカル変数を作らない設計にしています。特に、ebiten.GameのUpdate関数で呼び出される処理はゲームプレイ中に非常に多くの回数呼び出される処理のため、実装のしやすさを犠牲にしてもポインタで保持して管理しながら使うという方針にしています。
音声再生の処理などキャラクターのステータスに応じた処理の一部で、stateの伝搬にgoroutineおよびchannelを使っています。
scenesパッケージのsceneインターフェイスを実装することで、新しいゲーム内の画面やステージを追加可能です。後述するように、フィールドはFieldインターフェイスの実装を、障害物はObstacleインターフェイスの実装、食べ物はFoodインターフェイスの実装をそれぞれ保持しておいて、sceneインターフェイスのUpdateやDraw実装の中で画面の構成要素それぞれにUpdateやDrawを実装することで画面を実現できます。
fieldパッケージのFieldインターフェイスを満たす構造体を作ることで、ステージ毎に異なる雰囲気のフィールドを描画できるようにしています。ステージ1の草原フィールドとして実装したPrairieFieldなどです。
また、フィールド上に配置する障害物やアイテムなど、「レーン上に配置して、キャラクターの動きに応じて位置を変える必要がある物体」についてはScrollableObjectインターフェイスを満たすような構造体にします。さらに、キャラクターが食べてスタミナを回復させる食べ物にする場合はFoodインターフェイスを、岩などのようにキャラクターの進行を妨げる障害物にする場合はObstacleインターフェイスを、それぞれ実装することで実現可能です。
ゲーム画面に描画するキャラクターは、characterパッケージのPlayer構造体で実現しています。キャラクター選択画面での選択情報を元に、ゲーム画面で用いるキャラクターの実体が変わります。ここはインターフェイスにしておらず、Player構造体が保持する画像や音声データなどを変えて作り分けることでキャラクターを作り分けています。
また、同じmoveパッケージのStateMachine構造体は、ユーザーからのインプット情報や上・中・下段のレーン間移動のための状態管理を行う構造体です。レーン間の移動で過去に何度か不具合を出しながらやや複雑な実装にしてしまったので、これをPlayer構造体から切り離してその名の通りステートマシンとして動作させることを意図して切り離したのが発端です。
画面毎にボタン・マウス・タッチによる操作とそれの意味を変えるため、inputパッケージのInputCheckerインターフェイスを画面毎に実装する仕組みにしています。画面で使うボタンを予め保登録しておくことで、「このボタンが押されたら、こうげき操作がトリガーされたとみなす」という処理を全てInputCheckerの実装構造体が行い、ユーザー操作を知りたい他の実装では単にトリガーの有無をbool値でもらうだけでよくなります。
各キャラクターの動きを制御する仕組みに、moveパッケージのVelocityControllerというインターフェイスを使っています。このインターフェイスを実装した構造体をキャラクター毎に実装して、それぞれキャラクター毎に動きをカスタマイズしています。「このキャラは、この状態の時だけちょっと特殊な動きをする」というような仕様にしたくなった時にも、他のキャラに影響を与えず変更できるようにするためです。
また、このゲームは強制スクロールアクションなので、画面上でのキャラクターの描画位置は変えずに、キャラクターの進行速度に応じてそれのマイナス速度をフィールドの各パーツに適用して描画する仕組みを採用しています。