※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

入門編・9
シューティングゲームもどきを作る

入力を受け取る

さて、今回はいよいよ外部からの入力を受け取ります。

シーンのupdateの中身を追加する

入力を受け取る方法に入る前に、以前解説したゲームの流れ
開始処理
メインループ(表示・入力・計算)
終了処理
の流れをもう少し完成型に近づけましょう。
今回、入力によって自機の位置を移動させますが、この自機の位置が常にスプライトに
反映されるようにしないと、画面上で自機が移動しません。
Scene_Shootingのupdateメソッドに以下の内容を追加してください。
 #--------------------------------------------------------------------------
 # ● フレーム更新
 #--------------------------------------------------------------------------
 def update
   @myMachine.update
   @s_myMachine.update
 end
ゲームオブジェクト、及びスプライトを、update、フレーム更新のたびに更新します。
前回やったように、@s_myMachine.update、つまりスプライトのupdateを入れないと、
自機を動かしてもスプライトの位置に反映されません。
@myMachine.updateは今のところ何もありませんが、今回から処理を追加していきます。

自機にspeedのパラメータを追加する

入力によって自機が移動するようになる前に、自機のスピードを、パラメータとして決めておきましょう。
新たにパラメータを追加する場合は、自機のクラスであるGame_MyMachineに変数を追加します。
これはx座標、y座標の値をx,yとして決めた時と同様、
変数の宣言の所に、
  attr_accessor   :speed                    # 自機移動速度
を、また、初期の値として、initializeメソッドに
 def initialize
   @x=120
   @y=200
   @speed=3  # この行を追加
 end
と行を加えて初期化しましょう。なお、この値は好きに決めて構いません。
これで、Game_MyMachineクラスのインスタンス変数speedが追加されました。

自機のフレーム更新に、入力による移動を追加する

 #--------------------------------------------------------------------------
 # ● 更新
 #--------------------------------------------------------------------------
 def update
   move_by_input
 end
Game_MyMachineクラスのupdateに、入力を受け取って自機を動かすメソッドmove_by_inputを追加します。
そして、その内容を次のように定義します。
 #--------------------------------------------------------------------------
 # ● 方向ボタン入力による移動処理
 #--------------------------------------------------------------------------
 def move_by_input
   case Input.dir8
   when 1;  move_downleft
   when 2;  move_down
   when 3;  move_downright
   when 4;  move_left
   when 6;  move_right
   when 7;  move_upleft
   when 8;  move_up
   when 9;  move_upright
   end
   check_position
 end  
ここでいったん区切ります。
まず見て欲しいのが、定義開始(def)の次の行。
Input.dir8というのがありますね。
これは、方向キーで、どの方向のキーが押されているかを、テンキー(キーボードの右側にある数字キー)の位置1~9に対応した
値に返す、Inputモジュール(RGSS内部)の、dir8というメソッドです。
例えば、左上を押していると7、右を押していると6、というような値を返します。
そして、そのメソッドから返ってきた値が、case~whenで評価されます。
case~whenはRubyの文法で、caseの後ろの値(ここでは、dir8のメソッドが返した値)によって処理を分岐し、
whenの後ろの値と等しい処理を実行するというものです。
例えば、左上、7という値がdir8によって返されたら、when 7の右のmove_upleftが実行されます。
move_○○の内容はまだ定義していません。
下から3行目のendが、case~whenの流れがここで終わっている、という意味のendです。
move_○○と最後から2行目のcheck_positionについては、下に載せます。

 #--------------------------------------------------------------------------
 # ● 実際の移動
 #--------------------------------------------------------------------------
 def move_down
   self.y+=speed
 end
 def move_up
   self.y-=speed
 end 
 def move_right
   self.x+=speed
 end
 def move_left
   self.x-=speed
 end
 def move_downleft
   self.x-=speed*5/7
   self.y+=speed*5/7
 end
 def move_downright
   self.x+=speed*5/7
   self.y+=speed*5/7
 end
 def move_upleft
   self.x-=speed*5/7
   self.y-=speed*5/7
 end
 def move_upright
   self.x+=speed*5/7
   self.y-=speed*5/7
 end
長いですが、似たような文が続いているだけです。
"+="とか"-="というのは、あるパラメータの元の値に値を足したり引いたりという意味で、例えば
   self.y+=speed
は、self.y(自機のy座標)の値にspeedの値(先ほど定めたもの)を足せ、という意味です。
つまり、自機のy座標がspeedの値だけ加算され、自機は下方向に移動します。
方向キーと同じ方向に自機がspeedの値だけ移動するように定義しています。
なお、*5/7というのは、斜めに動く際、斜め移動の距離を調整するためにかけたり割ったりして調整している計算です。
縦と横にspeedだけ動かすと、直線距離ではspeedより大きな距離を移動してしまうためです。
数学が得意な方なら、およそ√2で割っていると言った方がいいでしょうか。
ところで、self.speedとしなくていいんでしょうかね?
打ってから気づいたんですが、これでも動いてるのでしなくてもいいんでしょう。
式の右辺のパラメータのselfは省略できる気がします。

画面からはみ出さないようにする

さて、これによって入力を受け取って移動したわけですが、
このままだと画面を飛び出してどこまでも移動できてしまいます。
まあ多少飛び出てもエラーにはならないんですが、あまりxやyが大きくなると変数の取れる値をオーバーして
強制終了とかになってしまう気がします。そこで、次のメソッドcheck_positionで値を画面内に納めます。
 #--------------------------------------------------------------------------
 # ● 画面からはみ出てないかのチェック
 #--------------------------------------------------------------------------
 def check_position
   self.x = [[@x, 0].max, WND_X-SIZE_X].min
   self.y = [[@y, 0].max, WND_Y-SIZE_Y].min
 end
ややこしい文です。この文は、
[@x, 0].max
でまず一区切り、このmaxというのは、[]内の値の大きい方を返す、というメソッドです。
これもRubyの文法です。続いて、返された大きい方の値を使って、
[(大きい方の値), WND_X-SIZE_X].min
今度は、小さい方の値を返すメソッドを使っています。
WND_X-SIZE_Xは、定数の引き算で、WND_Xは画面サイズ、SIZE_Xは自機サイズです。
なぜSIZE_Xを引くのか分からない人は、引かないとどうなるか試してみましょう。自機のサイズ分はみ出ます。

で、このmaxとminを使って、何をしているんでしょうか?
これは、xの値を、0からWND_X-SIZE_Xの値の範囲になるように、はみ出ていたら最小値または最大値に等しくなるように
修正する役割をしています。
例えば、自機のx座標が-120だとしましょう。すると、最初の[@x, 0].maxでは、-120と0の大きい方、つまり0が返されます。
次に、0とWND_X-SIZE_Xの小さい方、0が返され、この値がself.xに代入されます。
つまり、-120という位置が0に修正されます。
大きい方も同様です。考えてみましょう。
この手法は、RPG内でも所持金が変な値にならないように決めたりする際に使われています。

Input.dir8は、『入力を受け取る』ではない

細かい話になりますが、以前メインループは表示・入力・更新というループで動いていると言いました。
今回のInput.dir8は、あたかも入力に相当するかのようですが、実は入力ではなく更新に含まれます
(update内に入っているので、立場的に『更新』なのは明らかです)。
入力、に相当するのは、あくまでInput.updateの部分。ここで受け取った入力を使って、Input.dir8が
どんな値になるのかを計算しています。

なぜこんな細かい話をするかというと、updateの間にInput.dir8の値が変わったら困る! と考える人が
いるかも知れないからです。
一度Input.updateをしたら、次のInput.updateまでInput.dir8他Input関連の値は変わりません。
なので、まあ、そういった部分の記述に気を配らなくても大丈夫です。



  • すごくわかりやすいです!!
    わかりやすい講座を探していたのでありがたいです。
    続き楽しみにしています! -- (名無しさん) 2009-04-11 17:41:26
  • コメントありがとうございます。
    こんなに早く反応があるとは……。
    ヘルプの解説を含め、シーンの構造などを説明しているものが
    ほとんどなかったのが不満で、作ってみました。
    本当に実はあんまり分かっていないので、至らないところも
    多いかと思いますが、よろしくお願いします。 -- (管理人) 2009-04-11 18:58:22
  • すいません、『自機を表示する』の記述に誤りがありました。
    updateの中身を書かないと、自機の位置が正しく反映されません。
    記事を修正しておきます。 -- (管理人) 2009-04-14 21:59:20
  • ツクール古参ですがRGSSに四苦八苦でした(^^;)
    が、シーンの基本構造を解説した記事にガチで救われました
    応援してるんで、がんばってください!!続き楽しみです。

    -- (うきぶくろ) 2009-04-27 12:17:15
  • コメントありがとうございます。
    一番書きたかったそのあたりは書いたもののなんだか忙しい+
    自分でもRGSSの解読に手間取っているためになかなか更新できていません。
    どの程度まで書けるか分かりませんがよろしくお願いします。 -- (管理人) 2009-04-28 08:40:35
  • 敵キャラを作成する・2の最後の方に、
    updateの際に敵キャラを扱うスプライトの更新を行うのを忘れていたのを修正しました。
    イタリック体で修正が入っている部分です。 -- (管理人) 2009-05-02 22:10:23
  • UFOが見にくかったので画像に縁取りをつけました。 -- (管理人) 2009-05-04 08:56:56
  • ホントにスゴイと思います。尊敬します。
    大変だと思いますが少しずつでいいんで頑張ってください。 -- (ユウ) 2009-05-12 00:07:40
  • コメントありがとうございます。
    恐らくこれを見て作る側はすぐなんでたいそうもどかしいと思いますが……。
    ところで、今のところはちゃんとこの講座の通りで動くようになっているのでしょうか?
    一応チェックはしてますが、多少ポカはすると思ってたので指摘が無いのがむしろ意外です。 -- (管理人) 2009-05-13 21:11:52
  • 大丈夫です。ちゃんと動いています。
    頑張ってください。続きが楽しみです。 -- (ユウ) 2009-05-18 01:06:59
  • 1段目と言われている部分は『RGSS2』
    2段目と言われている部分は『プリセットのスクリプト』
    と言われると、より解り易い表現なのでは? -- (通行人) 2009-11-05 12:48:40
  • @enemies[i] = Game_Enemy.new(200 + rand(312), rand(384))
    ↑argumentErrorが発生しました。wrong number of arguments(2 for 0)
    どうすればいいでしょうか、頼みます。
    -- (help me!!) 2010-01-05 00:22:50
  • マウス入力はできますぜ。
    Win32とかなんやらをつかって。
    キーボードもできるみたいですが見つかりません。
    探してます。 -- (シャミラ) 2010-03-24 05:28:28
  • 勉強させてもらってます、とても参考になります。
    入門編・10 にあるGame_Ememiesのクラスの
    attr_accessor ;s_enemies ですが、;を:に変えないとエラーを吐きますので
    コピペでやった人は修正した方がよさそうです
    -- (邯鄲) 2010-09-04 17:27:18
  • @enemies[i] = Game_Enemy.new(200 + rand(312), rand(384))
    ↑argumentErrorが発生しました。wrong number of arguments(2 for 0)

    Game_Enemyクラスって最初からありますよね。
    それが原因では? -- (ぽん) 2010-10-03 23:11:42
  • 製作初心者なのでとても助かります!! -- (ありがとうございます!) 2011-02-05 12:44:03
  • セーブ/ロードまわりはMarshalを使ってスクリプトで記述されていますし、
    ファイルの読み書きもRubyと同様にできますから、
    セーブやロードをいじるのはスクリプト操作でできることでは? -- (ななし) 2011-05-20 13:04:19
  • ダンジョンなら3D化できると、下記サイトに書いてありました。 -- (だれかさん) 2011-08-18 07:26:19
  • アルバイトはじめましたd(´∀`*)グッ♪ http://64n.co/ -- (私だ) 2012-01-09 04:49:41
  • 風俗店を探よりココ!!男性は報酬あり!d(´∀`*)→ http://www.44m4.net/ -- (江梨子) 2012-08-20 17:11:02
名前:
コメント:

すべてのコメントを見る