みなさんアローラ!13のマハトです.
これは rogy Advent Calendar 2016 の7日目の記事です.

普段はMATLABで作った変なものを紹介する記事を書いている僕ですが,今回はせっかくのAdvent Calendar企画だし少し技術的な記事にしようということで,「どうやったらゲームっぽい動きをMATLABで作れるか」について軽く書きたいと思います.

※この記事はわかりやすさを重視するために厳密には正確でない表記を用いている部分があります.またどうプログラムするかは個人の好みの部分ですので,プログラム例はあくまで参考としてお使いください.

・グラフィックスオブジェクト

 誰もが使ったことのある「plot」をはじめとした,figure上に描画できる図形のことをグラフィックスオブジェクトと言います.グラフィックスオブジェクトを作成する関数は色々ありますが,その全てが返り値としてそのオブジェクト自身を示す変数(グラフィックオブジェクト変数)を返します.
p = plot(t,x);		%pはplot(t,x)自体を指す.
よく使うグラフィックスオブジェクトを下に挙げておきます.それぞれの関数の使い方は各自調べてみてください.
f = figure(); %figureウィンドウ
ax = axes(); %座標軸
pat = patch(x,y,color); %多角形
rec = rectangle('Pos',pos); %曲率を設定可能な長方形
text = text(x,y,text); %文字
im = image(x,y,C); %画像
(ちなみにパズドラのゲーム画面はここに挙げたオブジェクトのみで作ってます)


・プロパティ
 MATLABのグラフィックスオブジェクトには「プロパティ」という設定値がありまして,このプロパティを設定することで図形を編集できます.例えばグラフの線の太さや色はそれぞれ「LineWidth」,「Color」プロパティに対応します.プロパティの値を設定するにはグラフィックスオブジェクト変数を使って
set(オブジェクト変数,'プロパティ名','プロパティ値');
または
オブジェクト変数.プロパティ名 = プロパティ値;
とします.逆に,プロパティの値を知りたいときには
value = get(オブジェクト変数,'プロパティ名');
または
value = オブジェクト変数.プロパティ名;
とします.例えば上のpの色を赤に変えたければ,
set(p,'Color','r');    or    p.Color = 'r';
です.逆にpの色を知りたければ,
p_color = get(p,'Color');    or    p_color = p.Color
です.各オブジェクトが持つプロパティは全てmathworks社のページに載っています.「(オブジェクト名) プロパティ」で調べるとすぐに出てきますので,気になるオブジェクトについていくつか調べてみるといいかもしれません.


・ゲームっぽいプログラムの例
 ここからゲーム制作に話が移ります(いきなり難易度が上がります).ここではこれまでの知識を使って「ドラッグすると図形が動く」というパズドラの一番基礎となるプログラムを例として,それについて解説を入れていきます.
patchとfigureとaxesのプロパティのページを見ながら読み進めるとわかりやすいかと思います.

function test
f = figure();
ax = axes();
axis([0 5 0 5]); %座標の範囲をx:0~5,y:0~5に
pat = patch([0,1,1,0],[0,0,1,1],'r'); %(0,0),(1,0),(1,1),(0,1)を頂点とする正方形
pat.ButtonDownFcn = @bdf; %①

    function bdf(object,eventdata) %patがクリックされた時に実行される関数,objectにはpatが入る
        cp = ax.CurrentPoint %②
        x = cp(1,1);
        y = cp(1,2);
        pat.XData = [x-0.5 x+0.5 x+0.5 x-0.5]; %patの中心のx座標をマウス位置に変更
        pat.YData = [y-0.5 y-0.5 y+0.5 y+0.5]; %patの中心のy座標をマウス位置に変更
        f.WindowButtonMotionFcn = @wbmf; %③
        f.WindowButtonUpFcn = @wbuf; %③
    end

    function wbmf(fig,eventdata) %figure上でマウスが動いた時に実行される関数,figにはfが入る
        cp = ax.CurrentPoint; %④
        x = cp(1,1);
        y = cp(1,2);
        pat.XData = [x-0.5 x+0.5 x+0.5 x-0.5];
        pat.YData = [y-0.5 y-0.5 y+0.5 y+0.5];
    end

    function wbuf(fig,eventdata) %マウスが離れたときに実行される関数,figにはfが入る
        fig.WindowButtonMotionFcn = ''; %⑤
        fig.WindowButtonUpFcn = ''; %⑤
    end
end
―メイン(test)関数―
①patch:ButtonDownFcn
 patchには「ButtonDownFcn」というプロパティがあり,このプロパティの値を「@関数名」と設定しておくことで,patchがマウスでクリックされたときに設定した関数が実行されます.このプログラムでは「bdf」という関数を設定しています. 

―bdf関数―
②axes:CurrentPoint
 axesには「CurrentPoint」というプロパティがあり,マウスが最後にクリックされた座標が行列形式で保存されており,(1,1)にはx座標,(1,2)にはy座標が保存されています.これを使うことでpatをクリックされた位置に移動させることができます.

③figure:WindowButtonMotionFcn,WindowButtonUpFcn
 figureには「WindowButtonMotion(Up)Fcn」というプロパティがあり,①同様関数名を設定しておくことで,figure上でマウスが動いた(離れた)ときに設定した関数が実行されます.このプログラムでは「wbmf(wbuf)」という関数を設定しています. ちなみにメイン関数ではなくbdf関数内で設定している理由は,「ドラッグ」を検知したいからです.マウスが押されてから離れるまでの間にのみ処理が実行されて欲しいわけです.

―wbmf関数― 
④axes:CurrentPoint
 先ほど解説した「CurrentPoint」ですが,figureの「WindowButtonMotionFcn」に何か関数が設定されている場合は「最後にクリックされた場所」ではなく「直前のマウスの座標」が保存されています.そのため,マウスが少しでも動けば「CurrentPoint」の値が更新されていきます.

―wbuf関数― 
⑤ figure:WindowButtonMotionFcn,WindowButtonUpFcn
 先ほど設定した2つの関数の設定をリセットします.これでマウスが離れた後はマウスが動いても何も処理が実行されません.


こんなかんじで,意外と簡単に実装できてしまいます.ちなみにこのpatchを複数のrectangleにして動きに応じて位置が入れ替わるようにしたのがMAT&ドLABンズです.


・まとめ
今回読んでもらった知識があれば結構いろんなものが作れます.色々わかりにくいところもあったと思いますが,講義や課題でシミュレーションしてグラフ作ることにしかMATLABを使っていない人もこれを機に遊んでみてもらえたらな,と思います. 

・今後作りたいもの
 
 修士1年になって忙しくなってきたのでこれまでみたいに色々作れるわけではないですが,とりあえず2つほど作ってみたいなというものがあります.
1.パズドラメーカー
 今のパズドラのコードを整理するとともに,チームやステージなどを自作できるツールを開発できたら面白そうだと思っています. 
2.ポ〇モン
  1つの時間軸があってそれに伴ってNPC達がランダムに色々動く,という処理を前から作ってみたかったので,どうせならポ〇モンでも作ろうかな,というようなかんじです.当初simulinkで作りたかったんですが,自分のPCだとsimulinkが重すぎてとても開発できないので,やるならfigureベースになるかなといった感じ.


以上です. 最後まで読んでいただきありがとうございました!