RmakeでACTゲームをつくろう / 第04回 敵の動き背景演出を入れてみよう

投稿者:Cdv30200 aoi icon mini aoihikawa 投稿日:2011/10/24 23:47

RmakeでACTゲームをつくろう

 第04回 敵の動きや背景の演出を入れてみよう


  こんにちは。
 フリーデザイナープログラマー(自称)の
 簸川 葵(ひかわ あおい)と申します。


  第03回 では「敵・アイテムを追加してみよう」ということで、
 一通りのACTゲーム完成まで、お話しました。

  今回はより面白くするために、敵の動きや背景の演出を
 追加してみましょう。



04-01 敵に移動AIを追加する




  敵を移動させるAIを追加してみましょう。

  今回製作するAIのパターンは、
 通常は横に移動しますが、壁や崖に接すると
 進行方向を反対側に変えます。

  基本はキャラクターとマップの当たり判定と
 同様のスクリプトを書きますが、
 動きがキャラクターよりも単純なため、
 スクリプトの軽量化を考えて、
 判定するポイントを2点に絞ります。



  敵キャラクターの当たり判定のうち、
 縦方向の中央付近を壁判定に、
 縦方向の下部を床判定にします。



  それでは、実際にスクリプトを書いていきましょう。
 まずはチャプター1にて、定数の準備から。
#ここから↑は省略
#敵キャラクターの設定
max_enemy = 3
enemy_anime_change = 2
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
enemy_speed = 5
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
#ここから↓は省略

  「enemy_speed」は敵キャラクターの移動速度を設定しています。


  敵のアニメーションに移動するスクリプトを追加します。
#ここから↑は省略
#----- 敵キャラクターのアニメーション -----
        i = 0
        while i < max_enemy
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
            #敵キャラクターAI
            enemy_hit_flg = false  #方向転換フラグ
            
            #敵キャラクターの当たり判定範囲
            enemyHitpos_Y1 = floor((getVariable(pos_enemy)[i][y] + 
                             enemy_hit[y] + (enemy_hit[h] * 0.5) + 16) / 32)
            enemyHitpos_Y2 = floor((getVariable(pos_enemy)[i][y] + 
                             enemy_hit[y] + enemy_hit[h] + 32) / 32)
            
            if enemy_muki[i] == 0
                #左向き
                
                #当たり判定の座標を算出
                enemyHitpos_X1 = floor((getVariable(pos_enemy)[i][x] + 
                                 enemy_hit[x]) / 32)
                
                enemyHit_X = getVariable("hit_map")[enemyHitpos_Y1][enemyHitpos_X1]
                enemyHit_Y = getVariable("hit_map")[enemyHitpos_Y2][enemyHitpos_X1]
                
                getVariable(pos_enemy)[i][x] = getVariable(pos_enemy)[i][x] - enemy_speed
                
                #敵キャラクターの当たり判定左端の座標を取得
                hit_x = getVariable(pos_enemy)[i][x] + enemy_hit[x]
                
                if hit_x < 0
                    #画面端の判定
                    getVariable(pos_enemy)[i][x] = getVariable(pos_enemy)[i][x] - 
                                                   hit_x
                    enemy_hit_flg = true
                elsif (enemyHit_X != 19) ||
                      (enemyHit_Y == 19)
                    #壁または崖の判定
                    getVariable(pos_enemy)[i][x] = getVariable(pos_enemy)[i][x] + 
                                                   enemy_speed
                    enemy_hit_flg = true
                end
                #向きを反転する
                if enemy_hit_flg
                    enemy_muki[i] = 1
                end
            else
                #右向き
                
                #当たり判定の座標を算出
                enemyHitpos_X2 = floor((getVariable(pos_enemy)[i][x] + 
                                 enemy_hit[x] + enemy_hit[w]) / 32)
                
                enemyHit_X = getVariable("hit_map")[enemyHitpos_Y1][enemyHitpos_X2]
                enemyHit_Y = getVariable("hit_map")[enemyHitpos_Y2][enemyHitpos_X2]
                
                getVariable(pos_enemy)[i][x] = getVariable(pos_enemy)[i][x] + enemy_speed
                
                #敵キャラクターの当たり判定右端の座標を取得
                hit_x = getVariable(pos_enemy)[i][x] + enemy_hit[x] + enemy_hit[w]
                
                if hit_x > map_max_w
                    #画面端の判定
                    getVariable(pos_enemy)[i][x] = getVariable(pos_enemy)[i][x] - 
                                                   (hit_x - map_max_w)
                    enemy_hit_flg = true
                elsif (enemyHit_X != 19) ||
                      (enemyHit_Y == 19)
                    #壁または崖の判定
                    getVariable(pos_enemy)[i][x] = getVariable(pos_enemy)[i][x] - 
                                                   enemy_speed
                    enemy_hit_flg = true
                end
                #向きを反転する
                if enemy_hit_flg
                    enemy_muki[i] = 0
                end
            end
            
            #変更した座標に画像を移動する
            setSpritePosition(getVariable(img_enemy_name)[i], 
                              getVariable(pos_enemy)[i][x], getVariable(pos_enemy)[i][y])
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
            #アニメーション用カウンター
            enemy_anime_count[i] = enemy_anime_count[i] + 1
            if enemy_anime_count[i] == (enemy_anime_change * 4)
                enemy_anime_count[i] = 0
            end
#ここから↓は省略

  取得するY座標は左向き、右向き共に共通ですが、
 取得するX座標は向きによって取得するポイントを切り替えています。

  壁か崖の判定に入ったとき、「enemy_hit_flg」変数をオンに変更し、
 「enemy_hit_flg」がオンの場合、向きを反転する仕組みになっています。



  ここまでで、敵を移動させるAIができました。
 保存、終了をして、テストプレーを行い、
 敵が移動するか確認してみましょう。





04-02 敵を踏んで倒せるようにする




  敵を踏むことで倒せるようにしてみましょう。
 キャラクターと敵の当たり判定の位置判定を分けることで
 踏んでいるかどうかを判断します。




  それではチャプター1にて、定数の準備から。
#ここから↑は省略
#敵キャラクターの設定
max_enemy = 3
enemy_anime_change = 2
enemy_speed = 5

enemy_hit = createArray()
enemy_hit[x] = 10;          enemy_hit[y] = 10
enemy_hit[w] = 35;          enemy_hit[h] = 35
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
enemy_point = 100
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
#ここから↓は省略

  「enemy_point」は敵キャラクターを倒したときに
 獲得できるスコアの設定です。


  次は、変数の準備。
#ここから↑は省略
#敵キャラクター
enemy_anime_count = createArray()
enemy_muki = createArray()
enemy_act = createArray()
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
enemy_dmg_count = createArray()
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
enemy_atari = createArray()
i = 0
while i < max_enemy
    enemy_anime_count[i] = 0
    enemy_muki[i] = 0
    enemy_act[i] = act_wrk
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
    enemy_dmg_count[i] = 0
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
    #敵キャラクターの当たり判定範囲
    enemy_atari[i] = createArray()
    enemy_atari[i][x] = getVariable(pos_enemy)[i][x] + enemy_hit[x] - getVariable(pos_map)[x]
    enemy_atari[i][y] = getVariable(pos_enemy)[i][y] + enemy_hit[y] - getVariable(pos_map)[y]
    enemy_atari[i][w] = enemy_atari[i][x] + enemy_hit[w]
    enemy_atari[i][h] = enemy_atari[i][y] + enemy_hit[h]
    
    i = i + 1
end
#ここから↓は省略

  「enemy_dmg_count」は敵キャラクターを倒したときの
 アニメーション、状態を管理するカウンターです。


  敵キャラクターに、倒された時のアニメーションを追加します。
#ここから↑は省略
        #----- 敵キャラクターのアニメーション -----
        i = 0
        while i < max_enemy
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
            if enemy_act[i] == act_dmg
                #ダメージ中の場合
                
                if enemy_dmg_count[i] < 40
                    #ダメージ中カウント
                    enemy_dmg_count[i] = enemy_dmg_count[i] + 1
                    
                    if enemy_dmg_count[i] == 40
                        #画面外へ移動する
                        getVariable(pos_enemy)[i][x] = (-100)
                        getVariable(pos_enemy)[i][y] = 610
                        
                        setSpritePosition(getVariable(img_enemy_name)[i], 
                                  getVariable(pos_enemy)[i][x], getVariable(pos_enemy)[i][y])
                    end
                end
                
            else
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
                #敵キャラクターAI
                enemy_hit_flg = false  #方向転換フラグ
                
#中略
                setSpritePosition(getVariable(img_enemy_name)[i], 
                                  getVariable(pos_enemy)[i][x], getVariable(pos_enemy)[i][y])
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
            end
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
            #アニメーション用カウンター
            enemy_anime_count[i] = enemy_anime_count[i] + 1
            if enemy_anime_count[i] == (enemy_anime_change * 4)
                enemy_anime_count[i] = 0
            end
            
            #敵キャラクターの表示を切替
            if enemy_act[i] == act_dmg
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
                if enemy_dmg_count[i] < 10
                    setEnemySpritePattern(4 + (enemy_muki[i] * 4), i)
                else
                    setEnemySpritePattern(3 + (enemy_muki[i] * 4), i)
                end
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
            else
                if enemy_anime_count[i] < (enemy_anime_change * 2)
                    setEnemySpritePattern(1 + (enemy_muki[i] * 4), i)
                else
                    setEnemySpritePattern(2 + (enemy_muki[i] * 4), i)
                end
            end
#ここから↓は省略

  敵キャラクターがダメージ中だった場合、
 ダメージ状態カウンターが10より下かどうかで
 表示を切り替えています。
  また、ダメージ状態カウンターが40を超えた場合、
 画面外に移動することで、敵キャラクターの表示を消しています。



  敵キャラクターを踏んだかどうか、
 判定するスクリプトを追加します。
#ここから↑は省略
            #_/_/_/ 敵キャラクターとの当たり判定 _/_/_/
            i = 0
            while i < max_enemy
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
                if enemy_act[i] != act_dmg
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
                    #敵キャラクターの当たり判定範囲
                    enemy_atari[i] = createArray()
                    enemy_atari[i][x] = getVariable(pos_enemy)[i][x] + 
                                        enemy_hit[x] - getVariable(pos_map)[x]
                    enemy_atari[i][y] = getVariable(pos_enemy)[i][y] + 
                                        enemy_hit[y] - getVariable(pos_map)[y]
                    enemy_atari[i][w] = enemy_atari[i][x] + enemy_hit[w]
                    enemy_atari[i][h] = enemy_atari[i][y] + enemy_hit[h]
#_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/
                    #当たり判定のチェック
                    if ((char_atari[x3]) > (enemy_atari[i][x])) && 
                       ((char_atari[y2]) > (enemy_atari[i][y])) && 
                       ((char_atari[x1]) < (enemy_atari[i][w])) && 
                       ((char_atari[y1]) < (enemy_atari[i][h]))
                        #----- 上半身 -----
                        
                        #ゲームオーバー開始
                        char_act = act_dmg; char_dmg_count = 0
                        
                        fadeOutMusicStop(100)  #音楽の停止
                        
                    elsif ((char_atari[x3]) > (enemy_atari[i][x])) && 
                          ((char_atari[y3]) > (enemy_atari[i][y])) && 
                          ((char_atari[x1]) < (enemy_atari[i][w])) && 
                          ((char_atari[y2]) < (enemy_atari[i][h]))
                        #----- 下半身 -----
                        
                        if char_act != act_jmp
                            #ゲームオーバー開始
                            char_act = act_dmg; char_dmg_count = 0
                            
                            fadeOutMusicStop(100)  #音楽の停止
                            
                        else
                            #敵を倒す
                            score = score + enemy_point
                            
                            char_act = act_jmp; char_jmp_count = 5
                            
                            enemy_act[i] = act_dmg
                            enemy_dmg_count[i] = 0
                            
                        end
                    end
                end
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
#ここから↓は省略

  キャラクターの当たり判定と敵キャラクターの当たり判定範囲によって
 上半身、下半身のどちらが当たったか、スクリプトを分岐しています。

  また、敵を倒したときにキャラクターが少しだけ弾むように、
 ジャンプカウンターが5の状態の、ジャンプ状態に変更しています。



  ここまでで、敵を踏んで倒せる仕組みができました。
 保存、終了をして、テストプレーを行い、
 敵が倒せるかどうか確認してみましょう。





04-03 背景を多重スクロールにする




  現在、背景とマップを表示している間に
 マップよりも少しゆっくりとスクロールする背景を追加して
 多重スクロール背景にしてみましょう。

  第02回で追加した「setCreateMap」関数を利用します。


  まずは、背景マップの追加から。
#マップ画像の設定
img_no = 79094
map_size = 5
#_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/
img_map_name = "img_map"
pos_map_bg = "pos_map_bg"; pos_map = "pos_map"
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
setVariable(pos_map_bg, createArray())
getVariable(pos_map_bg)[x] = 0; getVariable(pos_map_bg)[y] = -8
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
setVariable(pos_map, createArray())
getVariable(pos_map)[x] = 0; getVariable(pos_map)[y] = -8

#マップデータの配列を準備
map_data = createArray()
map_data[00] = createArray()
map_data[01] = createArray()
map_data[02] = createArray()
map_data[03] = createArray()
map_data[04] = createArray()
map_data[05] = createArray()
map_data[06] = createArray()
map_data[07] = createArray()
map_data[08] = createArray()
map_data[09] = createArray()
map_data[10] = createArray()
map_data[11] = createArray()
map_data[12] = createArray()
map_data[13] = createArray()
map_data[14] = createArray()
map_data[15] = createArray()
map_data[16] = createArray()
map_data[17] = createArray()
map_data[18] = createArray()

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
map_bg_stno = getVariable(img_bg_name) + 1  #背景マップデータ開始位置番号

set_z = 2

#背景マップデータを作成
map_data[00][0] = 019019019019019; map_data[00][1] = 019019019019019; map_data[00][2] = 019019019019019
map_data[01][0] = 019019019019019; map_data[01][1] = 019019019019019; map_data[01][2] = 019019019019019
map_data[02][0] = 019019019019019; map_data[02][1] = 019019019019019; map_data[02][2] = 019019019019019
map_data[03][0] = 019019019019019; map_data[03][1] = 019019019019019; map_data[03][2] = 019019019019019
map_data[04][0] = 019019019019019; map_data[04][1] = 019019019019019; map_data[04][2] = 019019019019019
map_data[05][0] = 019019019019019; map_data[05][1] = 019019019019019; map_data[05][2] = 019019019019244
map_data[06][0] = 019019019240241; map_data[06][1] = 019019019019019; map_data[06][2] = 019019019019019
map_data[07][0] = 019019019019019; map_data[07][1] = 019019019019019; map_data[07][2] = 019019019019019
map_data[08][0] = 019019019019019; map_data[08][1] = 019019019019242; map_data[08][2] = 243019019019019
map_data[09][0] = 019019019019019; map_data[09][1] = 019019019019019; map_data[09][2] = 019019019019019
map_data[10][0] = 019019019019019; map_data[10][1] = 019019019019019; map_data[10][2] = 019019019019019
map_data[11][0] = 019019019019019; map_data[11][1] = 019019019019019; map_data[11][2] = 019019019019019
map_data[12][0] = 019019019019019; map_data[12][1] = 019019019019019; map_data[12][2] = 019019019019019
map_data[13][0] = 019019019019019; map_data[13][1] = 019019019019019; map_data[13][2] = 019019019019019
map_data[14][0] = 019019019019019; map_data[14][1] = 019019019019019; map_data[14][2] = 019019019019019
map_data[15][0] = 019019019019019; map_data[15][1] = 019019019019019; map_data[15][2] = 019019019019019
map_data[16][0] = 019019019019019; map_data[16][1] = 019019019019019; map_data[16][2] = 019019019019019
map_data[17][0] = 019019019019019; map_data[17][1] = 019019019019019; map_data[17][2] = 019019019019019
map_data[18][0] = 019019019019019; map_data[18][1] = 019019019019019; map_data[18][2] = 019019019019019

map_data[00][3] = 019019019019019; map_data[00][4] = 019019019019019; map_data[00][5] = 019019019019019
map_data[01][3] = 019019019019019; map_data[01][4] = 019019019019019; map_data[01][5] = 019019019019019
map_data[02][3] = 019019019019019; map_data[02][4] = 019019019019019; map_data[02][5] = 019019019019019
map_data[03][3] = 019019019019019; map_data[03][4] = 019019019019019; map_data[03][5] = 019019019019019
map_data[04][3] = 019019019019019; map_data[04][4] = 019019019019019; map_data[04][5] = 019019019019019
map_data[05][3] = 245019019019019; map_data[05][4] = 019019019019019; map_data[05][5] = 019019019019019
map_data[06][3] = 019019019019019; map_data[06][4] = 019019019019019; map_data[06][5] = 019019019019019
map_data[07][3] = 019019019019019; map_data[07][4] = 019019019019019; map_data[07][5] = 019019019240241
map_data[08][3] = 019019019019019; map_data[08][4] = 019019242243019; map_data[08][5] = 019019019019019
map_data[09][3] = 019019019019019; map_data[09][4] = 019019019019019; map_data[09][5] = 019019019019019
map_data[10][3] = 019019019019019; map_data[10][4] = 019019019019019; map_data[10][5] = 019019019019019
map_data[11][3] = 019019019019019; map_data[11][4] = 019019019019019; map_data[11][5] = 019019019019019
map_data[12][3] = 019019019019019; map_data[12][4] = 019019019019019; map_data[12][5] = 019019019019019
map_data[13][3] = 019019019019019; map_data[13][4] = 019019019019019; map_data[13][5] = 019019019019019
map_data[14][3] = 019019019019019; map_data[14][4] = 019019019019019; map_data[14][5] = 019019019019019
map_data[15][3] = 019019019019019; map_data[15][4] = 019019019019019; map_data[15][5] = 019019019019019
map_data[16][3] = 019019019019019; map_data[16][4] = 019019019019019; map_data[16][5] = 019019019019019
map_data[17][3] = 019019019019019; map_data[17][4] = 019019019019019; map_data[17][5] = 019019019019019
map_data[18][3] = 019019019019019; map_data[18][4] = 019019019019019; map_data[18][5] = 019019019019019

setCreateMap(img_map_name, img_no, pos_map_bg, set_z, map_size, map_data)
map_bg_edno = getVariable(img_map_name) + 1  #背景マップデータ終了位置番号

#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

set_z = 4

#マップデータを作成
#ここから↓は省略

  マップデータの準備前に、背景マップデータの準備を追加しています。
  背景マップデータはカメラのスクロールの対象外となる
 レイヤー番号「set_z」を2に設定しています。
  また、スクロールをカメラに頼らず行う必要があるため、
 背景マップデータの開始位置、終了位置番号を取得し、変数に準備しています。


  スクロール用の変数を準備します。
#ここから↑は省略

#ゴールの当たり判定範囲
goal_atari[i] = createArray()
goal_atari[i][x] = getVariable(pos_goal)[i][x] + goal_hit[x] - getVariable(pos_map)[x]
goal_atari[i][y] = getVariable(pos_goal)[i][y] + goal_hit[y] - getVariable(pos_map)[y]
goal_atari[i][w] = goal_atari[i][x] + goal_hit[w]
goal_atari[i][h] = goal_atari[i][y] + goal_hit[h]

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#背景スクロール
pos_map_sa = 0
pos_map_old = getVariable(pos_map)[x]
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#----- テキストボックスの設定 -----
#スコア表示の設定
#ここから↓は省略

  「pos_map_sa」はマップスクロールの移動量、
 「pos_map_old」は移動量の計算に使用します。



  背景マップデータをスクロールします。
#ここから↑は省略

        #----- 背景のスクロール -----
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
        #背景マップ
        pos_map_sa = pos_map_old - getVariable(pos_map)[x]
        if pos_map_sa != 0
            getVariable(pos_map_bg)[x] = getVariable(pos_map_bg)[x] + 
                                         (pos_map_sa * (char_speed * 0.01))
            i = map_bg_stno
            while i < map_bg_edno
                setSpritePosition(i, getVariable(pos_map_bg)[x], getVariable(pos_map_bg)[y])
                i = i + 1
            end
            pos_map_old = getVariable(pos_map)[x]
        end
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
        #マップ
        setSpriteCameraOffset(-(getVariable(pos_map)[x]), 0)
        
#ここから↓は省略

  まず、前回のマップ位置座標である「pos_map_old」と
 現在の「getVariable(pos_map)[x]」を比較し、
 差分である「pos_map_sa」を計算しています。

  この「pos_map_sa」の値が0以外に変わっていた場合、
 「pos_map_sa」を「char_speed」の0.01倍、背景マップデータを移動させ、
 スクロールしています。

  while文でループしているのは、マップのときとは異なり、
 マップチップの画像ごとに移動を設定する必要があるため、
 背景マップデータの作成時に準備しておいた
 「map_bg_stno」「map_bg_edno」を元に、
 マップチップ画像を1枚ずつ移動させています。



  ここまでで、背景を多重スクロールさせる仕組みができました。
 保存、終了をして、テストプレーを行い、
 背景がスクロールするかどうか確認してみましょう。





04-04 効果音を再生する




  アイテムの取得、ゲームオーバー、ゲームクリア時に
 効果音を再生してみましょう。

  今回もまた、お手軽にスクリプトの作成までできるよう、
 サンプルの素材を準備いたしました。
  なお、効果音素材はrerofumi様、TAM Music Factory 多夢(TAM)様の素材を
 許可を頂きまして、利用させていただいております。

効果音


zako_hit03


効果音


TAM_soft_001


効果音


TAM_soft_002


効果音


TAM_decide2


  こちらを参考に、クリップからリソースへの登録まで行い、
 すぐにスクリプトで利用できるように、準備してください。


  それではチャプター1に、定数を準備するところから。
#ここから↑は省略

#音楽・効果音の設定
bgm_main = 66498

bgm_vol = 0.7
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
se_clear = 89978
se_gameover = 89981
se_get = 89930
se_dmg = 63622

se_vol = 1
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#ここから↓は省略

 「se_clear」「se_gameover」「se_get」は効果音素材のID、
 「se_vol」は効果音の再生音量を設定しています。


  次に、再生の準備を行います。
#ここから↑は省略

#スコアの初期表示
score = 0
str = "スコア "
str = str + addZero(score, 5)
setText(text_score, str)

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#効果音の事前準備
se_id = playSound(se_clear);  setSoundVolume(se_id, 0)
se_id = playSound(se_gameover);  setSoundVolume(se_id, 0)
se_id = playSound(se_get);  setSoundVolume(se_id, 0)
se_id = playSound(se_dmg);  setSoundVolume(se_id, 0)
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#音楽の再生開始
playBGM(bgm_main);  setMusicVolume(bgm_vol)

  再生音量 0 で予め再生しておくことで
 プレイ中の再生がスムーズに行われるようにしています。


  それぞれの再生タイミングで、効果音の再生を行います。
#ここから↑は省略
                score = score + goal_point
                
                #ゲームクリア開始
                char_goal_count = 1
                char_act = act_std
                fadeOutMusicStop(100)  #音楽の停止
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
                se_id = playSound(se_clear)
                setSoundVolume(se_id, se_vol)
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#中略

                    getVariable(pos_item)[i][x] = (-100)
                    getVariable(pos_item)[i][y] = 700
                    setSpritePos(img_item_name, getVariable(pos_item), i)
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
                    se_id = playSound(se_get)
                    setSoundVolume(se_id, se_vol)
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#中略

                    #当たり判定のチェック
                    if ((char_atari[x3]) > (enemy_atari[i][x])) && 
                       ((char_atari[y2]) > (enemy_atari[i][y])) && 
                       ((char_atari[x1]) < (enemy_atari[i][w])) && 
                       ((char_atari[y1]) < (enemy_atari[i][h]))
                        #----- 上半身 -----
                        
                        #ゲームオーバー開始
                        char_act = act_dmg; char_dmg_count = 0
                        
                        fadeOutMusicStop(100)  #音楽の停止
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
                        se_id = playSound(se_gameover);  setSoundVolume(se_id, se_vol)
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
                    elsif ((char_atari[x3]) > (enemy_atari[i][x])) && 
                          ((char_atari[y3]) > (enemy_atari[i][y])) && 
                          ((char_atari[x1]) < (enemy_atari[i][w])) && 
                          ((char_atari[y2]) < (enemy_atari[i][h]))
                        #----- 下半身 -----
                        
                        if char_act != act_jmp
                            #ゲームオーバー開始
                            char_act = act_dmg; char_dmg_count = 0
                            
                            fadeOutMusicStop(100)  #音楽の停止
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
                            se_id = playSound(se_gameover);  setSoundVolume(se_id, se_vol)
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
                        else
                            #敵を倒す
                            score = score + enemy_point
                            
                            char_act = act_jmp; char_jmp_count = 5
                            
                            enemy_act[i] = act_dmg
                            enemy_dmg_count[i] = 0
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
                            se_id = playSound(se_dmg);  setSoundVolume(se_id, se_vol)
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
                        end
                    end
                end
                i = i + 1
            end
            
            #穴に落下
            if pos_char[y] > (gameover_pos_y - 25)
                #ダメージ状態開始
                char_act = act_dmg; char_dmg_count = 0
                
                fadeOutMusicStop(100)  #音楽の停止
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
                se_id = playSound(se_gameover);  setSoundVolume(se_id, se_vol)
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
            end

#ここから↓は省略




  スクリプト全体

  これで、一通り完成です。
 保存、終了をして、テストプレーを行い、
 効果音が再生されるか確認してみましょう。
  なお、メインループのフレーム数、ジャンプの落下速度、
 ゴールの当たり判定を調整しなおしています。


  ゲームを公開状態にするときは、
 こちらを参考に、オープニング、エンディング、ゲームオーバーの設定も
 忘れないようにしましょう。




04-05 おわりに


  いかがでしたでしょうか。
 前回のシリーズでお話しましたSTGの拡張として、
 今回のシリーズではACTゲームならではの仕組みや動きも
 追加してきました。

  どのようなジャンルのゲームでも
 どうやって動かしていくか、という工夫は必要になってきますが、
 定数や変数の使い方、画像の表示や移動といった
 基本的なところは、共通の流れです。

  今回までのシリーズをきっかけに、
 面白いアイデアの作品、新しいジャンルのゲームなどが
 Rmakeにて登場することを
 心より期待、応援しております。


  なお、今回のシリーズで完成したサンプルのゲームを
 公開しておりますので、実際にプレイしてみたい方は
 是非、遊んでみてください。
アクションサンプルゲーム - 【ノベルゲーム】



  第01回 関数を再利用してみよう
  第02回 マップを表示してみよう
  第03回 敵・アイテムを追加してみよう
  第04回 敵の動きや背景の演出を入れてみよう
  番外 外部ツールと連携してみよう

コメントする

コメントするには、ログインする必要があります。

コメント一覧

User icon mini 退会したユーザー(投稿日:2012/04/14 20:14, 履歴)
こんなもの見つけました~
            #--------------------
            #str = ""
            #
            #str = str + charHit_X1 + "," + charHit_Y1 + " : " + charHit_X2 + "," + charHit_Y1 + " : " + charHit_X3 + "," + charHit_Y1 + "\n"
            #str = str + charHit_X1 + "," + charHit_Y2 + " : " + charHit_X2 + "," + charHit_Y2 + " : " + charHit_X3 + "," + charHit_Y2 + "\n"
            #str = str + charHit_X1 + "," + charHit_Y3 + " : " + charHit_X2 + "," + charHit_Y3 + " : " + charHit_X3 + "," + charHit_Y3 + "\n"
            #str = str + charHit_X1 + "," + charHit_Y4 + " : " + charHit_X2 + "," + charHit_Y4 + " : " + charHit_X3 + "," + charHit_Y4 + "\n"
            #
            #str = str + charHitpos[0] + " : " + charHitpos[1] + " : " + charHitpos[2] + "\n"
            #str = str + charHitpos[3] + " : " + charHitpos[4] + " : " + charHitpos[5] + "\n"
            #str = str + charHitpos[6] + " : " + charHitpos[7] + " : " + charHitpos[8] + "\n"
            #str = str + charHitpos[9] + " : " + charHitpos[10] + " : " + charHitpos[11] + "\n"
            #
            #str = str + "D : " + HitFlgD + " / LD : " + HitFlgLD + " / RD : "+ HitFlgRD 
            #str = str + "\nU : " + HitFlgU + " / LU : " + HitFlgLU + " / RU : "+ HitFlgRU 
            #str = str + "\nM : " + HitFlgM + "\nLS : " + HitFlgLS
            #str = str + " / RS : " + HitFlgRS + "\n"
            #
            #str = str + "xSa : " + xSa + " / ySa : " + ySa + "\n"
            #
            #setText(text_score, str)
            #--------------------


これについて少し説明していただけないでしょうか?
Cdv30200 aoi icon mini aoihikawa(投稿日:2012/04/14 20:34, 履歴)
現在の状態を把握するための
テスト中用スクリプトです。

charHit_~はキャラクターの座標関連
charHitpos~はそれを元にした当たり判定座標関連
HitFlg~は実際の当たり判定の状態です。

最後のxSa、ySaはスクロール位置の座標です。
User icon mini 退会したユーザー(投稿日:2012/04/14 22:10, 履歴)
ありがとうございます。
Cdv30200 aoi icon mini aoihikawa(投稿日:2011/10/25 21:47, 履歴)
タクミ2310号さま>

スクリプト内、一部の箇所で
重くなるときがありますね。

スクリプトの量が多くなってきた場合、
テキストエディタソフトなどを利用して編集した後、
Rmake側にコピーするという方法があります。
User icon mini 退会したユーザー(投稿日:2011/10/25 21:09, 履歴)
コピペして、
いざいじってみようとしたらGoogle Chromeなのにフリーズしかけたorz

簸川さん一体どうやって動かしたんですか・・・?