ゲーム Human Resource Machineやってみたらハマってしまった
あいさつ
どうも、はかせです。
今回はいつぞや買ったものの時間が無くて積みゲーと化していた
「Human Resource Machine」というゲームをやってみたら
予想の斜め上で面白かったので書いていきたいと思います。
どういうゲーム
プログラミングをゲームにしたという言葉がぴったりなゲームです。
プレイヤーの動きをプログラミングと同じ要領で組み上げて
左のベルトコンベアから要件にあったデータを右側のベルトコンベアに
移動させるパズルゲームです。
このゲームでやるプログラミングなんですが
低水準言語と呼ばれるもの(アセンブリとか)みたいな感じです。
計算は加減算しかないですし、
C#やC++にあるようなif文やfor文とかもないです。(これが中々むずかしい)
ループはjump命令を上に飛ばすことでのみ実現できます。(goto文ですね)
やりこみ要素としてはプログラムにおける最適化があります。
プログラムの行数やステップ数を最小限にして設定された目標を達成することを目指します。
自分はIOSでやっているのですが縦持ちに切り替えると
それ用の画面配置になります。
あとタブがあって作ったプログラムを3つまで保存しておけるみたいです。
他にもコメントやステップ実行の機能もあります。
そしてこのステップ実行なんですが
なんと戻ることが出来ます。
意図しない結果になった時戻ることで
どこが意図した結果と異なっているかを調べることが出来る神機能です。
(実際の開発環境にも欲しい・・・)
難易度としては最初は簡単ですが
進むにつれて結構難しくなってきます。
今私は21番目のステージまで進みましたが、
17ぐらいから最適化目標を達成していくことが出来なくなってきました。
見る感じ30~40ぐらいステージがあるので
終盤になったら素直にクリアすることさえできなくなるのではないかと
ビクビクしていますw
あとがき
今回はHuman Resource Machineのレビューでした。
私のブログではレビュー系の記事は初めてかもしれないですね。
私がハマった理由は
・難易度調整がしっかりしておりパズルゲームとして楽しめる
・プログラミングの勉強になる
・縦持ち対応や前後へのステップ実行など、
ゲームを遊びやすくする機能が実装されている
・長いロードや反応が遅いなどの操作のストレスがない
といった感じですね。
私自身パズルゲームは好きですし、プログラミングも大好きです。
そして地味にポイントが高いのが後ろ2つですね。
ゲームで大事にすべきポイントって
やってて不要なストレスを感じないかだと私は思うんですよね。
もちろんゲームなのでやってて面白いのは前提だったりするんですけど
面白いゲームって良くも悪くも世にあふれてきているじゃないですか。
となるとただ面白いだけのゲームだと
やりはしてもやり続けてはくれないと思うんですよね。
実際最近のゲームのレビューで評価低いやつとか見てると
ゲームがつまらないっていうより
ロードが長いとか
○○の機能がないからとか
ゲームの内容じゃなくて
ゲームの操作感や機能についての不満が多いように思うんですよ。
そしてやってて不要なストレスを感じるから途中で辞められる。
最後までやってもらえたとしても序盤の印象がすごく悪いから
結局評価は悪いまんま。
これってすごくもったいないなって思うんですよ。
だってプレイ自体がストレスになっているから
肝心のゲームの内容に触れてすらもらえないんですよ?
ちゃんとプレイして中身で評価して貰えれば
神ゲーってなってたかもしれないゲームが、
ロードが長いとかいう理由でク〇ゲーって言われちゃうんですよ?
こう考えていくと
やってて不要なストレスを感じてしまうゲームって
もったいないなって思いませんか?
なので私はゲームをやるときには
やっててゲームの内容に関係のないストレスがあるかないかは
すごく重要視しますし、
作るときにはデータのキャッシュや先読みなどで、
可能な限り不要なストレスを感じる要因を排除することを意識します。
そして今回やったHuman Resource Machineは
少なくとも今のところそういった不要なストレスを私は感じていないので
とてもいいゲームだなと思っています。
それでは今回はこの辺でノシ
プログラミング MVPパターン ~実装編~
あいさつ
どうも、はかせです。
今回はいよいよMVPパターン実装です。
実装
まずはModel、View、Presenterのスクリプトから見ていきます。
Model
public interface IModel<T> { ReadOnlyReactiveProperty<T> ModelRP(); void SetModel(T inValue); } public class TestModel : MonoBehaviour, IModel<int> { private ReactiveProperty<int> mValue; private void Awake() { mValue = new ReactiveProperty<int>(); mValue.Subscribe(x => print(x)); } public ReadOnlyReactiveProperty<int> ModelRP() { return mValue.ToReadOnlyReactiveProperty(); } public void SetModel(int inValue) { mValue.Value = inValue; } private void Update() { if (Input.GetKeyDown(KeyCode.Space)) { mValue.Value++; } } }
View
public interface IView<T> { ReadOnlyReactiveProperty<T> ViewRP(); void SetView(T inValue); } public class TestView : MonoBehaviour, IView<int> { private ReactiveProperty<int> mValue; public Text mText; private void Awake() { mValue = new ReactiveProperty<int>(); mValue.Subscribe(x => mText.text = x.ToString()); } public ReadOnlyReactiveProperty<int> ViewRP() { return mValue.ToReadOnlyReactiveProperty(); } public void SetView(int inValue) { mValue.Value = inValue; } }
Presenter
public class TestPresenter : MonoBehaviour { private void Start() { var model = gameObject.GetComponent<IModel<int>>(); var view = gameObject.GetComponent<IView<int>>(); model.ModelRP().Subscribe(x => view.SetView(x)); view.ViewRP().Subscribe(x => model.SetModel(x)); } }
今回監視と通知にはUniRxのReactivePropertyを使用しています。
(UnityでやるときはUniRx使うのがいいと思います。何より実装が楽ですw)
(そして楽だから改めて説明することがないという致命的な問題がありますw)
ModelとViewは保持しているReactivePropertyの公開と
値の通知を受ける用のメソッドを用意しています。
またModelの実装にはとりあえずSpaceキー入力があった時、
保持している値をインクリメントするようにしてます。
本来のMVPではViewからも更新がModelに行きますが、
今回はざっくりとした説明目的なので
View側は更新を受けてUIの更新のみを行っています。
では実行結果です。
単純に数値が増えているだけですが
UIとロジックの分離には成功しています。
あとがき
今回はMVPパターン実装編でした。
今回の実装ではPresenterのみModelとViewを知っており、
ModelとViewは他の誰も知らないような実装にしました。
入力などにしてもModelやViewが受け取る形にして
とにかくUIと内部ロジックを完全に分断しています。
他にも入力はPresenterが受け取りそれぞれModelとViewに伝えるパターンや、
ModelやViewがPresenterに対して
通知を飛ばしてPresenterを動かすパターンなど
色々な設計や実装があります。
今回の実装はあくまで私がプライベートで使う時に
一番よく使うパターンをあげただけです。
実際使う時は、自分が参加しているプロジェクトにとって
最良のパターンを選択して実装するのがいいと思います。
それでは今回はこの辺でノシ