RmakeでACTゲームをつくろう / 第01回 関数を再利用してみよう
投稿者: aoihikawa 投稿日:2011/09/28 23:14
RmakeでACTゲームをつくろう
第01回 関数を再利用してみよう
こんにちは。
フリーデザイナープログラマー(自称)の
簸川 葵(ひかわ あおい)と申します。
前回、Rmakeで自由なゲームをつくろう の連載では
スクリプトについての基本を学びながら、
シューティングゲーム(STG)をつくってみました。
今回はこのSTGを応用して
アクション(ACT)ゲームを作ってみましょう。
第01回は「関数を再利用してみよう」
というところから始めていきますね。
01-01 前回までのおさらい
Rmakeのゲームは絵や音楽などの素材と、
それをどのように動かすか指示することができる「スクリプト」
の組み合わせで出来ています。
このスクリプトを作り込むことで、
様々なゲームを作り出すことが出来ますが、
規模が大きくなってくるほど、沢山のスクリプトを
書く必要がでてくるため、大変になってきます。
しかし、前回の第1回にて解説いたしました、
自作の「関数」を利用することで、スクリプトを書く量を
ぐっと減らすことができます。
関数とは、処理を代行してくれる便利な纏まりのことです。
例えば、画像を表示したり、アニメーションさせたり、
当たり判定を行ったり、という内容はSTGでもACTでも変わりません。
こういった処理を自作の「関数」で行っている場合、
この関数をコピーしてくる(移植と呼びます)だけで、
同じ処理が行えるようになるわけです。
さて、それでは実際にスクリプトや関数の移植から始めてみましょう。
01-02 必要なスクリプトを移植しよう
第06回 より面白くするために のスクリプトから
まずは、そのまま利用できる関数を移植します。
#メニュー項目等の表示OFF setMenuItemVisible(getMenuBackLog(), false) setMenuItemVisible(getMenuSave(), false) setMenuItemVisible(getMenuLoad(), false) setHelpVisible(false) #キャンバスの初期化 setCanvasVisible(false) deleteAllSprite() drawCanvas() #----- 関数の設定 ----- #スプライトの表示位置を変更する関数 def setSpritePos(img_name, pos, i) if i setSpritePosition(getVariable(img_name)[i], pos[i][0], pos[i][1]) else setSpritePosition(getVariable(img_name), pos[0], pos[1]) end end #画像を設定する関数 def setCreateSprite(img_name, img_no, get, set, set_z, pos, ilen) x = 0; y = 1; w = 2; h = 3 if ilen setVariable(img_name, createArray()) i = 0 while i < ilen getVariable(img_name)[i] = createSprite(img_no) setSpriteRect(getVariable(img_name)[i], get[x], get[y], get[w], get[h], set[x], set[y], set[w], set[h]) setSpriteZOrder(getVariable(img_name)[i], set_z) setSpritePos(img_name, pos, i) i = i + 1 end else setVariable(img_name, createSprite(img_no)) setSpriteRect(getVariable(img_name), get[x], get[y], get[w], get[h], set[x], set[y], set[w], set[h]) setSpriteZOrder(getVariable(img_name), set_z) setSpritePos(img_name, pos) end end
続いて、メイン処理の基盤部分を移植します。
場所は先ほどのスクリプトのすぐ後ろです。
#----- 定数の設定 ----- #FPS管理の設定 draw_setting = 30 #ゲームのメイン処理実行タイミングを設定(ミリ秒) #----- 変数の設定 ----- #FPS管理の設定 fps = 0 fpscount = 0 oldfpstime = 0 draw_count = 0 olddrawtime = 0 draw_flg = false #キー入力フラグの設定 key_flg_left = false; key_flg_right = false key_flg_up = false; key_flg_down = false key_flg_z = false #画面の更新 drawCanvas() setCanvasVisible(true) setBaseTime() #時間計測の開始 startInput() #入力受付の開始 #メインループの開始 mainloop = true while mainloop #----- FPSの計測と判定 ----- timer = getTime() #差分の時間を取得 fps = fps + 1 #FPSのカウント fpscount = timer - oldfpstime if fpscount < (draw_setting * fps) draw_flg = true #最低限のFPSを満たしている場合描画OK else #最低限のFPSを満たしていない場合、前回描画したかどうか if draw_flg draw_flg = false else draw_flg = true end end if fpscount > 999 #1秒を超えたらFPSのカウントをリセットする fps = 0 oldfpstime = timer fpscount = fpscount % 1000 end #----- ゲームのメイン処理実行判定 ----- draw_count = timer - olddrawtime #メイン処理実行タイミングのカウント if draw_setting < draw_count #ゲームのメイン処理実行タイミングになっていたら、カウントをリセットする olddrawtime = timer draw_count = draw_count % draw_setting #キー入力の判定 while hasInput() takeInput() #----- キー入力の判定処理を入れる場所 ----- if isKeyDown("LEFT") key_flg_left = true elsif isKeyUp("LEFT") key_flg_left = false elsif isKeyDown("RIGHT") key_flg_right = true elsif isKeyUp("RIGHT") key_flg_right = false elsif isKeyDown("UP") key_flg_up = true elsif isKeyUp("UP") key_flg_up = false elsif isKeyDown("DOWN") key_flg_down = true elsif isKeyUp("DOWN") key_flg_down = false elsif isKeyDown("Z") key_flg_z = true elsif isKeyUp("Z") key_flg_z = false end end #----- ゲームのメイン処理を入れる場所 ----- #(ゲームの終了時はmainloopをfalseに) #----- 画面の更新 ----- if draw_flg drawCanvas() #描画OKならキャンバスを更新 end else waitTime(1) #ゲームのメイン処理実行タイミングになるまで保留 end end endInput() #入力受付の終了
これで、一通り基盤部分が完成しました。
01-03 チャプターで分割してみよう
スクリプトの量が増えてくると、修正したい箇所やエラーの発生した箇所が
探しにくくなってきます。
これまでは、1つのチャプターに全てのスクリプトを書いてきましたが、
複数のチャプターにスクリプトを分割することで、これを解消することができます。
チャプターについてもスクリプトと同様、上から順に流れるため、
関数などを1つめのチャプター、メイン処理などを2つめのチャプターというように、
スクリプトの流れ順に分割します。
チャプターを追加します。
追加したチャプターに初期スクリプトを書きます。
#メニュー項目等の表示OFF setMenuItemVisible(getMenuBackLog(), false) setMenuItemVisible(getMenuSave(), false) setMenuItemVisible(getMenuLoad(), false) setHelpVisible(false)
01-02の後半部分のスクリプトを切り取り、
追加したチャプターに貼り付けます。
今回は関数とメイン処理で分けたため、すんなりと分割できましたが、
チャプターを分割した場合、ローカル変数は引継ぎされないという点に
注意する必要があります。
ローカル変数を受け渡しする場合、通常変数に変更するか、
関数の引数や戻り値の仕組みを利用するように変更しましょう。
01-04 カスタマイズしながら移植してみよう
キャラクターと背景を描画する仕組みをつくります。
今回もまた、お手軽にスクリプトの作成までできるよう、
サンプルの素材を準備いたしました。
なお、BGMにつきましては助教授さまの音楽素材を利用いたします。
こちらを参考に、クリップからリソースへの登録まで行い、
すぐにスクリプトで利用できるように、準備してください。
まずはチャプター0にて、関数の追加から。
#ここから↑は省略 #キャラクターの表示内容を変更する関数 def setCharSpritePattern(no) img_char_name = "img_char" get_x = 0; get_y = 0; get_w = 96; get_h = 96 set_x = 0; set_y = 0; set_w = 96; set_h = 96 if no == 1 get_x = 0; get_y = 0 elsif no == 2 get_x = 96; get_y = 0 elsif no == 3 get_x = 192; get_y = 0 elsif no == 4 get_x = 288; get_y = 0 elsif no == 5 get_x = 384; get_y = 0 elsif no == 6 get_x = 480; get_y = 0 elsif no == 7 get_x = 576; get_y = 0 elsif no == 8 get_x = 672; get_y = 0 elsif no == 9 get_x = 768; get_y = 0 elsif no == 10 get_x = 864; get_y = 0 elsif no == 11 get_x = 0; get_y = 96 elsif no == 12 get_x = 96; get_y = 96 elsif no == 13 get_x = 192; get_y = 96 elsif no == 14 get_x = 288; get_y = 96 elsif no == 15 get_x = 384; get_y = 96 elsif no == 16 get_x = 480; get_y = 96 elsif no == 17 get_x = 576; get_y = 96 elsif no == 18 get_x = 672; get_y = 96 elsif no == 19 get_x = 768; get_y = 96 elsif no == 20 get_x = 864; get_y = 96 else get_w = 0; get_h = 0 set_w = 0; set_h = 0 end setSpriteRect(getVariable(img_char_name), get_x, get_y, get_w, get_h, set_x, set_y, set_w, set_h) end
内容は、STGにもありました、
キャラクターの表示内容を変更する関数と同様です。
画像サイズと、アニメーションの画像数分、
if文による分岐が追加されています。
次はチャプター1にて、実際の描画処理を追加します。
まずは、初期設定から。
#ここから↑は省略 #----- 定数の設定 ----- #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ x = 0; y = 1; w = 2; h = 3 act_std = 0; act_wrk = 1; act_jmp = 2; act_dmg = 3 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #FPS管理の設定 draw_setting = 30 #ゲームのメイン処理実行タイミングを設定(ミリ秒) #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #キャラクターの設定 char_speed = 7 char_w_max = 800 - 63; char_h_max = 600 - 80 char_anime_change = 6 char_hit = createArray() char_hit[x] = 30; char_hit[y] = 10 char_hit[w] = 33; char_hit[h] = 80 #音楽・効果音の設定 bgm_main = 66498 bgm_vol = 0.7 #----- 画像の設定 ----- get = createArray() set = createArray() #キャラクター画像の設定 img_no = 87833 img_char_name = "img_char" get[x] = 0; get[y] = 96; get[w] = 96; get[h] = 96 set[x] = 0; set[y] = 0; set[w] = 96; set[h] = 96 set_z = 7 pos_char = createArray() pos_char[x] = 96; pos_char[y] = 478 setCreateSprite(img_char_name, img_no, get, set, set_z, pos_char) setSpriteIndependentCamera(getVariable(img_char_name), true) #背景画像の設定 img_no = 79101 img_bg_name = "img_bg" get[x] = 0; get[y] = 0; get[w] = 800; get[h] = 600 set[x] = 0; set[y] = 0; set[w] = 800; set[h] = 600 set_z = 1 pos_bg = createArray() pos_bg[x] = 0; pos_bg[y] = 0 setCreateSprite(img_bg_name, img_no, get, set, set_z, pos_bg) setSpriteIndependentCamera(getVariable(img_bg_name), true) #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #----- 変数の設定 ----- #FPS管理の設定 fps = 0 fpscount = 0 oldfpstime = 0 draw_count = 0 olddrawtime = 0 draw_flg = false #キー入力フラグの設定 key_flg_left = false; key_flg_right = false key_flg_up = false; key_flg_down = false key_flg_z = false #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #アニメーション用カウンター #キャラクター char_anime_count = 0 char_muki = 1 char_act = act_std #キャラクターの当たり判定範囲 char_atari = createArray() char_atari[x] = pos_char[x] + char_hit[x] char_atari[y] = pos_char[y] + char_hit[y] char_atari[w] = char_atari[x] + char_hit[w] char_atari[h] = char_atari[y] + char_hit[h] #音楽の再生開始 playBGM(bgm_main); setMusicVolume(bgm_vol) #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #ここから↓は省略
基本な構造はSTGのから変更はありませんが、
画像ID、音楽IDの変更と、
新たにsetSpriteIndependentCamera関数が追加されています。
setSpriteIndependentCamera関数は、
カメラ移動に連動させて画像を動かすかどうかを設定します。
今回は「true」つまり、カメラが移動しても画像も連動して移動するため、
カメラの位置にとらわれず、常に同じ位置に表示されるようになります。
キー入力による座標の移動をメインループ内に追加します。
#ここから↑は省略 #----- ゲームのメイン処理を入れる場所 ----- #(ゲームの終了時はmainloopをfalseに) #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #----- キャラクターの移動 ----- if key_flg_left #左 pos_char[x] = pos_char[x] - char_speed char_muki = 0 char_act = act_wrk elsif key_flg_right #右 pos_char[x] = pos_char[x] + char_speed char_muki = 1 char_act = act_wrk else char_act = act_std end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #ここから↓は省略
変数「char_muki」はキャラクターの方向、
「char_act」はキャラクターの状態を格納しています。
これらの変数の状態によって、
アニメーション種類の切り替えを行います。
最後に、アニメーション処理をメインループ内に追加します。
先ほどのスクリプトのすぐ下です。
#ここから↑は省略 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #----- キャラクターのアニメーション ----- #アニメーション用カウンター char_anime_count = char_anime_count + 1 if char_anime_count == (char_anime_change * 4) char_anime_count = 0 end #キャラクターの表示を切替 if char_act == act_wrk if char_anime_count < (char_anime_change) setCharSpritePattern(3 + (char_muki * 10)) elsif char_anime_count < (char_anime_change * 2) setCharSpritePattern(4 + (char_muki * 10)) elsif char_anime_count < (char_anime_change * 3) setCharSpritePattern(5 + (char_muki * 10)) else setCharSpritePattern(6 + (char_muki * 10)) end else if char_anime_count < (char_anime_change * 2) setCharSpritePattern(1 + (char_muki * 10)) else setCharSpritePattern(2 + (char_muki * 10)) end end #キャラクターの当たり判定範囲 if key_flg_left || key_flg_right char_atari[x] = pos_char[x] + char_hit[x] char_atari[y] = pos_char[y] + char_hit[y] char_atari[w] = char_atari[x] + char_hit[w] char_atari[h] = char_atari[y] + char_hit[h] if pos_char[x] < -(char_hit[x]) pos_char[x] = -(char_hit[x]) elsif pos_char[x] > char_w_max pos_char[x] = char_w_max end setSpritePos(img_char_name, pos_char) end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #----- 画面の更新 ----- if draw_flg drawCanvas() #描画OKならキャンバスを更新 end #ここから↓は省略
アニメーションのカウンターと種類を元に
キャラクターを描画する関数の変数を変更し、画像を切り替えています。
また、キャラクターの当たり判定を元に、
キャラクターを画面内で移動させています。
スクリプト全体
これで、一通り完成です。
保存、終了をして、テストプレーを行い、
背景とキャラクターの描画、キャラクターの移動が行えるか
確認してみましょう。
01-05 おわりに
いかがでしたでしょうか。
このように、移植の仕方やコツを理解できれば、
以前の作品を元にして、簡単に新しいゲームを作成することができます。
また、他の方が作成された関数やスクリプトも、
効率的に利用できるようになります。
さらに、その仕組みを理解することができれば、
アレンジも自由自在です。
さて、次回は新しい関数を利用して、
「マップを表示してみよう」を実践してみましょう。
第01回 関数を再利用してみよう
第02回 マップを表示してみよう
第03回 敵・アイテムを追加してみよう
第04回 敵の動きや背景の演出を入れてみよう
番外 外部ツールと連携してみよう
コメントする
コメントするには、ログインする必要があります。
コメント一覧
退会したユーザー(投稿日:2011/09/30 19:07,
履歴)
この段階はクリアしたどっ!
僕はいつも、処理を早くするために、できる限り短くしようとして、
逆にエラーが起こったり不都合が発生したりするのですが、
これだと何か問題はありますか?
逆にエラーが起こったり不都合が発生したりするのですが、
これだと何か問題はありますか?
#キャラクターの表示内容を変更する関数 def setCharSpritePattern(no) img_char_name = "img_char" get_x = 0; get_y = 0; get_w = 96; get_h = 96 set_x = 0; set_y = 0; set_w = 96; set_h = 96 if no > 0 && no < 11 get_y = 0 get_x = (no-1)*96 elsif no < 21 get_y = 96 get_x = (no-11)*96 else get_w = 0; get_h = 0 set_w = 0; set_h = 0 end setSpriteRect(getVariable(img_char_name), get_x, get_y, get_w, get_h, set_x, set_y, set_w, set_h) end
退会したユーザー(投稿日:2011/09/29 19:04,
履歴)
キターーーーーッ
>>まずは、「仕組みを理解する」という意味もあり
>>行いたい処理そのままの形のスクリプトで掲載しております。
たしかに、短縮したものを説明に使うと、
仕組みがわかる人にしか何がしたいのか、よく分からないですね(^^;)