10年前にIPL社員が作ったJava製のシューティングゲームを、Web技術を使ってリメイクしました。 また、JavaからTypeScriptへの移植のポイントについても記載します。
何はともあれゲームを遊ぶ
以下のURLからプレイできます。
https://iplanning.heteml.net/2018-shooting/
Chrome, Firefox, Edgeブラウザで動作確認しております。スマートフォンには非対応です。
操作方法 スペースキー:ゲーム開始&弾を撃つ カーソルキー:上下左右に移動
ハイスコアはお使いのブラウザ内(LocalStorage)に記録されます。
経緯
アイプランニングでは、毎年新人に自由課題を課しています。
ゲームやカロリー計算機など、人によって作るものはそれぞれですが、 10年前に筆者は、当時新しい技術だったJavaとAWTを使って、 簡単なシューティングゲームを作りました。
旧版はこちらで記事にしています。
見た目は下記のような、かなり寂しいものになっています。
10年の時を経て、今やJavaScriptの方が当時のJavaよりも高速に動作する時代です。 JavaScriptはブラウザなどのマルチプラットフォームで動作するという利点があるため、 弊社でもJavaからJavaScriptへの移植案件を度々頂くことがあります。
一方で、JavaScriptは良くも悪くも柔軟なところがあり、バグを作り込みやすく、大規模な開発には向いていません。
これに対処するため、弊社で採用している言語が「TypeScript」です。
TypeScriptとは
TypeScriptは、コンパイルするとJavaScriptを出力する言語です。 (このような言語を一般的にAltJSと呼びます。同種の言語として、ElmやFlowなども人気です)
TypeScriptの最も強力で便利な機能は、型チェックです。
TypeScriptでは、コンパイル時に型チェックを行なうことが出来ます。 最も簡単なサンプルを下記に例示します。
例示したコードでは、name
引数にstring
型を指定しています。
ここで、name
引数に数値を指定すると、型が想定と異なるために、コンパイル時にエラーになります。
また、name
にnull
やundefined
が来ることも防ぐ事が出来ます。
このTypeScriptコンパイラの強力な型チェック機能により、開発者はより安全なコードを書くことが出来ます。
移植作業は、大きなひとかたまりのコードを移植して、エラーを直す作業の繰り返しなので、賢いコンパイラは非常に頼りになる存在です。
TypeScriptはJava開発者におすすめ
アイプランニングには、多くのJava経験者が在籍しています。 その為、Java経験者にとって学習が容易である点も重要です。
その点、TypeScriptはJavaからの移行もスムーズです。理由としては下記が挙げられます。
- TypeScriptはC#に似ていますが、C#に近い言語であるJavaにもある程度文法が似ています。
- クラスやインターフェースがあるため、Javaのフィーリングで書くことが出来ます。
- VSCodeを使うことで、Eclipseのような賢い補完やリファクタ機能を使う事ができます。
ただし、下記の点について注意が必要です。
- TypeScriptは型指定が後置です。
- TypeScriptはStructural Subtyping(構造的部分型) を採用しています。
- 計算精度について注意が必要です。
- JavaScriptの数値は常に浮動小数点数として計算されるため、Javaと計算結果が異なる場合があります。
移植の方法
JavaからTypeScriptへのコンバータは知る限り存在しません。
ということで、ひたすら手で書き換えていきます。対象クラスは13個です。
他のクラスに依存していない、例えばデータクラスの移植を最初に行なうと良いでしょう。一括変換などは現実的ではありません。エラーが出ないことを確認しながら少しずつ置き換える作業になります。
また、作業量を削減するため、最初はany
型を許可する設定(noImplicitAny
を指定しない)にしておきましょう。
例として、プレイヤークラスの移動処理を掲載します。
移植前(Java)
/** * 移動処理 * @param mx x方向の入力(-1 ... +1) * @param my y方向の入力(-1 ... +1) */ public void move(int mx, int my) { //Canvasの外には移動できないようにする double postX = x + mx * speed; double postY = y + my * speed; if ((0 < postX)&&(postX < 500)) { x = postX; } if ((0 < postY)&&(postY < 480)) { y = postY; } }
移植後(TypeScript)
movePlayer(mx: number, my: number) { //Canvasの外には移動できないようにする var postX: number = this.x + mx * this.speed; var postY: number = this.y + my * this.speed; var margin = 50 if (0 + margin < postX && postX < 500- margin) { this.x = postX; } if (0 + margin < postY && postY < 480 - margin) { this.y = postY; } this.mesh.position.x = this.x; this.mesh.position.y = Util.normalize(this.y); }
3D化
折角なので、見た目を豪華にするため、表示を3Dに変更しました。
Web上で3D表示を行なう際は、必ずと言っていいほどThree.jsが採用されます。今回も、Three.jsを使います。
three.js - Javascript 3D library
3Dとはいえ、当たり判定や移動ロジックなどは2Dのものをそのまま流用出来ます。2Dと同じ座標に3Dの物体を配置するようにするだけです。Java版は描画を各オブジェクトに任せるという抽象化を行っていたため、描画部分のみの変更で対応できました。
移植しての感想
- 元バージョンの設計がある程度抽象化されていたため、それほど苦労せずに移植出来ました。
- やはり3Dならではの描画の難しさがありました。ライティングや表示サイズを確認しながら作れないとかなり厳しいです。3DゲームでUnity等のオーサリングツールが主流になっている理由がよく分かります。
- 3Dモデリング能力があればもっと見た目の良いものが出来たのでは無いかと思います。
- Three.jsにはオンラインエディタが存在し、シーンをインタラクティブに作成することが出来ます。そちらを使うようにしたほうが良かったかもしれません。
- 元バージョンではFlyweightパターンを意図したオブジェクトの使い回しを行っていましたが、今となっては不要なテクニックかもしれません。
オンラインエディタは下記のようなインタラクティブなものです。スクリプトも書けるため、使いこなすことで製作効率は上がりそうです。
ソースコード
ソースコードは下記からダウンロード出来ます。
https://iplanning.heteml.net/2018-shooting/ipl-shooting-src.zip
終わりに
JavaからWebアプリへ移行するに当たって、TypeScriptはおすすめの選択肢です。 弊社では業務アプリケーションのWebアプリへの移植も多く行っております。ご相談は弊社メールフォームよりお問い合わせ下さい。