phaserでアクションRPG Day1
アクションRPGが作りたくなった
あとゲームフレームワークのPhaserがバージョン3になってたので勉強も兼ねて開発経過をメモします
初期状態のおまじない
var config = { type: Phaser.AUTO, width: 400, height: 400, physics: { default: 'arcade', arcade: { debug: true// お好みで } }, scene: { preload: preload, create: create, update: update }, pixelArt: true// アンチエイリアスをoffにする }; var game = new Phaser.Game(config); function preload() { // assetの読み込み } function create() { // 初期化処理 } function update() { // フレーム単位の処理 }
ここは「おまじない」だと思っていい
設定の仕方は以前はセッターを使ってたけど、ver3からはconfigオブジェクトにセットするように変更されたっぽい
その方が引数の拡張がしやすいからかな
設定のポイントはpixelArt
を必ず設定すること
これを設定しないとアンチエイリアスが効いてピクセルが潰れてボケボケな絵になる
ファミコンぽいゲームを作りたいなら必ずpixelArt
をtrueに設定しよう
その他の設定では、今回は物理的な衝突が使いたいのでarcade
という物理演算を使います
arcade
は四角形の衝突等を適当に計算してくれます
あとhtml側はphserをCDNから読み込んでおけばok
<script src="//cdn.jsdelivr.net/npm/phaser@3.11.0/dist/phaser.js"></script>
便利だなぁ
See the Pen ActionRPG Day1 by なおしむ (@naosim) on CodePen.
実行すると真っ黒な画面が表示されました
とりあえず今日はここまで
問題: いい感じの日付取得
下記に月・日を入力するといい感じに日付(年月日)にしてくれる機能がある。
これと同じ機能のメソッドcreateDate()
を完成させよ。
メソッドのインターフェースは↓この通り。
/** * @param {number} month 1-12 * @param {number} dayOfMonth 1-31 * @param {Date} currentDate * @return {Date} */ function createDate(month, dayOfMonth, currentDate) { //TODO: 実装 }
ただし言語はjsでなくてもなんでも良い。
また、monthやdayOfMonthに不正な値(マイナスなど)が入ることは考慮しなくて良い。
求められるスキル: 要件分析、実装
いい感じDate
月:
日:
現在:
結果:
先輩に「メソッドを実行して結果を変数に突っ込め」と言われたら2
前回の記事でメソッドを実行して変数に突っ込む時の思考を整理しました
「そんなの出来て当然」と思った方も多いと思いますが、実はjavaはそんなに甘くないです
ってことで抜き打ちテスト!
以下の問いに答えよ
1. hogeメソッドを実行して変数に突っ込め
class Hoge { public int hoge(String text) { /* 実装省略 */ } }
2. hogeメソッドを実行して変数に突っ込め
class Hoge { public static int hoge(String text) { /* 実装省略 */ } }
3. valueを取得して変数に突っ込め
class Hoge { @Getter private final String value; public String getDoubleValue() { return value + value; } }
4. hogeメソッドを実行して変数に突っ込め
@Component class Hoge { public int hoge(String text) { /* 実装省略 */ } }
5. invokeメソッドを実行して変数に突っ込め
※これはひっかけ問題です
@RestController class Hoge { @RequestMapping(value = "/hello", method = RequestMethod.POST) public Map invoke() { /* 実装省略 */ } }
解答
1
int hoge = new Hoge().hoge("あいうえお");
インスタンスに対してメソッドを呼べばOK
2
int hoge = Hoge.hoge("あいうえお");
クラスに対してメソッドを呼べばOK
3
ここからが本題
@Getter
に注目できればOK
@Getter
はlombokが提供しているアノテーションで、フィールドにつけると"getフィールド名()"の形式のメソッドを自動生成してくれる
今回の場合はvalue
にアノテーションが付いているのでgetValue()
が生成されている
なので正解はこう
String value = new Hoge("あいうえお").getValue();
こんな感じでアノテーションが目に見えないメソッドを生成していることがある
アノテーションの意味を理解しよう
ちなみに今回の問題は@Getter
を理解してないと
「問題はvalue
を取れって言ってるけどprivate
だから取れない。。お?getDoubleValue()
てメソッドがあるぞ。とりあえずこれ使っとこと」
String value = new Hoge("あいうえお").getDoubleValue();
みたいなな違いが起きる
これはアノテーションを理解していない場合に現場でありがちな勘違い
気をつけよう
4
@Component
に注目できればOK
@Component
の場合はDIが絡んでいるのでインスタンス生成に@Autowired
を用いる
なのでどこかで生成してからメソッドを呼べばok
@Autowired
Hoge hoge;
int hoge = hoge.hoge("あいうえお");
ちなみに@Autowired
してから使う系は
@Component
の他にも@Service
や@Repository
などがある
いちおう文法上は普通にnewしても使えるけど、たぶんチームメンバーに怒られる
5
これはもはやRestApiなので普通にnewして呼ぶものじゃない
curlコマンドで呼ぶとか、webClient的なもので呼ぶとか、テストツールで呼ぶとか
まとめ
「メソッドを実行して結果を変数に突っ込め」と言われた時、その実現方法は状況に応じていろいろあることがわかった
とくにlombokやDIなどのアノテーションが絡むと状況判断が難しくなる
アノテーションに気をつけて正しい状況判断ができるようになろう
先輩に「メソッドを実行して結果を変数に突っ込め」と言われたら
javaのコーディング中にこんな風に言われた時に、どんなことを考えているのかを整理しておきます
調査
まず対象となるメソッドが何なのかを調査します
- メソッドはインスタンスメソッドかクラスメソッドか
- 引数の型は何か
- 戻り値の型は何か
たとえば
class StringUtil { int getLength(String text) { /* 実装省略 */ } }
ならこう
- インスタンスメソッド
- 引数の型はString
- 戻り値の型はint
実装
調査が終わったら次は実装です
最初に書くのは戻り値の型です
int
個人的にはここが最もハードルが高いように感じます
どうしてもメソッドの実行を最初に書きたくなるみたい
ただ文法上、変数宣言が先なのでしょうがない
次に書くのはメソッドの結果を入れる変数名
int length
クーーーッ!
まだメソッド実行させてくれないのかー!
て感じですが変数名を決める必要があります
ここで変数名を迂闊にhoge
とかにすると叱られます
適切な名前をつけましょう
次にようやくメソッドの実行です
メソッドがインスタンスメソッドなら変数名.メソッド名()
クラスメソッドならクラス名.メソッド名()
の形式で書きます
今回はインスタンスメソッドなので前者の形式ですが、インスタンスが入ってる変数がないのでそれを先に書きます
StringUtil util = new StringUtil(); int length
次にメソッドを書きます
とりあえず引数は空で良い
StringUtil util = new StringUtil(); int length = util.getLength();
最後に引数を書きます
引数の型を意識して書きます
StringUtil util = new StringUtil(); int length = util.getLength("あいうえお");
以上
まとめ
コーディング中に「メソッドを実行して結果を変数に突っ込め」と言われたときの思考を整理しました
普段は体が勝手に反応するレベルでコーディングしてますが、整理してみるといろいろ考えてるものだな
とりあえず調査してから実装することが重要だと思います
タスクの依存性を表現したタスクボードをmermaidjsで書くと良い
タスク管理の方法としてバックログやタスクかんばん(TODO,DOING,DONEのやつ)を使っていますが、ちょっとツラみを感じています
これらの方法はタスクの優先順位が見える意味では良いけど、タスク間の依存関係が見えない
最近やってる案件がウォーターフォール的なので、優先順位よりもタスクの依存の方が知りたい
そうゆう意味でタスクを管理する方法としてはバリューストリームマップやアローダイアグラムのような図で表現して、終わったらチェックマークをつけていく感じにしたいなぁと
ただなかなかイイツールが無くて...
と思ってたらmermaidjsでイイ感じにかけたーー!
百聞は一見に如かず
説明するより見た方が早いので今回作った図を載せます
タスクの依存関係がわかる!
図から以下のことがわかります
- タスク同士が矢印で繋がっている => の依存関係がわかる
- 大きな枠が月、小さな枠が週 => 週ごとのスケジュールがわかる
- 色 => タスクの状態がわかる
- 赤: 私にアサインされたタスク
- グレー: 完了したタスク
mermaidjsのコード
書いたコードはこちら
graph LR T0[設計] T1[コーディング] T2[テスト] T3[リリース準備] T4[リリース] T5[サービスイン] T0 --> T1 T1 --> T2 T2 --> T4 T3 --> T4 T4 --> T5 subgraph 9月 subgraph 1w T0 T1 end subgraph 2w T2 T3 end subgraph 3w T4 T5 end end classDef done fill:#aaa; classDef naosim fill:#faa; class T0,T1,T3 done; class T2 naosim;
- タスクの内容と依存関係はフローチャートの記法で書く
- スケジュールはsubgraphで書く
- タスクの状態は独自のclassを定義する
タスクで表現したいこと毎にかける
で、mermaidの何が良いかって、コードを見ればわかる通りタスクの内容・依存・スケジュール・状態を別々に管理きる!
やべーーmermaid最高やーー!
まとめ
- mermaidでタスクの依存性表現したタスクボードが作れる
- mermaidならタスクで表現したいこと毎にかけるから良さそう
【GAS + kotlin】コードを分割してメンテしやすくする
前回、GASをkotlinで開発する方法を書きました
この記事で「3万行を超えるkotlin.jsをコードに直接コピペする」と書きましたが、さすがにそれでは辛い
幸いGASは同一プロジェクトのスクリプトを簡単に呼べるのでそれを利用してファイル分割してみました
以下、その方法
前回の最終形態
コード.gs (呼び出し元スクリプト)
// おまじない var ArrayBuffer = Int8Array = Int16Array = Uint16Array = Int32Array = Float32Array = Float64Array = function(){}; // kotlin.jsのコード 3万行超え // gaskotlin.jsのコード 20行くらい // 呼び出し function myFunction() { gaskotlin.com.naosim.gaskotlin.run(); }
ファイルを3つに分割する
kotlin.js.gs
function initKotlin() { // おまじない var ArrayBuffer = Int8Array = Int16Array = Uint16Array = Int32Array = Float32Array = Float64Array = function(){}; // kotlin.jsのコード 3万行超え return kotlin; // 最後にkotlinオブジェクトを返す }
gaskotlin.js.gs
function initGaskotlin() { var kotlin = initKotlin(); // kotlinを読み込む // gaskotlin.jsのコード 20行くらい return gaskotlin;// 最後にgaskotlinオブジェクトを返す }
コード.gs (呼び出し元スクリプト)
var gaskotlin = initGaskotlin(); function myFunction() { gaskotlin.com.naosim.gaskotlin.run(); }
結果
可読性が上がった
当たり前ですが...
3万行のコードは読みにくいので...
ファイルの保存時間が早くなった
3万行のコードを保存した時は保存だけで結構時間がかかっていましたが、それを外だししたら早くなった
GASは保存時に何してるんだろう...
保存するファイルだけシンタックスエラーのチェックが走るのかな?
まとめ
- kotlin.js等を別gsファイルに外だしした
- 保存時間が短くなったりしてよかった