スクリプト/RmakeでACTゲームをつくろう / 第01回 関数を再利用してみよう
最終投稿者:
aoihikawa
更新:2013/04/01 16:28:26
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回 敵の動きや背景の演出を入れてみよう
番外 外部ツールと連携してみよう
この記事についてご質問等がありましたら
こちらのブログ記事のコメントへご投稿、
よろしくお願いいたします。
コメントする
コメントするには、ログインする必要があります。
う~ん・・・ギコのデザインとか作ったあとはこれのどうとかどうやってとか・・・