いつクリはてブロ

いつになったらクリエイティブするの?

ゲーム開発にMVCモデルを導入する

DXRuby Advent Calendar 2013 10日目です。

9日目はあおいたくさんのAnimeSpriteを使おうでした。
画像素材が充実しているとゲームも華やかになります。
可愛いドット絵がアニメすれば、さらに可愛いのは必然!

なお、今回はそういう華やかさとは正反対の記事になりますのでご了承ください。

MVCモデルって?

さて、皆さんはMVCモデルという言葉を聞いたことがあるでしょうか。

MVCモデル - Google 検索

詳しくはググっていただくとして。
簡単に言えば、ソフトウェア開発の際、プログラムを役割ごとにModel、View、Controllerに分割して管理すれば見通しが良くなる! という話でございます。

それぞれの役割は大体以下のようになっています。

Model

ソフトウェアのシステムロジックを担当する部分です。
ViewとController以外、と言ってしまってもいいかもしれません。

View

ソフトウェアの出力、特にユーザーに対し提示する情報を扱う部分です。
DXRubyで言えば、Window#drawで画像を表示したり、Window#drawFontで文字を表示したりする部分にあたります。

Controller

ソフトウェアの入力、特にユーザーの操作を受け付ける部分です。
DXRubyで言えば、Inputに実装されている、キーボードやマウスの値を参照する部分です。

Model、View、Controllerのそれぞれの関係に注目してみましょう。
Controllerは、ユーザーの入力に従いModelを操作します。
Viewは、Modelの情報を読み取り、画面を構成したり音を鳴らしたりします。
逆の視点で見ると、例えばViewはModelの情報を書き換えることはありませんし、ModelがViewやControllerの値を書き換えることもありません。
また、ViewやControllerがソフトウェアの内部情報(ゲームならスコアやキャラの位置情報など)を独自に持つことも無いことになります。

ゲームを開発している間は、コーディングをしている間に新しい仕様が浮かんできたり(今まで使っていなかったキーに新しいコマンドを割り振ったりとか)、画面の構成もコロコロ変わることが常だと思います。
そのような場合にまるっきり無計画にコーディングを進めれば、何が起こるかは火を見るより明らかです。
MVCを意識したコーディングを身につけると、ゲームの仕様は仕様、キー入力はキー入力、画面表示は画面表示と自分で無意識のうちに分割してコーディングを進めることができるので、
「Zキーでジャンプしたら位置がこうでHPはこうなって画面にはこう表示して……」
などとプログラムが絡まってこんがらがるのを避けることができます。*1

具体的にどう書けばよいかを示すために、サンプルとなるゲームを作りました。

MAGURO
github vivit_jc/maguro


簡単に各ソースファイルを説明します。

main.rb

起動時に実行されるプログラムです。
画面位置や色情報、ゲームの設定値などはここにまとめて書きました。
あとはWindow.loopでModel、View、Controllerを回しているだけです。

view.rb

画面表示はここにまとめました。
このゲームでは、「タイトル画面」「ゲーム画面」「ゲーム終了時画面」「ランキング画面」があるので、ゲームが今どの画面なのかを読み取ってそれぞれを表示しています。

controller.rb

キーとマウスの入力処理によって、Modelに対して行う操作を書いてあります。

game.rb

このソフトウェアのModelの親玉に当たる部分です。
子分のship.rbとfish.rbを引き連れています。
ゲーム内部の情報を全て管理しており、それらの操作の全ても担当しています。

ship.rb,fish.rb

おさかなたくさん^q^


ソースコードを見ると、ViewからはModelの情報を書き換えておらず、ControllerもModelの情報を直接書き換えるのは極めて限定的で、基本的にはキーやマウスの入力に従いModelに命令だけを与え、処理は全部Modelが引き受けているのが分かると思います。

MVCモデル導入のもう一つのメリット

MVCモデルをコーディングに取り入れることによって得られるメリットはもうひとつあります。
それはRuby製の別のソフトウェアに移植する際、圧倒的にラクになるということです。
Rubyには様々なライブラリ(gem)があり、そのおかげで多種多様のOSやデバイスで動かすことができます。
例えばDXRubyを使って作ったゲームをMac上で起動したり、スマートフォンで動かしたり、ブラウザで動かしたりといったことも可能なわけです。
Mac OS Xで動かすなら
Shoes! The easiest little GUI toolkit, for Ruby.
iPhoneで動かすなら
RubyMotion - Ruby for iOS and OS X
Androidなら
Ruboto
アクションゲームなどインタラクティブなゲームなら難しいですが、MAGUROのようなSLGをブラウザで動かすなら
Ruby on Rails
というgemがあります。
DXRubyはWindowsのDirectXを利用しているので、Windows上でしか動きませんが、MVCに分割していれば、移植の際にどこを書き直せばいいのか迷うことはありません。
そのOSやデバイスに合わせて入力部と出力部、つまりControllerとViewだけを書き直せばいいということになります。
Modelに至っては完全にそのまま載せ換えるだけでいいのです。*2

筆者は実際に、DXRubyを利用してゲームを作成した後でRuby on Railsを習得し、ゲームをRuby on Railsに移植することに成功しました。
今はWindows上でしかゲームを動かしていなくても、いつか別のOSやデバイスでゲームを動かしたいと思う日が来るかもしれません。
来るべきその日のために、MVCモデルでプログラムを書いておくことは、スムーズな移植に多大な貢献をしてくれることでしょう。

とはいえ、かくいう私もMVCモデルっぽいプログラムの書き方については勉強中であり、常に「こんな感じかな?」と試行錯誤しながら書いています。
GithubにMAGUROのソースコードを公開していますので、「ここをこうしたらいいよ!」という意見がありましたらどんどんご指摘ください。*3

筆者は最近ずっとRuby on Railsでソフトウェア開発を行っており、DXRubyによるゲーム開発は久しぶりだったのですが、その手軽さと面白さに改めて驚きました。
他のデバイスに移植する前提でも、DXRubyを使えば気軽に試作品を作ることができるので、肝心のゲームの中身そのものの調整や向上に時間を割くことができるのは大きな利点だと思います。

DXRuby発のゲームや開発者の皆さんが、更なるステージへ旅立てるよう願ってやみません。

なんだかDXRubyとあまり関係ない内容になってしまいました……いいのかなコレ。
次はfourxzさんのRuby使ったことない人がDXRubyでゲームを作りたいのでIDE3つインストールしましたです。
めちゃくちゃ参考になりそうなので楽しみです!

*1:ゲームの内部、すなわちModelの中身が複雑化していくのは止められません…

*2:MAGUROについては例外があって、ランキングのセーブとロードはRubyの標準的なファイル入出力を利用していて、それはgame.rbによって行っているので、スマホなどに載せる際に引っかかる可能性はあります

*3:言い訳ですが、このゲームはほぼ1日くらいで作ったので、かなり雑でツッコミどころはたくさんあると思います