Rmakeで自由なゲームをつくろう / 第06回 より面白くするために

投稿者:Cdv30200 aoi icon mini aoihikawa 投稿日:2011/08/11 15:41

Rmakeで自由なゲームをつくろう

 第06回 敵キャラクターを登場させる


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


 第05回 では弾を発射させるなど、
 シューティングゲームとして完成するまでのお話でした。
 第06回は、いよいよ最終回。
 より面白くするために、様々な工夫の方法を紹介していきます。



06-01 敵に弾を発射させる




  キャラクターが攻撃できるのに、
 敵キャラクターが攻撃できないのは不公平ですね。
 敵キャラクターにも弾を発射させてみましょう。

  基本的な仕組みは、キャラクターの弾を発射させたときと同じです。
 今回は、弾にアニメーションも付けてみましょう。


  今回もまた、恒例のサンプルの素材を準備いたしました。


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



  それでは、まずは関数の準備から。
#ここから↑は省略

#敵キャラクターの表示内容を変更する関数
def setEnemySpritePattern(no, i)
    img_enemy_name = "img_enemy"
    get_x = 0;    get_y = 0;    get_w = 64;   get_h = 64
    set_x = 0;    set_y = 0;    set_w = 64;   set_h = 64
    
    if no == 1
        get_x = 0;    get_y = 0
    elsif no == 2
        get_x = 64;   get_y = 0
    elsif no == 3
        get_x = 128;  get_y = 0
    elsif no == 4
        get_x = 192;  get_y = 0
    else
        get_w = 0;    get_h = 0
        set_w = 0;    set_h = 0
    end
    
    setSpriteRect(getVariable(img_enemy_name)[i],
                  get_x, get_y, get_w, get_h,
                  set_x, set_y, set_w, set_h)
end

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#敵キャラクター弾の表示内容を変更する関数
def setEnemyTamaSpritePattern(no, i)
    img_enemy_tama_name = "img_enemy_tama"
    get_x = 0;    get_y = 0;    get_w = 16;   get_h = 16
    set_x = 0;    set_y = 0;    set_w = 16;   set_h = 16
    
    if no == 1
        get_x = 0;    get_y = 0
    elsif no == 2
        get_x = 16;   get_y = 0
    elsif no == 3
        get_x = 32;  get_y = 0
    else
        get_w = 0;    get_h = 0
        set_w = 0;    set_h = 0
    end
    
    setSpriteRect(getVariable(img_enemy_tama_name)[i],
                  get_x, get_y, get_w, get_h,
                  set_x, set_y, set_w, set_h)
end
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
#ここから↓は省略



  続いて、定数の設定
#ここから↑は省略
#敵キャラクターの設定
max_enemy = 3
enemy_speed = 5
enemy_baratuki = 20
enemy_w_max = 800 - 64;     enemy_h_min = -64
enemy_anime_change = 2

enemy_hit = createArray()
enemy_hit[x] = 20;          enemy_hit[y] = 20
enemy_hit[w] = 24;          enemy_hit[h] = 35

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#敵キャラクター弾の設定
max_enemy_tama = 6
enemy_tama_speed = 15
enemy_tama_w_max = 800 - 16
enemy_tama_anime_change = 2

enemy_tama_hassya_pos = createArray()
enemy_tama_hassya_pos[0] = 50
enemy_tama_hassya_pos[1] = 190

enemy_tama_hit = createArray()
enemy_tama_hit[x] = 3;      enemy_tama_hit[y] = 3
enemy_tama_hit[w] = 10;     enemy_tama_hit[h] = 10
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#ここから↓は省略

  「enemy_tama_hassya_pos」は敵キャラクターがこの設定値よりも
 下に移動したとき、攻撃を行うボーダーラインの設定です。



  次に、画像の設定。
#ここから↑は省略

#敵キャラクターの画像の設定
img_no = 77127
img_enemy_name = "img_enemy"

get[x] = 0;    get[y] = 0;    get[w] = 64;  get[h] = 64
set[x] = 0;    set[y] = 0;    set[w] = 64;  set[h] = 64
set_z = 5
pos_enemy = createArray()
i = 0
while i < max_enemy
    pos_enemy[i] = createArray()
    pos_enemy[i][x] = 800;    pos_enemy[i][y] = 600
    i = i + 1
end
setCreateSprite(img_enemy_name, img_no, get, set,
                set_z, pos_enemy, max_enemy)

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#敵キャラクター弾の画像の設定
img_no = 77349
img_enemy_tama_name = "img_enemy_tama"

get[x] = 0;    get[y] = 0;    get[w] = 16;  get[h] = 16
set[x] = 0;    set[y] = 0;    set[w] = 16;  set[h] = 16
set_z = 4
pos_enemy_tama = createArray()
i = 0
while i < max_enemy_tama
    pos_enemy_tama[i] = createArray()
    pos_enemy_tama[i][x] = 800;    pos_enemy_tama[i][y] = 600
    i = i + 1
end
setCreateSprite(img_enemy_tama_name, img_no, get, set,
                set_z, pos_enemy_tama, max_enemy_tama)
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#ここから↓は省略



  大体、パターンも覚えてきましたでしょうか。
 次は、変数の設定です。
#ここから↑は省略
#敵キャラクター
enemy_anime_count = createArray()
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
enemy_tama_hassya_count = createArray()
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
i = 0
while i < max_enemy
    enemy_anime_count[i] = -1
    #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
    enemy_tama_hassya_count[i] = 0
    #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
    i = i + 1
end
enemy_syutugen_count = 0

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#敵キャラクター弾
enemy_tama_anime_count = createArray()
i = 0
while i < max_enemy_tama
    enemy_tama_anime_count[i] = -1
    i = i + 1
end
enemy_tama_syutugen_count = 0
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#キャラクターの非ダメージ
char_damage = false

#キャラクターの当たり判定範囲
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]

#キャラクター弾の発射間隔カウント
char_tama_interval_count = 0

#キャラクター弾の当たり判定範囲
char_tama_atari = createArray()

#敵キャラクターの当たり判定範囲
enemy_atari = createArray()
i = 0
while i < max_enemy
    enemy_atari[i] = createArray()
    i = i + 1
end

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#敵キャラクター弾の当たり判定範囲
enemy_tama_atari = createArray()
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#ここから↓は省略

  先ほど説明しました、ボーダーラインを超えた数のカウントに
 「enemy_tama_hassya_count」という変数を準備しています。



  それでは、メインループ内のスクリプトへ。
 まずは、敵キャラクター弾の発射から。
#ここから↑は省略

                #敵キャラクターの当たり判定範囲
                enemy_atari[i][x] = pos_enemy[i][x] + enemy_hit[x]
                enemy_atari[i][y] = pos_enemy[i][y] + enemy_hit[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[w]) > (enemy_atari[i][x])) && 
                   ((char_atari[h]) > (enemy_atari[i][y])) && 
                   ((char_atari[x]) < (enemy_atari[i][w])) && 
                   ((char_atari[y]) < (enemy_atari[i][h]))
                   
                   char_damage = true
                   mainloop = false
                end
                #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
                #弾の発射
                j = enemy_tama_hassya_count[i]
                jlen = getArrayLength(enemy_tama_hassya_pos)
                if j < jlen
                    if pos_enemy[i][y] > enemy_tama_hassya_pos[j]
                        enemy_tama_syutugen_count = enemy_tama_syutugen_count + 1  #出現カウント
                        k = 0
                        while k < max_enemy_tama
                            if enemy_tama_anime_count[k] < 0
                                pos_enemy_tama[k][x] = pos_enemy[i][x] + 13
                                pos_enemy_tama[k][y] = pos_enemy[i][y] + 50
                                enemy_tama_anime_count[k] = 0           #アニメーションをリセット
                                enemy_tama_hassya_count[i] = enemy_tama_hassya_count[i] + 1
                                
                                k = max_enemy_tama
                            end
                            k = k + 1
                        end
                    end
                end
                #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#ここから↓は省略

  「getArrayLength」関数は、配列の長さを調べます。
 発射した回数が、発射するボーダーラインの設定数に達しているかどうか
 比較してスクリプトを分岐させています。

  次のif文は敵キャラクターの位置と、ボーダーラインの比較ですね。
 while文は、画面外に待機している弾の画像、
 つまり「enemy_tama_anime_count」が「-1」になっている画像を探しています。
 見つかったところで、発射状態の設定を行い、このループを抜けています。

  発射時のX座標とY座標に微妙な数値を加算しているのは、
 敵キャラクターの所持している、光線銃の場所から
 発射しているように見せるための調整値です。



  最後に弾のアニメーション、移動、当たり判定。
 これは、敵キャラクターを追加したときと内容はほとんど一緒ですね。
 アニメーションが3枚のループになっている点に気をつけましょう。
#ここから↑は省略
                                k = max_enemy_tama
                            end
                            k = k + 1
                        end
                    end
                end
            end
        end
        
        i = i + 1
    end
    
    #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
    #----- 敵キャラクター弾のアニメーション -----
    i = 0
    while i < max_enemy_tama
        if enemy_tama_anime_count[i] > -1
            #アニメーション用カウンター
            enemy_tama_anime_count[i] = enemy_tama_anime_count[i] + 1
            if enemy_tama_anime_count[i] == (enemy_tama_anime_change * 3)
                enemy_tama_anime_count[i] = 0           #アニメーションをリセット
            end
            
            if enemy_tama_anime_count[i] < enemy_tama_anime_change
                setEnemyTamaSpritePattern(1, i)
            elsif  enemy_tama_anime_count[i] < (enemy_tama_anime_change * 2)
                setEnemyTamaSpritePattern(2, i)
            else
                setEnemyTamaSpritePattern(3, i)
            end
            
            #敵キャラクター弾の移動
            pos_enemy_tama[i][y] = pos_enemy_tama[i][y] + enemy_tama_speed
            if pos_enemy_tama[i][y] > 600
                #敵キャラクター弾を初期値に戻す
                enemy_tama_syutugen_count = enemy_tama_syutugen_count - 1  #出現カウント
                pos_enemy_tama[i][x] = 800
                pos_enemy_tama[i][y] = 600
                enemy_tama_anime_count[i] = -1
            end
            setSpritePos(img_enemy_tama_name, pos_enemy_tama, i)
            
            #敵キャラクター弾の当たり判定範囲
            enemy_tama_atari[x] = pos_enemy_tama[i][x] + enemy_tama_hit[x]
            enemy_tama_atari[y] = pos_enemy_tama[i][y] + enemy_tama_hit[y]
            enemy_tama_atari[w] = enemy_tama_atari[x] + enemy_tama_hit[w]
            enemy_tama_atari[h] = enemy_tama_atari[y] + enemy_tama_hit[h]
            
            #当たり判定のチェック
            if ((char_atari[w]) > (enemy_tama_atari[x])) && 
               ((char_atari[h]) > (enemy_tama_atari[y])) && 
               ((char_atari[x]) < (enemy_tama_atari[w])) && 
               ((char_atari[y]) < (enemy_tama_atari[h]))
               
               char_damage = true
               mainloop = false
            end
        end
        i = i + 1
    end
    #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
    
    #----- キャラクター弾のアニメーション -----
    i = 0
    while i < max_char_tama
#ここから↓は省略



  ここまでで、敵キャラクターが弾を発射してくるようになりました。
 完成したら、テストプレーを行ってみましょう。



06-02 敵にAIを搭載する




  敵キャラクターの動きがワンパターンでは、
 やっぱり物足りない感じがしてしまいます。
 今度は、簡単なAIを搭載して、
 動きを変化させてみることにしましょう。


  まずは定数の準備から。
#ここから↑は省略
#敵キャラクターの設定
max_enemy = 3
enemy_speed = 5
enemy_baratuki = 20
enemy_w_max = 800 - 64;     enemy_h_min = -64
enemy_anime_change = 2

enemy_hit = createArray()
enemy_hit[x] = 20;          enemy_hit[y] = 20
enemy_hit[w] = 24;          enemy_hit[h] = 35
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
enemy_ai_pattern = 3
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#ここから↓は省略

  「enemy_ai_pattern」には、AIの種類を設定しておきます。



  次は変数の準備。
 現在のAIの状態を保管しておく変数を準備しておきます。
#ここから↑は省略
#アニメーション用カウンター
#キャラクター
char_anime_count = 0

#キャラクター弾
char_tama_anime_count = createArray()
i = 0
while i < max_char_tama
    char_tama_anime_count[i] = -1
    i = i + 1
end
char_tama_syutugen_count = 0

#敵キャラクター
enemy_anime_count = createArray()
enemy_tama_hassya_count = createArray()
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
enemy_ai = createArray()
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
i = 0
while i < max_enemy
    enemy_anime_count[i] = -1
    enemy_tama_hassya_count[i] = 0
    #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
    enemy_ai[i] = 0
    #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
    i = i + 1
end
enemy_syutugen_count = 0

#ここから↓は省略



  メインスクリプト。
 敵キャラクターの登場時にAIをランダムで決定、
 移動のスクリプトを関数に渡して行ってもらい、
 結果を配列で受けとっています。
#ここから↑は省略
    #----- 敵キャラクターのアニメーション -----
    i = 0
    while i < max_enemy
        #敵キャラクターを出現させる
        if (enemy_syutugen_count < max_enemy) && (enemy_anime_count[i] < 0)
            if rand(enemy_baratuki) == 0
                #出現カウントが最大値より少なく、アニメーションがマイナス(初期値)の場合
                enemy_syutugen_count = enemy_syutugen_count + 1  #出現カウント
                
                pos_enemy[i][x] = rand(enemy_w_max)
                pos_enemy[i][y] = enemy_h_min
                enemy_anime_count[i] = 0                     #アニメーションをリセット
                enemy_tama_hassya_count[i] = 0
                #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
                enemy_ai[i] = rand(enemy_ai_pattern)
                #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
            end
        end
        
#中略
                
                #敵キャラクターの移動
                #_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/
                ret_data = retEnemyAI(pos_enemy[i], enemy_speed,
                                      enemy_ai[i], enemy_w_max)
                pos_enemy[i] = ret_data[0]
                enemy_ai[i]  = ret_data[1]
                #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
                if pos_enemy[i][y] > 600
                    #敵キャラクターを初期値に戻す
                    enemy_syutugen_count = enemy_syutugen_count - 1  #出現カウント
                    pos_enemy[i][x] = 800
                    pos_enemy[i][y] = 600
                    enemy_anime_count[i] = -1
                end
                setSpritePos(img_enemy_name, pos_enemy, i)

#ここから↓は省略




  最後に、AIによって移動を切り替えて実行する関数の作成。
 今回は直線移動、斜め移動の右方向、左方向の3種類を実装します。
#ここから↑は省略

#敵キャラクター弾の表示内容を変更する関数
def setEnemyTamaSpritePattern(no, i)
    img_enemy_name = "img_enemy_tama"
    get_x = 0;    get_y = 0;    get_w = 16;   get_h = 16
    set_x = 0;    set_y = 0;    set_w = 16;   set_h = 16
    
    if no == 1
        get_x = 0;    get_y = 0
    elsif no == 2
        get_x = 16;   get_y = 0
    elsif no == 3
        get_x = 32;  get_y = 0
    else
        get_w = 0;    get_h = 0
        set_w = 0;    set_h = 0
    end
    
    setSpriteRect(getVariable(img_enemy_name)[i],
                  get_x, get_y, get_w, get_h,
                  set_x, set_y, set_w, set_h)
end

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#敵キャラクターのAI実行関数
def retEnemyAI(pos_enemy, enemy_speed, enemy_ai, enemy_w_max)
    x = 0;    y = 1
    if enemy_ai == 0
        #直線移動
        pos_enemy[y] = pos_enemy[y] + floor(enemy_speed * 1.5)
    elsif enemy_ai == 1
        #右下へ移動
        pos_enemy[x] = pos_enemy[x] + (enemy_speed * 3)
        pos_enemy[y] = pos_enemy[y] + enemy_speed
        if pos_enemy[x] > enemy_w_max
            #右端に到達
            pos_enemy[x] = enemy_w_max
            enemy_ai = 2  #AIの切り替え
        end
    else
        #左下へ移動
        pos_enemy[x] = pos_enemy[x] - (enemy_speed * 3)
        pos_enemy[y] = pos_enemy[y] + enemy_speed
        if pos_enemy[x] < 0
            #左端に到達
            pos_enemy[x] = 0
            enemy_ai = 1  #AIの切り替え
        end
    end
    
    ret_data = createArray()
    ret_data[0] = pos_enemy
    ret_data[1] = enemy_ai
    return ret_data
end
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#----- 定数の設定 -----

#ここから↓は省略

  「floor」小数点以下を切り捨てる関数です。

  右下、左下へ移動するAIの場合、画面外へ消えていってしまわないよう、
 端に到達したときにAIを切り替えるスクリプトにしています。



  ここまでで、敵キャラクターにAIが搭載されました。
 完成したら、テストプレーを行ってみましょう。



06-03 ボスを登場させる




  同じ敵だけではなく、他の種類の敵も登場させてみましょう。
 最後の1体になったとき、ボスが出現するようにします。


  今回もまた、恒例のサンプルの素材を準備いたしました。








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



  それでは、関数の追加から。
#ここから↑は省略

#敵キャラクター弾の表示内容を変更する関数
def setEnemyTamaSpritePattern(no, i)
    img_enemy_tama_name = "img_enemy_tama"
    get_x = 0;    get_y = 0;    get_w = 16;   get_h = 16
    set_x = 0;    set_y = 0;    set_w = 16;   set_h = 16
    
    if no == 1
        get_x = 0;    get_y = 0
    elsif no == 2
        get_x = 16;   get_y = 0
    elsif no == 3
        get_x = 32;  get_y = 0
    else
        get_w = 0;    get_h = 0
        set_w = 0;    set_h = 0
    end
    
    setSpriteRect(getVariable(img_enemy_tama_name)[i],
                  get_x, get_y, get_w, get_h,
                  set_x, set_y, set_w, set_h)
end

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#ボスキャラクターの表示内容を変更する関数
def setBossSpritePattern(no)
    img_boss_name = "img_boss"
    get_x = 0;    get_y = 0;    get_w = 256;   get_h = 160
    set_x = 0;    set_y = 0;    set_w = 256;   set_h = 160
    
    if no == 1
        get_x = 0;    get_y = 0
    else
        get_w = 0;    get_h = 0
        set_w = 0;    set_h = 0
    end
    
    setSpriteRect(getVariable(img_boss_name),
                  get_x, get_y, get_w, get_h,
                  set_x, set_y, set_w, set_h)
end
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#敵キャラクターのAI実行関数
def retEnemyAI(pos_enemy, enemy_speed, enemy_ai, enemy_w_max)
    x = 0;    y = 1
    if enemy_ai == 0
        #直線移動
        pos_enemy[y] = pos_enemy[y] + floor(enemy_speed * 1.5)
    elsif enemy_ai == 1
        #右下へ移動
        pos_enemy[x] = pos_enemy[x] + (enemy_speed * 3)
        pos_enemy[y] = pos_enemy[y] + enemy_speed
        if pos_enemy[x] > enemy_w_max
            #右端に到達
            pos_enemy[x] = enemy_w_max
            enemy_ai = 2  #AIの切り替え
        end
    #_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/
    elsif enemy_ai == 2
    #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
        #左下へ移動
        pos_enemy[x] = pos_enemy[x] - (enemy_speed * 3)
        pos_enemy[y] = pos_enemy[y] + enemy_speed
        if pos_enemy[x] < 0
            #左端に到達
            pos_enemy[x] = 0
            enemy_ai = 1  #AIの切り替え
        end
    #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
    elsif enemy_ai == 30
        #直線移動
        pos_enemy[y] = pos_enemy[y] + enemy_speed
        if pos_enemy[y] > 20
            enemy_ai = (rand(2) + 31)
        end
    elsif enemy_ai == 31
        pos_enemy[x] = pos_enemy[x] + floor(enemy_speed * 1.5)
        if pos_enemy[x] > enemy_w_max
            #右端に到達
            pos_enemy[x] = enemy_w_max
            enemy_ai = 32  #AIの切り替え
        end
    else
        pos_enemy[x] = pos_enemy[x] - floor(enemy_speed * 1.5)
        if pos_enemy[x] < -96
            #左端に到達
            pos_enemy[x] = -96
            enemy_ai = 31  #AIの切り替え
        end
    end
    #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
    
    ret_data = createArray()
    ret_data[0] = pos_enemy
    ret_data[1] = enemy_ai
    return ret_data
end

#ここから↓は省略

  ボスの表示を切り替える関数の追加と、
 AIの関数にボスの動きで使用する30番台を追加しています。



  それでは、定数の準備。
#ここから↑は省略

#敵キャラクター弾の設定
max_enemy_tama = 6
enemy_tama_speed = 15
enemy_tama_w_max = 800 - 16
enemy_tama_anime_change = 2

enemy_tama_hassya_pos = createArray()
enemy_tama_hassya_pos[0] = 50
enemy_tama_hassya_pos[1] = 190

enemy_tama_hit = createArray()
enemy_tama_hit[x] = 3;      enemy_tama_hit[y] = 3
enemy_tama_hit[w] = 10;     enemy_tama_hit[h] = 10

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#ボスキャラクターの設定
boss_speed = 8
boss_max_life = 30
boss_w_max = 800 - 160

boss_hit = createArray()
boss_hit[x] = 60;           boss_hit[y] = 50
boss_hit[w] = 136;          boss_hit[h] = 90

#ボスキャラクター弾の設定
max_boss_tama = 6
boss_tama_interval = 9
boss_tama_speed = 20

boss_tama_hit = createArray()
boss_tama_hit[x] = 1;       boss_tama_hit[y] = 0
boss_tama_hit[w] = 14;      boss_tama_hit[h] = 64
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#残撃破数の設定
gekiha_max = 30

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

bgm_vol = 0.7

se_hit = 63622
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
se_hit2 = 78638
se_bomb = 78639
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

se_vol = 1

#ここから↓は省略

  「boss_max_life」はボスの最大ライフ、
 「boss_tama_interval」はボスの攻撃間隔を設定しています。
  また、新規に効果音を2つ追加しています。



  続いて画像の設定
#ここから↑は省略
#敵キャラクター弾の画像の設定
img_no = 77349
img_enemy_tama_name = "img_enemy_tama"

get[x] = 0;    get[y] = 0;    get[w] = 16;  get[h] = 16
set[x] = 0;    set[y] = 0;    set[w] = 16;  set[h] = 16
set_z = 4
pos_enemy_tama = createArray()
i = 0
while i < max_enemy_tama
    pos_enemy_tama[i] = createArray()
    pos_enemy_tama[i][x] = 800;    pos_enemy_tama[i][y] = 600
    i = i + 1
end
setCreateSprite(img_enemy_tama_name, img_no, get, set,
                set_z, pos_enemy_tama, max_enemy_tama)

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#ボスキャラクター画像の設定
img_no = 78549
img_boss_name = "img_boss"

get[x] = 0;    get[y] = 0;    get[w] = 256;  get[h] = 160
set[x] = 0;    set[y] = 0;    set[w] = 256;  set[h] = 160
set_z = 5
pos_boss = createArray()
pos_boss[x] = 800;            pos_boss[y] = 600

setCreateSprite(img_boss_name, img_no, get, set, set_z, pos_boss)


#ボスキャラクター弾の画像の設定
img_no = 77649
img_boss_tama_name = "img_boss_tama"

get[x] = 0;    get[y] = 0;    get[w] = 16;  get[h] = 64
set[x] = 0;    set[y] = 0;    set[w] = 16;  set[h] = 64
set_z = 4
pos_boss_tama = createArray()
i = 0
while i < max_boss_tama
    pos_boss_tama[i] = createArray()
    pos_boss_tama[i][x] = 800;    pos_enemy_tama[i][y] = 600
    i = i + 1
end
setCreateSprite(img_boss_tama_name, img_no, get, set,
                set_z, pos_boss_tama, max_boss_tama)
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#ここから↓は省略



  次は変数の設定
#ここから↑は省略

#敵キャラクター弾
enemy_tama_anime_count = createArray()
i = 0
while i < max_enemy_tama
    enemy_tama_anime_count[i] = -1
    i = i + 1
end
enemy_tama_syutugen_count = 0

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#ボスキャラクター
boss_anime_count = -1
boss_ai = 0
boss_life = boss_max_life

#ボスキャラクター弾
boss_tama_anime_count = createArray()
i = 0
while i < max_boss_tama
    boss_tama_anime_count[i] = -1
    i = i + 1
end
boss_tama_syutugen_count = 0
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#中略

#敵キャラクター弾の当たり判定範囲
enemy_tama_atari = createArray()

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#ボスキャラクターの当たり判定範囲
boss_atari = createArray()

#ボスキャラクター弾の発射間隔カウント
boss_tama_interval_count = 0

#ボスキャラクター弾の当たり判定範囲
boss_tama_atari = createArray()
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#残撃破数の設定
gekiha_count = gekiha_max
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
enemy_zan_syutugen_count = max_enemy
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#ここから↓は省略

  「enemy_zan_syutugen_count」は最後の1体でボスを登場させるため
 通常の敵キャラクターの出現調整に使用します。



  効果音の準備
#ここから↑は省略

#効果音の事前準備
se_id = playSound(se_hit);  setSoundVolume(se_id, 0)
#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
se_id = playSound(se_hit2);  setSoundVolume(se_id, 0)
se_id = playSound(se_bomb);  setSoundVolume(se_id, 0)
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#音楽の再生開始
playBGM(bgm_main);  setMusicVolume(bgm_vol)
#ここから↓は省略



  メインループ、ボスキャラクターと発射する弾のスクリプト
#ここから↑は省略
                #敵キャラクター弾の当たり判定範囲
                enemy_tama_atari[x] = pos_enemy_tama[i][x] + enemy_tama_hit[x]
                enemy_tama_atari[y] = pos_enemy_tama[i][y] + enemy_tama_hit[y]
                enemy_tama_atari[w] = enemy_tama_atari[x] + enemy_tama_hit[w]
                enemy_tama_atari[h] = enemy_tama_atari[y] + enemy_tama_hit[h]
                
                #当たり判定のチェック
                if ((char_atari[w]) > (enemy_tama_atari[x])) && 
                   ((char_atari[h]) > (enemy_tama_atari[y])) && 
                   ((char_atari[x]) < (enemy_tama_atari[w])) && 
                   ((char_atari[y]) < (enemy_tama_atari[h]))
                   
                   char_damage = true
                   mainloop = false
                end
            end
            i = i + 1
        end
    end
    
    #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
    #----- ボスキャラクターのアニメーション -----
    if boss_anime_count > 2
        boss_anime_count = boss_anime_count + 1
        
        if (boss_anime_count % 2) == 0
            setBossSpritePattern(1)
        else
            setBossSpritePattern(0)
        end
        
        if (boss_anime_count % 3) == 0
             #効果音
             se_id = playSound(se_bomb);  setSoundVolume(se_id, se_vol)
        end
        
        if boss_anime_count > 30
            gekiha_count = 0
            #残撃破が0になったらゲームクリア
            mainloop = false
        end
    elsif boss_anime_count > 0
        boss_anime_count = boss_anime_count - 1
        if (boss_anime_count % 2) == 0
            setBossSpritePattern(1)
        else
            setBossSpritePattern(0)
        end
        
        #ボスキャラクターの移動
        ret_data = retEnemyAI(pos_boss, boss_speed,
                              boss_ai, boss_w_max)
        pos_boss = ret_data[0]
        boss_ai  = ret_data[1]
        setSpritePos(img_boss_name, pos_boss)
    elsif boss_anime_count > -1
        #ボスキャラクターの移動
        ret_data = retEnemyAI(pos_boss, boss_speed,
                              boss_ai, boss_w_max)
        pos_boss = ret_data[0]
        boss_ai  = ret_data[1]
        setSpritePos(img_boss_name, pos_boss)
        
        #敵キャラクターの当たり判定範囲
        boss_atari[x] = pos_boss[x] + boss_hit[x]
        boss_atari[y] = pos_boss[y] + boss_hit[y]
        boss_atari[w] = boss_atari[x] + boss_hit[w]
        boss_atari[h] = boss_atari[y] + boss_hit[h]
        
        #当たり判定のチェック
        if ((char_atari[w]) > (boss_atari[x])) && 
           ((char_atari[h]) > (boss_atari[y])) && 
           ((char_atari[x]) < (boss_atari[w])) && 
           ((char_atari[y]) < (boss_atari[h]))
           
           char_damage = true
           mainloop = false
        end
        
        boss_tama_interval_count = boss_tama_interval_count + 1
        if (boss_tama_interval_count > boss_tama_interval) && 
           (boss_tama_syutugen_count < max_boss_tama)
            boss_tama_interval_count = 0
            boss_tama_syutugen_count = boss_tama_syutugen_count + 2
            
            #弾の発射
            i = 0
            tama_count = 0
            while i < max_boss_tama
                if boss_tama_anime_count[i] < 0
                    pos_boss_tama[i][x] = pos_boss[x] + 95 + (tama_count * 50)
                    pos_boss_tama[i][y] = pos_boss[y] + 90
                    boss_tama_anime_count[i] = 0
                    
                    tama_count = tama_count + 1
                    if tama_count > 1
                        i = max_char_tama
                    end
                end
                i = i + 1
            end
        end
    end
    
    #----- ボスキャラクター弾のアニメーション -----
    if boss_tama_syutugen_count > 0
        i = 0
        while i < max_boss_tama
            if boss_tama_anime_count[i] > -1
                #キャラクター弾の移動
                pos_boss_tama[i][y] = pos_boss_tama[i][y] + boss_tama_speed
                if pos_boss_tama[i][y] > 600
                    #弾を初期値に戻す
                    boss_tama_syutugen_count = boss_tama_syutugen_count - 1  #出現カウント
                    pos_boss_tama[i][x] = 800
                    pos_boss_tama[i][y] = 600
                    boss_tama_anime_count[i] = -1
                end
                setSpritePos(img_boss_tama_name, pos_boss_tama, i)
                
                #キャラクター弾の当たり判定範囲
                boss_tama_atari[x] = pos_boss_tama[i][x] + boss_tama_hit[x]
                boss_tama_atari[y] = pos_boss_tama[i][y] + boss_tama_hit[y]
                boss_tama_atari[w] = boss_tama_atari[x] + boss_tama_hit[w]
                boss_tama_atari[h] = boss_tama_atari[y] + boss_tama_hit[h]
                
                #当たり判定のチェック
                if ((char_atari[w]) > (boss_tama_atari[x])) && 
                   ((char_atari[h]) > (boss_tama_atari[y])) && 
                   ((char_atari[x]) < (boss_tama_atari[w])) && 
                   ((char_atari[y]) < (boss_tama_atari[h]))
                   
                   char_damage = true
                   mainloop = false
                end
            end
            
            i = i + 1
        end
    end
    #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#ここから↓は省略

  ボスキャラクターの動きは「boss_anime_count」の状態が
 「-1」で出現前、「0」で出現中、「1~2」ダメージ中、「3以降」が撃破後
 の動きになっています。
  「3以降」は「30」になるまでカウントし、点滅表示や爆発音の再生を行っています。
 「30」になったとき、メインループを抜けて、エンディング画面に移動します。



  次に、敵キャラクターの出現制限と、ボスキャラクターの登場。
 敵キャラクターを撃破したときのスクリプトに少し追加します。
#ここから↑は省略
                       #弾を初期値に戻す
                       char_tama_syutugen_count = char_tama_syutugen_count - 1  #出現カウント
                       pos_char_tama[i][x] = -64
                       pos_char_tama[i][y] = 600
                       char_tama_anime_count[i] = -1
                       setSpritePos(img_char_tama_name, pos_char_tama, i)
                       
                       #撃破カウント
                       gekiha_count = gekiha_count - 1
                       #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
                       if gekiha_count == 4
                           enemy_zan_syutugen_count = 2
                       elsif gekiha_count == 2
                           enemy_zan_syutugen_count = 1
                       elsif gekiha_count == 1
                           enemy_zan_syutugen_count = 0
                           
                           #ボスキャラクターの登場
                           if boss_anime_count == -1
                               pos_boss[x] = ((800 - 256) / 2)
                               pos_boss[y] = -160
                               boss_ai = 30
                               boss_life = boss_max_life
                               boss_anime_count = 0
                           end
                       #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
                       #_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/
                       elsif gekiha_count == 0
                           #残撃破が0になったらゲームクリア
                           #mainloop = false
                           #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
                       end
#ここから↓は省略

  「gekiha_count」の値によって
 「enemy_zan_syutugen_count」を変更しています。
  「gekiha_count」が残り1となったとき、
 「enemy_zan_syutugen_count」を「0」にして
 通常の敵キャラクターの登場をストップさせ、
 同時にボスキャラクターを登場させています。

  ボスを倒したとき、エンディングに移動するようになったため、
 これまでのスクリプトをコメントにすることで無効化しています。



  「enemy_zan_syutugen_count」によって
 通常の敵キャラクターが登場する数を調整します。
  スクリプトの位置は、若干上に戻ります。
#ここから↑は省略

#----- 敵キャラクターのアニメーション -----
    i = 0
    while i < max_enemy
        #敵キャラクターを出現させる
        #_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/
        if (enemy_syutugen_count < enemy_zan_syutugen_count) &&
           (enemy_anime_count[i] < 0)
        #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
            if rand(enemy_baratuki) == 0
                #出現カウントが最大値より少なく、アニメーションがマイナス(初期値)の場合
                enemy_syutugen_count = enemy_syutugen_count + 1  #出現カウント


#ここから↓は省略



  最後に、ボスキャラクターとキャラクター弾との
 当たり判定を行います。
#ここから↑は省略
                       #効果音
                       se_id = playSound(se_hit);  setSoundVolume(se_id, se_vol)
                       
                       j = max_enemy
                    end
                end
                j = j + 1
            end
            
            #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
            if boss_anime_count == 0
                #当たり判定のチェック
                if ((char_tama_atari[w]) > (boss_atari[x])) && 
                   ((char_tama_atari[h]) > (boss_atari[y])) && 
                   ((char_tama_atari[x]) < (boss_atari[w])) && 
                   ((char_tama_atari[y]) < (boss_atari[h]))
                    
                    #弾を初期値に戻す
                    char_tama_syutugen_count = char_tama_syutugen_count - 1  #出現カウント
                    pos_char_tama[i][x] = -64
                    pos_char_tama[i][y] = 600
                    char_tama_anime_count[i] = -1
                    setSpritePos(img_char_tama_name, pos_char_tama, i)
                    
                    #ボスの残りHPを減算
                    if boss_life > 0
                        boss_life = boss_life - 1
                        
                        boss_anime_count = 2
                        
                        #効果音
                        se_id = playSound(se_hit2);  setSoundVolume(se_id, se_vol)
                    else
                        boss_anime_count = 3
                    end
                end
            end
            #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
        end
        
        i = i + 1
    end
    
    #----- 残撃破数の表示 -----
#ここから↓は省略

  ボスキャラクターは敵キャラクターと異なり、
 キャラクター弾に当たったとき、「boss_life」が減少するスクリプトに
 変更しています。
  「boss_life」が「0」になっている時の場合、
 「boss_anime_count」を「3」、つまりボスキャラクターが「撃破後」の
 状態に変更しています。



  ここまでで、ボスキャラクターが登場するようになりました。
 完成したら、テストプレーを行ってみましょう。



06-04 フレームスキップを実装する


  さまざまな要素を追加していくと、少しずつスクリプトの動きが
 重くなってきます。
  特に、複雑な動きや、表示する内容の数を追加すると
 局所的に重くなることもあります。

  前者はスクリプトの改善を行うことで、軽くしていきますが、
 表示する内容については減らしたくない場合もあります。


  これを解決する方法として、「フレームスキップ」という手段があります。
 「フレーム」とは、1秒あたりに何回描画を実行するかのことで、
 重くなってきたときにこの描画をスキップ、飛ばしてしまうわけです。




  フレームスキップも何を基準とするかによって、様々な方法がありますが、
 今回は 『スクリプト コツ』 フレームスキップスクリプト で紹介しております
 時間を基準に実装する方法で行います。
  なお、変更箇所のみ記載いたしますので、
 詳細の解説は、フレームスキップスクリプトのブログ記事を、参照して頂けると幸いです。


  まずは定数の設定から。
 同時に、フレームスキップが発生するか確認しやすくするために、
 フレームスキップの規定値を低めに設定し、敵キャラクターの数を増加させています。
#ここから↑は省略

#----- 定数の設定 -----
x = 0;    y = 1;    w = 2;    h = 3

#_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/
#FPS管理の設定
draw_setting = 35 #ゲームのメイン処理実行タイミングを設定(ミリ秒)
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#キャラクターの設定

#中略

#敵キャラクターの設定
#_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/
max_enemy = 6
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
enemy_speed = 5
enemy_baratuki = 20
enemy_w_max = 800 - 64;     enemy_h_min = -64
enemy_anime_change = 2

enemy_hit = createArray()
enemy_hit[x] = 20;          enemy_hit[y] = 20
enemy_hit[w] = 24;          enemy_hit[h] = 35

enemy_ai_pattern = 3

#敵キャラクター弾の設定
#_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/
max_enemy_tama = 12
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
enemy_tama_speed = 15
enemy_tama_w_max = 800 - 16
enemy_tama_anime_change = 2

#中略

#残撃破数の設定
#_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/
gekiha_max = 50
#_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/

#ここから↓は省略



  フレームスキップを実行するための事前スクリプトを追加します。
#ここから↑は省略
#画面の更新
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
        #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
        
        #キー入力の判定
#ここから↓は省略



  最後に、フレームスキップを実行するスクリプトを追加します。
#ここから↑は省略
        #----- 残撃破数の表示 -----
        str = "残り撃墜数 "
        if gekiha_count < 10
             str = str + "0"
        end
        str = str + gekiha_count
        setText(text_zan, str)
        
        #_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/
        #----- 画面の更新 -----
        if draw_flg
            drawCanvas() #描画OKならキャンバスを更新 
        end
    else
        waitTime(1) #ゲームのメイン処理実行タイミングになるまで保留 
    end
    #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
end
#ここから↓は省略



  ここまでで、フレームスキップの機能が実装されました。
 完成したら、敵の数が増えたときに描画がスキップされるか
 テストプレーを行ってみましょう。



  スクリプト全体(一部、少し整理とフレームスキップの値を調整しています)

  これで、一通り完成です。
 保存、終了をして、テストプレーを行い、
 確認してみましょう。




06-05 オープニングやエンディングを設定する




  ゲームの内容は一通り完成しましたが、
 ゲームを遊んでもらうためには、外見、つまり「タイトル画面」は
 重要な要素のひとつです。

  完成したゲームは公開をする前に、
 タイトル画面、エンディング画面、バッドエンディング画面を
 設定しておきましょう。


  今回もまた、恒例のサンプルの素材を準備いたしました。
 音楽素材は、助教授さまと、rerofumiさまの音楽素材を利用いたします。












  クリップをしたら、ゲームエディタ画面で「OP:ED:全滅」を押します。


  オープニング画面の項目の、「クリップした画像を設定する」を押し、
 設定する画像の「設定(追加)する」を押します。


  同様に、エンディング画面、ゲームオーバー画面も設定しましょう。



  画像を設定したら、次は画面の下のほうにある
 オープニング音楽、エンディング音楽、ゲームオーバー音楽を
 設定しましょう。
  操作は画像のときと同じです。



  これで、設定が完了しました。
 テストプレーを行い、確認してみましょう。



  テストプレーでしっかりと確認ができたら
 ゲームを公開しましょう。


  まず、メインエディタに戻ります。


  公開したいゲームの右側にある「公開します」を押します。


  「上記を確認したので、ゲームを公開します」を押します。




  これで、ゲームの公開が完了しました。



06-06 おわりに


  いかがでしたでしょうか。
 今回のシリーズではシューティングゲームの
 基本的なところをつくりましたが、
 敵の種類を増やしてみたり、
 キャラクターを強化するアイテムを登場させてみたり
 まだまだアレンジをしてみることができます。

  また、他のジャンルのゲームも、基本的なポイントは同じであり、
 キャラクターなどの動きや当たり判定の方法を変更していけば、
 つくってみることもできるでしょう。


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



  第01回 スクリプトって何?
  第02回 画面にキャラクターを描画する
  第03回 キャラクターをキー入力で操作する
  第04回 敵キャラクターを登場させる
  第05回 弾を発射させる
  第06回 より面白くするために

コメントする

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

コメント一覧

Rmakeic1 mini muga(投稿日:2017/04/04 03:06, 履歴)
こんばんは~!
敵に弾を発射させる
のところなんですが
enemy_tama_hassya_count[i] = 0
を敵が倒された時と画面から出た時に入れないと
弾を撃ってこなくなると思うのですがどうでしょうか
実際にやってみて僕はこれで改善しました
Cdv30200 aoi icon mini aoihikawa(投稿日:2017/04/04 20:58, 履歴)
敵の弾の発射カウントは
新しく出現させたとき(731行目)で
リセットされるように組み込まれています
      mini きゅうり(投稿日:2012/05/05 19:54, 履歴)
敵がある程度弾を撃つと、弾を撃ってこなくなってしまいます...
どうすれば解決するでしょう・・・?
Cdv30200 aoi icon mini aoihikawa(投稿日:2012/05/05 20:31, 履歴)
まずは、必要となる弾の最大スプライト数を
把握する必要があります。

それにあわせて、弾に関連する設定箇所を
変更しましょう。

各最大値を設定している変数は
通常の敵は「max_enemy_tama」
ボスは「max_boss_tama」です
      mini きゅうり(投稿日:2012/05/05 21:41, 履歴)
1度に表示する最大敵の数4体、発射する弾のボーダーラインは2本で、
(1度に表示する最大)弾の数は8個にしているのですが、
8個発射すると敵が攻撃を止めてしまいます((1度に表示する(ry )弾の数を変更しても同じ)...
他に変える所があるのでしょうか?
Cdv30200 aoi icon mini aoihikawa(投稿日:2012/05/05 23:30, 履歴)
そのままのコピーであれば
他に変更点はないはずですが、、、

画面から弾が消えた後、
表示中の弾の数である
enemy_tama_syutugen_countの値は
正常にセットされておりますでしょうか?
      mini きゅうり(投稿日:2012/05/07 19:51, 履歴)
はい。正常にセットされています。
ですが、別のenemy_tama_hassya_countの値が正常にセットされていなかったことが分かりまして、
無事解決できました!
ありがとうございました!
Cdv30200 aoi icon mini aoihikawa(投稿日:2012/05/08 11:00, 履歴)
解決できて何よりです。

原因発見お疲れ様でした。
User icon mini 退会したユーザー(投稿日:2012/04/24 20:53, 履歴)
敵を2種類用意することは出来ますか?
また、2種類用意できるのであれば片方だけに弾を打たせることは出来ますか?
Cdv30200 aoi icon mini aoihikawa(投稿日:2012/04/24 21:08, 履歴)
敵に関連したスクリプト箇所を複数にすることで
敵の種類や動作パターンを追加することができます。
User icon mini 退会したユーザー(投稿日:2012/04/24 21:21, 履歴)
ふむ。じゃあ片方だけ弾を打たせることは出来るのか。
つまり弾を打たせるスクリプトは1つでいいのかな?
User icon mini 退会したユーザー(投稿日:2012/04/24 21:37, 履歴)
でもどうすればいいでしょうか?
敵キャラを増やすのはいけそうですが、
弾を発射してくる敵とかをセットできるんでしょうか。。。
Cdv30200 aoi icon mini aoihikawa(投稿日:2012/04/24 21:37, 履歴)
その通りです。

それ以外のスクリプトについては
変数名を変更した状態の
一式のスクリプトが必要になります。
User icon mini 退会したユーザー(投稿日:2012/04/24 21:42, 履歴)
>弾を打たせるスクリプトは1つ
片方だけにするなら、それで大丈夫かと。


それにしても、
プラプリみたいに敵や弾(敵弾だけど)に結構な種類があると、
あの速度でいったいどうなっているのかが気になる(w
User icon mini 退会したユーザー(投稿日:2012/04/24 21:50, 履歴)
うわぁきついなぁ・・・
でもがんばろ!(スクリプト全書き直し居間で5回目)
User icon mini 退会したユーザー(投稿日:2012/04/24 21:56, 履歴)
あぁー無理だー
エラー直したらまたエラー出てきた・・・
しかも動きとまった。
あきらめよう。うん。今の私には無理なんだ。うん。
Cdv30200 aoi icon mini aoihikawa(投稿日:2011/09/01 18:13, 履歴)
>foodmakesさま

・味方の弾を発射する方向
・敵の登場する初期値
・敵の移動方向
・敵の弾を発射する方向

まずは、この辺りの改造から、ですね。
User icon mini 退会したユーザー(投稿日:2011/09/01 13:42, 履歴)
次は横シューが作りたくなってきたおw
User icon mini 退会したユーザー(投稿日:2011/08/13 10:53, 履歴)
ワラワラ(笑うな)
Cdv30200 aoi icon mini aoihikawa(投稿日:2011/08/12 19:08, 履歴)
>foodmakesさま

エラーが発生したとき、
エラーの行番号が表示されますので、
その行番号の前後の行を確認することで
エラーの場所が発見しやすくなります。

その関数の周辺でしたら、
ボス用のAIの追加のあたりで
if文の変更も入っておりますので
if~elsif~else~endの流れが
ちゃんと完結しているかどうか
確認してみてください。
User icon mini 退会したユーザー(投稿日:2011/08/12 18:28, 履歴)
やっぱ私にシューティングなど無理なのか・・・。(ほぼ完コピ以外)
User icon mini 退会したユーザー(投稿日:2011/08/12 17:47, 履歴)
ボスの関数入れたら急にエラーでて真っ暗なった・・・。
User icon mini 退会したユーザー(投稿日:2011/08/12 17:32, 履歴)
あ、タマをなかなか発射してくれなかったのもこれがなかったからなのか
Cdv30200 aoi icon mini aoihikawa(投稿日:2011/08/12 14:19, 履歴)
>foodmakesさま

「retEnemyAI」関数を定義していない状態ではないでしょうか。
その次のスクリプトにあります、
「retEnemyAI」関数の追加をスクリプトに追加後、
再度テストしてみてください。
User icon mini 退会したユーザー(投稿日:2011/08/12 12:44, 履歴)
ret_data = retEnemyAI(pos_enemy[i], enemy_speed,
enemy_ai[i], enemy_w_max)
pos_enemy[i] = ret_data[0]
enemy_ai[i] = ret_data[1]
をスクリプトに入れたとたん大量にエラーが出て敵が1箇所に密集するようになってしまったんですが・・・。
あ、何もいじってません。入れる場所も間違いはありません
Icon mini ronto(投稿日:2011/08/12 11:48, 履歴)
どういうエラー?
User icon mini 退会したユーザー(投稿日:2011/08/12 11:43, 履歴)
なんかどうしても追加した部分でエラーがでる・・。
コピペ部分はちゃんとあっているのにエラッタがでてしまう・・・。
Icon mini ronto(投稿日:2011/08/11 20:21, 履歴)
さて、シューティング用の素材作りに励むか。
Cdv30200 aoi icon mini aoihikawa(投稿日:2011/08/11 18:09, 履歴)
>ikosamiさま

ゲーム、プレイしてみました。

動きが速くなったのは
フレームスキップと同じ理由で、
「timer」によって描画する回数を
減らしたため、ですね。

なお、ご投稿いただきましたスクリプトは
常時、描画回数を減らしているところが、
ブログで紹介いたしました
フレームスキップのスクリプトと
異なっています。
Icon mini ikosami(投稿日:2011/08/11 17:49, 履歴)
あと、いこさみアドベンチャーでフレームスキップを
ちょっと自己流にアレンジして取り入れてみたら
動きは速くなったような気がするのですが
気のせいでしょうか?(これでは変わらないでしょうか?)
setBaseTime()
startInput()
loop = true
timer = getTime()

while loop
#-----中略-------
if getTime() > timer + 50
drawCanvas()
timer = getTime()
end
#-----中略-------
end
Cdv30200 aoi icon mini aoihikawa(投稿日:2011/08/11 17:38, 履歴)
>ikosamiさま

自分と敵との、強さのバランスによる面白さは
個人差がありますが、
多数の種類やパターンがあるという面白さは
より広い範囲で有効かなと。

RPGで例えるなら、
前者はボスを倒すために必要となるLv、
後者は幅広い特徴の装備品コレクション、
といった感じでしょうか。

ありがとうございます。
現在、公開しているゲームや素材の
イラスト、背景、キャラクター、小物絵などは
全て自作です。
Icon mini ikosami(投稿日:2011/08/11 17:03, 履歴)
やっぱり、敵を強くしたほうが面白みがありますよね。
というよりも、ボスの絵はaoihikawaさんが描いたんですか?
めちゃくちゃうまいですね(^^;)