スクリプト/RmakeでACTゲームをつくろう / 第03回 敵・アイテムを追加してみよう(履歴ID:132)
最終投稿者: aoihikawa
更新:2012/03/22 18:42:30
RmakeでACTゲームをつくろう
第03回 敵・アイテムを追加してみよう
こんにちは。
フリーデザイナープログラマー(自称)の
簸川 葵(ひかわ あおい)と申します。
第02回 では「マップを表示してみよう」ということで、
ACTゲームの基盤である、マップの表示についてお話しました。
今回はこのマップ上に、敵・アイテムを追加してみましょう。
03-01 敵・アイテムを準備する
基本的な配置までの流れは、画像の準備、マップ上への配置と
マップチップの場合と同じです。
しかし、敵やアイテムはマップチップと違い、
素材ごとにサイズや当たり判定が異なります。
そのため、マップチップのようにひとつの関数の中で行うのではなく、
準備と配置を分けて実装していきます。
今回もまた、お手軽にスクリプトの作成までできるよう、
サンプルの素材を準備いたしました。
こちらを参考に、クリップからリソースへの登録まで行い、
すぐにスクリプトで利用できるように、準備してください。
それではチャプター1に、定数を準備するところから。
#ここから↑は省略 #背景の設定 bg_center = 352 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #敵キャラクターの設定 max_enemy = 3 enemy_anime_change = 2 #アイテムの設定 max_item = 2 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #音楽・効果音の設定 bgm_main = 66498 #ここから↓は省略
「max_enemy」は敵キャラクターの最大数
「enemy_anime_change」はアニメーションの切り替えタイミング
「max_item」はアイテムの最大数を設定しています。
次に、画像を設定します。
#ここから↑は省略 #マップデータの設定 setCreateMap(img_map_name, img_no, pos_map, set_z, map_size, map_data) map_count = getArrayLength(map_data[0]) * map_size map_max_w = map_count * 32 map_w = map_max_w - 800 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ set_z = 5 #敵キャラクターの画像の設定 img_no = 87840 img_enemy_name = "img_enemy"; pos_enemy = "pos_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 setVariable(pos_enemy, createArray()) i = 0 while i < max_enemy getVariable(pos_enemy)[i] = createArray() getVariable(pos_enemy)[i][x] = 800; getVariable(pos_enemy)[i][y] = 600 i = i + 1 end setCreateSprite(img_enemy_name, img_no, get, set, set_z, getVariable(pos_enemy), max_enemy) #アイテムの画像の設定 img_no = 87847 img_item_name = "img_item"; pos_item = "pos_item" get[x] = 0; get[y] = 0; get[w] = 96; get[h] = 96 set[x] = 0; set[y] = 0; set[w] = 96; set[h] = 96 setVariable(pos_item, createArray()) i = 0 while i < max_item getVariable(pos_item)[i] = createArray() getVariable(pos_item)[i][x] = 800; getVariable(pos_item)[i][y] = 600 i = i + 1 end setCreateSprite(img_item_name, img_no, get, set, set_z, getVariable(pos_item), max_item) #ゴール画像の設定 img_no = 87854 img_goal_name = "img_goal"; pos_goal = "pos_goal" get[x] = 0; get[y] = 0; get[w] = 96; get[h] = 96 set[x] = 0; set[y] = 0; set[w] = 96; set[h] = 96 setVariable(pos_goal, createArray()) i = 0 getVariable(pos_goal)[i] = createArray() getVariable(pos_goal)[i][x] = 800; getVariable(pos_goal)[i][y] = 600 setCreateSprite(img_goal_name, img_no, get, set, set_z, getVariable(pos_goal), 1) #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
敵キャラクター、アイテムの数だけ、
「setCreateSprite」関数を利用して画像を準備しています。
ゴールはひとつしかありませんが、
敵キャラクター、アイテムのスクリプトを応用して利用しているため、
最大数1の配列データとして設定しています。
変数を設定します。
#ここから↑は省略 #キャラクターの当たり判定範囲 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] #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #敵キャラクター enemy_anime_count = createArray() enemy_muki = createArray() enemy_act = createArray() i = 0 while i < max_enemy enemy_anime_count[i] = 0 enemy_muki[i] = 0 enemy_act[i] = act_wrk i = i + 1 end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #音楽の再生開始 #ここから↓は省略
敵キャラクターのみ、動作が入るため
キャラクターのスクリプトと同様の変数を準備しています。
ここまでで、表示の準備ができました。
03-02 敵・アイテムをマップに配置する
第2回のマップの設定で利用した、関数とスクリプトを応用して、
敵・アイテムをマップに配置していきます。
まずは、チャプター0にて、関数の準備から。
#ここから↑は省略 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #敵キャラクターの表示内容を変更する関数 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 elsif no == 5 get_x = 0; get_y = 64 elsif no == 6 get_x = 64; get_y = 64 elsif no == 7 get_x = 128; get_y = 64 elsif no == 8 get_x = 192; get_y = 64 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 setCreateItem(max_enemy, max_item, max_goal, map_w, map_dat) x = 0; y = 1; w = 2; h = 3 enemy_count = 0; item_count = 0; goal_count = 0 pos_enemy = "pos_enemy"; pos_item = "pos_item"; pos_goal = "pos_goal" set_map = createArray(); get = createArray(); set = createArray() i = 0; ilen = getArrayLength(map_dat) while i < ilen j = 0; jlen = getArrayLength(map_dat[i]) while j < jlen map_d = map_dat[i][j] k = 0; klen = map_w while k < klen if map_d != 0 #画像の切り出しポイントを算出 if k < (klen - 1) chk = (map_d / POWER(1000, (map_w - (k + 1)))) else chk = map_d end #画像の座標を算出 if chk == 0 set_map[x] = 0; set_map[y] = 0 else chk = chk % 1000 set_map[x] = floor(chk % 20); set_map[y] = floor(chk / 20) if set_map[y] > 24 set_map[y] = set_map[y] - 25 end end #画像を座標にセットする chk = floor(chk) if (chk != 0) if (chk == 1) && (enemy_count < max_enemy) #敵 set[x] = (32 * k) + (32 * j * map_w); set[y] = 32 * i getVariable(pos_enemy)[enemy_count][x] = set[x] getVariable(pos_enemy)[enemy_count][y] = set[y] setSpritePos("img_enemy", getVariable(pos_enemy), enemy_count) enemy_count = enemy_count + 1 elsif (chk == 2) && (item_count < max_item) #アイテム set[x] = (32 * k) + (32 * j * map_w) - 16; set[y] = 32 * i getVariable(pos_item)[item_count][x] = set[x] getVariable(pos_item)[item_count][y] = set[y] setSpritePos("img_item", getVariable(pos_item), item_count) item_count = item_count + 1 elsif (chk == 3) && (goal_count < max_goal) #ゴール set[x] = (32 * k) + (32 * j * map_w) - 16; set[y] = 32 * i - 4 getVariable(pos_goal)[goal_count][x] = set[x] getVariable(pos_goal)[goal_count][y] = set[y] setSpritePos("img_goal", getVariable(pos_goal), goal_count) goal_count = goal_count + 1 end end end k = k + 1 end j = j + 1 end i = i + 1 end end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #当たり判定の座標を算出 #ここから↓は省略
「setEnemySpritePattern」関数は敵キャラクターの表示を変更します。
キャラクターの表示の変更に使用していた「setCharSpritePattern」関数をベースに、
複数の敵キャラクターに対応できるよう、配列を利用した仕組みに変更されています。
「setCreateItem」関数は配置データ変数を元に、
敵、アイテム、ゴールの座標を取得し、画面上に配置する関数です。
マップの設定に使用していた「setCreateMap」関数をベースに、
表示位置の設定のみ行うよう変更されています。
また、アイテムとゴールの設定座標を若干左寄りに微調整しています。
チャプター1にて、「setCreateItem」関数に送る配置データ変数を準備します。
配列データの仕組みはマップ表示のときと同様です。
#ここから↑は省略 setCreateSprite(img_goal_name, img_no, get, set, set_z, getVariable(pos_goal), 1) #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #敵・アイテム設定データ item_data = createArray() item_data[00] = createArray() item_data[01] = createArray() item_data[02] = createArray() item_data[03] = createArray() item_data[04] = createArray() item_data[05] = createArray() item_data[06] = createArray() item_data[07] = createArray() item_data[08] = createArray() item_data[09] = createArray() item_data[10] = createArray() item_data[11] = createArray() item_data[12] = createArray() item_data[13] = createArray() item_data[14] = createArray() item_data[15] = createArray() item_data[16] = createArray() item_data[17] = createArray() item_data[18] = createArray() item_data[00][0] = 000000000000000; item_data[00][1] = 000000000000000; item_data[00][2] = 000000000000000 item_data[01][0] = 000000000000000; item_data[01][1] = 000000000000000; item_data[01][2] = 000000000000000 item_data[02][0] = 000000000000000; item_data[02][1] = 000000000000000; item_data[02][2] = 000000000000000 item_data[03][0] = 000000000000000; item_data[03][1] = 000000000000000; item_data[03][2] = 000000000000000 item_data[04][0] = 000000000000000; item_data[04][1] = 000000000000000; item_data[04][2] = 000000000000000 item_data[05][0] = 000000000000000; item_data[05][1] = 000000000000000; item_data[05][2] = 000000000000000 item_data[06][0] = 000000000000000; item_data[06][1] = 000000000000000; item_data[06][2] = 000000000000000 item_data[07][0] = 000000000000000; item_data[07][1] = 000000000000000; item_data[07][2] = 000000000000000 item_data[08][0] = 000000000000000; item_data[08][1] = 000000000000000; item_data[08][2] = 000000000000000 item_data[09][0] = 000000000000000; item_data[09][1] = 000000000000000; item_data[09][2] = 000000000000000 item_data[10][0] = 000000000000000; item_data[10][1] = 000000000000000; item_data[10][2] = 000000000000000 item_data[11][0] = 000000000000000; item_data[11][1] = 000000000000000; item_data[11][2] = 000002000000000 item_data[12][0] = 000000000000000; item_data[12][1] = 000000000000000; item_data[12][2] = 000000000000000 item_data[13][0] = 000000000000000; item_data[13][1] = 000000000000000; item_data[13][2] = 000000000000000 item_data[14][0] = 000000000000000; item_data[14][1] = 000000000000000; item_data[14][2] = 000000000000000 item_data[15][0] = 000000000000000; item_data[15][1] = 000000000000000; item_data[15][2] = 000000000000000 item_data[16][0] = 000000000000000; item_data[16][1] = 000000000000000; item_data[16][2] = 000000000000000 item_data[17][0] = 000000000000000; item_data[17][1] = 000000000000000; item_data[17][2] = 000000000000000 item_data[18][0] = 000000000000000; item_data[18][1] = 000000000000000; item_data[18][2] = 000000000000000 item_data[00][3] = 000000000000000; item_data[00][4] = 000000000000000; item_data[00][5] = 000000000000000 item_data[01][3] = 000000000000000; item_data[01][4] = 000000000000000; item_data[01][5] = 000000000000000 item_data[02][3] = 000000000000000; item_data[02][4] = 000000000000000; item_data[02][5] = 000000000000000 item_data[03][3] = 000000000000000; item_data[03][4] = 000000000000000; item_data[03][5] = 000000000000000 item_data[04][3] = 000000000000000; item_data[04][4] = 000000000000000; item_data[04][5] = 000000000000000 item_data[05][3] = 000000000000000; item_data[05][4] = 000000000000000; item_data[05][5] = 000000000000000 item_data[06][3] = 000000000000000; item_data[06][4] = 000000000000000; item_data[06][5] = 000000000000000 item_data[07][3] = 000000000000000; item_data[07][4] = 000000000000000; item_data[07][5] = 000000000000000 item_data[08][3] = 000000000000000; item_data[08][4] = 000000000000000; item_data[08][5] = 000000000000000 item_data[09][3] = 000000000000000; item_data[09][4] = 000000000000000; item_data[09][5] = 000000000000000 item_data[10][3] = 000000000000000; item_data[10][4] = 000000000000000; item_data[10][5] = 000000000000000 item_data[11][3] = 000000000000000; item_data[11][4] = 000000000000000; item_data[11][5] = 000000000000000 item_data[12][3] = 000000000000000; item_data[12][4] = 000000000000000; item_data[12][5] = 000000000000000 item_data[13][3] = 000000000000000; item_data[13][4] = 000000000000000; item_data[13][5] = 000000000000000 item_data[14][3] = 000000000000000; item_data[14][4] = 000000000000000; item_data[14][5] = 000000000001000 item_data[15][3] = 000000000000000; item_data[15][4] = 000000000000000; item_data[15][5] = 000000000000000 item_data[16][3] = 000000000000000; item_data[16][4] = 000000000001000; item_data[16][5] = 000000000000000 item_data[17][3] = 000000000000000; item_data[17][4] = 000000000000000; item_data[17][5] = 000000000000000 item_data[18][3] = 000000000000000; item_data[18][4] = 000000000000000; item_data[18][5] = 000000000000000 item_data[00][6] = 000000000000000; item_data[00][7] = 000000000000000; item_data[00][8] = 000000000000000 item_data[01][6] = 000000000000000; item_data[01][7] = 000000000000000; item_data[01][8] = 000000000000000 item_data[02][6] = 000000000000000; item_data[02][7] = 000000000000000; item_data[02][8] = 000000000000000 item_data[03][6] = 000000000000000; item_data[03][7] = 000000000000000; item_data[03][8] = 000000000000000 item_data[04][6] = 000000000000000; item_data[04][7] = 000000000000000; item_data[04][8] = 000000000000000 item_data[05][6] = 000000000000000; item_data[05][7] = 000000000000000; item_data[05][8] = 000000000000000 item_data[06][6] = 000000000000000; item_data[06][7] = 000000000000000; item_data[06][8] = 000000000000000 item_data[07][6] = 000000000000000; item_data[07][7] = 000000000000000; item_data[07][8] = 000000000000000 item_data[08][6] = 000000000000000; item_data[08][7] = 000000000000000; item_data[08][8] = 000000000000000 item_data[09][6] = 000000000000000; item_data[09][7] = 000000000000000; item_data[09][8] = 000000000000000 item_data[10][6] = 000000000000000; item_data[10][7] = 000000000000000; item_data[10][8] = 000000000000000 item_data[11][6] = 000000000000000; item_data[11][7] = 000000000000000; item_data[11][8] = 000000000000000 item_data[12][6] = 000000000000000; item_data[12][7] = 000000000000000; item_data[12][8] = 000000000000000 item_data[13][6] = 000000000000000; item_data[13][7] = 000000000000000; item_data[13][8] = 000000000000000 item_data[14][6] = 000000000000000; item_data[14][7] = 000000000000000; item_data[14][8] = 000000000000000 item_data[15][6] = 000000000000000; item_data[15][7] = 000000000000000; item_data[15][8] = 000000000000000 item_data[16][6] = 000000000000000; item_data[16][7] = 000000000000000; item_data[16][8] = 000000000000000 item_data[17][6] = 000000000000000; item_data[17][7] = 000000000000000; item_data[17][8] = 000000000000000 item_data[18][6] = 000000000000000; item_data[18][7] = 000000000000000; item_data[18][8] = 000000000000000 item_data[00][9] = 000000000000000; item_data[00][10] = 000000000000000; item_data[00][11] = 000000000000000 item_data[01][9] = 000000000000000; item_data[01][10] = 000000000000000; item_data[01][11] = 000000000000000 item_data[02][9] = 000000000000000; item_data[02][10] = 000000000000000; item_data[02][11] = 000000000000000 item_data[03][9] = 000000000000000; item_data[03][10] = 000000000000000; item_data[03][11] = 000000000000000 item_data[04][9] = 000000000000000; item_data[04][10] = 000000000000000; item_data[04][11] = 000000000000000 item_data[05][9] = 002000000000000; item_data[05][10] = 000000000000000; item_data[05][11] = 000000000000000 item_data[06][9] = 000000000000000; item_data[06][10] = 000000000000000; item_data[06][11] = 000000000000000 item_data[07][9] = 000000000000000; item_data[07][10] = 000000000000000; item_data[07][11] = 000000000000000 item_data[08][9] = 000000000000000; item_data[08][10] = 000000000000000; item_data[08][11] = 000000000000000 item_data[09][9] = 000000000000000; item_data[09][10] = 000000000000000; item_data[09][11] = 000000000000000 item_data[10][9] = 000000000000000; item_data[10][10] = 000000000000000; item_data[10][11] = 000000000000000 item_data[11][9] = 000000001000000; item_data[11][10] = 000000000000000; item_data[11][11] = 000000000000000 item_data[12][9] = 000000000000000; item_data[12][10] = 000000000000000; item_data[12][11] = 000000000000000 item_data[13][9] = 000000000000000; item_data[13][10] = 000000000000000; item_data[13][11] = 000000000000000 item_data[14][9] = 000000000000000; item_data[14][10] = 000000000000000; item_data[14][11] = 000000000000000 item_data[15][9] = 000000000000000; item_data[15][10] = 000000000000000; item_data[15][11] = 000000000003000 item_data[16][9] = 000000000000000; item_data[16][10] = 000000000000000; item_data[16][11] = 000000000000000 item_data[17][9] = 000000000000000; item_data[17][10] = 000000000000000; item_data[17][11] = 000000000000000 item_data[18][9] = 000000000000000; item_data[18][10] = 000000000000000; item_data[18][11] = 000000000000000 setCreateItem(max_enemy, max_item, 1, map_size, item_data) #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #----- 変数の設定 ----- #ここから↓は省略
「item_data」変数の中身は
「000」は、データなし
「001」は、敵キャラクター
「002」は、アイテム
「003」は、ゴール
の位置がセットされている配列変数になっています。
先ほど作成した「setCreateItem」関数にデータを引数としてセットし、
画面上への配置を行っています。
キャラクターのアニメーションを応用して、
敵キャラクターのアニメーションをつくります。
#ここから↑は省略 setCharSpritePattern(2 + (char_muki * 10)) end end #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #----- 敵キャラクターのアニメーション ----- i = 0 while i < max_enemy #アニメーション用カウンター 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 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 i = i + 1 end #----- キャラクターの当たり判定 ----- #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #マップとの当たり判定 if char_act != act_dmg #ここから↓は省略
基本的な仕組みはキャラクターのアニメーションと同じです。
「setEnemySpritePattern」関数を追加したときと同様、
敵キャラクターの数だけループするように変更しています。
ここまでで、敵・アイテムの表示ができました。
保存、終了をして、テストプレーを行い、
設定したとおりに表示されているか確認してみましょう。
03-03 敵・アイテムの当たり判定を追加する
基本的な当たり判定の仕組みは、前回の第4回で解説したとおりです。
前回と異なる点は、敵の場合はゲームオーバーで良いですが、
アイテムの場合はポイント取得、ゴールの場合はポイント取得後
ゲームクリアとなるように変更します。
それではチャプター1にて、定数の追加から追加していきます。
#ここから↑は省略 #敵キャラクターの設定 max_enemy = 3 enemy_anime_change = 2 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ enemy_hit = createArray() enemy_hit[x] = 10; enemy_hit[y] = 10 enemy_hit[w] = 35; enemy_hit[h] = 35 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #アイテムの設定 max_item = 2 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ item_hit = createArray() item_hit[x] = 30; item_hit[y] = 52 item_hit[w] = 37; item_hit[h] = 35 item_point = 200 #ゴールの設定 goal_hit = createArray() goal_hit[x] = 30; goal_hit[y] = 5 goal_hit[w] = 37; goal_hit[h] = 90 goal_point = 500 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #ここから↓は省略
「enemy_hit」「item_hit」「goal_hit」は各画像の当たり判定の範囲、
「item_point」「goal_point」は取得時の入手ポイントを設定しています。
次は、変数の設定です。
#ここから↑は省略 #敵キャラクター enemy_anime_count = createArray() enemy_muki = createArray() enemy_act = 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_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 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #アイテム item_atari = createArray() i = 0 while i < max_item #アイテムの当たり判定範囲 item_atari[i] = createArray() item_atari[i][x] = getVariable(pos_item)[i][x] + item_hit[x] - getVariable(pos_map)[x] item_atari[i][y] = getVariable(pos_item)[i][y] + item_hit[y] - getVariable(pos_map)[y] item_atari[i][w] = item_atari[i][x] + item_hit[w] item_atari[i][h] = item_atari[i][y] + item_hit[h] i = i + 1 end #ゴール goal_atari = createArray() i = 0 #ゴールの当たり判定範囲 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] #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #ここから↓は省略
当たり判定の範囲については、前回の第4回と同じ仕組みになっています。
しかし、今回は敵キャラクター自体の移動量だけではなく、
キャラクターの移動によってマップと共に敵キャラクターもスクロールします。
そのためマップのスクロール量である「getVariable(pos_map)」の座標分、
マイナスすることで当たり判定の位置を計算しなおしてしています。
メインループに当たり判定のスクリプトを追加します。
場所はマップの当たり判定を行ったすぐ後です。
#ここから↑は省略 #中心線 getVariable(pos_map)[x] = getVariable(pos_map)[x] - xSa if getVariable(pos_map)[x] > map_w pos_char[x] = pos_char[x] + (getVariable(pos_map)[x] - map_w) getVariable(pos_map)[x] = map_w end end end end #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #キャラクターの当たり判定範囲(座標変化後の再設定) char_atari[x1] = pos_char[x] + char_hit[x] char_atari[y1] = pos_char[y] + char_hit[y] char_atari[x3] = char_atari[x1] + char_hit[w] char_atari[y3] = char_atari[y1] + char_hit[h] #_/_/_/ ゴールとの当たり判定 _/_/_/ i = 0 #ゴールの当たり判定範囲 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] #当たり判定のチェック if ((char_atari[x3]) > (goal_atari[i][x])) && ((char_atari[y3]) > (goal_atari[i][y])) && ((char_atari[x1]) < (goal_atari[i][w])) && ((char_atari[y1]) < (goal_atari[i][h])) score = score + goal_point #ゲームクリア開始 end #_/_/_/ アイテムとの当たり判定 _/_/_/ i = 0 while i < max_item #アイテムの当たり判定範囲 item_atari[i] = createArray() item_atari[i][x] = getVariable(pos_item)[i][x] + item_hit[x] - getVariable(pos_map)[x] item_atari[i][y] = getVariable(pos_item)[i][y] + item_hit[y] - getVariable(pos_map)[y] item_atari[i][w] = item_atari[i][x] + item_hit[w] item_atari[i][h] = item_atari[i][y] + item_hit[h] #当たり判定のチェック if ((char_atari[x3]) > (item_atari[i][x])) && ((char_atari[y3]) > (item_atari[i][y])) && ((char_atari[x1]) < (item_atari[i][w])) && ((char_atari[y1]) < (item_atari[i][h])) score = score + item_point getVariable(pos_item)[i][x] = (-100) getVariable(pos_item)[i][y] = 700 setSpritePos("img_item", getVariable(pos_item), i) end i = i + 1 end #_/_/_/ 敵キャラクターとの当たり判定 _/_/_/ i = 0 while i < max_enemy #敵キャラクターの当たり判定範囲 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[y3]) > (enemy_atari[i][y])) && ((char_atari[x1]) < (enemy_atari[i][w])) && ((char_atari[y1]) < (enemy_atari[i][h])) #ゲームオーバー開始 end i = i + 1 end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ end #画面端との当たり判定 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 #ここから↓は省略
当たり判定の範囲の比較についても、前回の第4回と
同じ仕組みになっています。
アイテムに当たった場合、何度も同じアイテムに当たらないよう
アイテムの位置座標を変更しています。
ここまでで、敵・アイテムの当たり判定ができました。
引き続き、当たった後のスクリプトを追加していきます。
03-04 ゲームオーバー、ゲームクリアを実装する
敵キャラクターやゴールの当たり判定ができましたので、
ゲームオーバー、ゲームクリアができるようにしてみましょう。
同時に、スコア表示も追加していきます。
チャプター0にて、スコア表示用の関数を追加します。
#ここから↑は省略 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #0埋め def addZero(n, b) l = 0; c = n; r = ""; b = b - 1 while c > 9 c = floor(c / 10); l = l + 1 end while l < b r = r + "0"; l = l + 1 end r = r + n return r end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #べき乗 def POWER(n, b) r = 1; i = 0 while i < b r = r * n; i = i + 1 end return r end #ここから↓は省略
チャプター1に移動して、定数・変数の準備から。
#ここから↑は省略 #ゴールの設定 goal_hit = createArray() goal_hit[x] = 30; goal_hit[y] = 5 goal_hit[w] = 37; goal_hit[h] = 90 goal_point = 500 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ goal_wait_time = 100 gameover_pos_y = 700 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #音楽・効果音の設定 bgm_main = 66498 #中略 #キャラクター char_anime_count = 0 char_muki = 1 char_act = act_std char_jmp_count = 0 char_jmp_flg = false #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ char_dmg_count = 0 char_goal_count = 0 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #キャラクターの当たり判定範囲 #ここから↓は省略
「goal_wait_time」定数はゲームクリアまでの待ち時間
「gameover_pos_y」定数はキャラクターがダメージ中状態になってから
ゲームオーバーまでの座標
「char_dmg_count」「char_goal_count」変数は
それぞれの時間カウントに使用します。
スコアの表示場所を設定します。
#ここから↑は省略 #ゴールの当たり判定範囲 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] #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #----- テキストボックスの設定 ----- #スコア表示の設定 setTextFontSize(25) setTextFontColor(200, 255, 220) set[x] = 11; set[y] = 11; set[w] = 600; set[h] = 800 text_score = createText(set[x], set[y], set[w], set[h]) #スコアの初期表示 score = 0 str = "スコア " str = str + addZero(score, 5) setText(text_score, str) #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #音楽の再生開始 #ここから↓は省略
ダメージ中の動作をつくります。
ジャンプ中の動作をベースに、少し待ち時間を含めています。
#ここから↑は省略 #----- ゲームのメイン処理を入れる場所 ----- #(ゲームの終了時はmainloopをfalseに) #----- キャラクターの移動 ----- #_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/ if (char_act != act_dmg) && (char_goal_count == 0) #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ if key_flg_left #中略 #----- キャラクターのジャンプ ----- if key_flg_z if (char_act != act_jmp) && !(char_jmp_flg) char_act = act_jmp; char_jmp_count = 0; char_jmp_flg = true end else char_jmp_flg = false end #_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/ end if char_act == act_jmp if char_jmp_count < 10 pos_char[y] = pos_char[y] - (char_jmp_h * (0.4 + ((6 - char_jmp_count) * 0.1))) else pos_char[y] = pos_char[y] + (char_jmp_h * (0.4 + ((char_jmp_count - 14) * 0.1))) end if char_jmp_count < 20 char_jmp_count = char_jmp_count + 1 end end #ダメージ中 if char_act == act_dmg if char_dmg_count < 10 elsif char_dmg_count < 20 pos_char[y] = pos_char[y] - (char_jmp_h * (0.4 + ((6 - (char_dmg_count - 10)) * 0.1))) else pos_char[y] = pos_char[y] + (char_jmp_h * (0.4 + (((char_dmg_count - 10) - 14) * 0.1))) end if char_dmg_count < 30 char_dmg_count = char_dmg_count + 1 end end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #----- キャラクターのアニメーション ----- #ここから↓は省略
キャラクターを操作できる条件が、ダメージ中ではなくさらに
ゴール中でない時に行われるよう変更されています。
ダメージ中の動きについては
ジャンプ時間が20を頂点に、上昇中・下降中を切り替えています。
ジャンプ時間が30以上になったとき、落下速度は固定となります。
次に、表示の切り替え。
#ここから↑は省略 #キャラクターの表示を切替 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 elsif char_act == act_jmp if char_jmp_count < 10 setCharSpritePattern(7 + (char_muki * 10)) else setCharSpritePattern(8 + (char_muki * 10)) end #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ elsif char_act == act_dmg if char_dmg_count < 20 setCharSpritePattern(9 + (char_muki * 10)) else setCharSpritePattern(10 + (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 (char_act != act_dmg) && (char_goal_count == 0) #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #マップとの当たり判定 #中略 #ゴールの当たり判定範囲 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] #当たり判定のチェック if ((char_atari[x3]) > (goal_atari[i][x])) && ((char_atari[y3]) > (goal_atari[i][y])) && ((char_atari[x1]) < (goal_atari[i][w])) && ((char_atari[y1]) < (goal_atari[i][h])) score = score + goal_point #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #ゲームクリア開始 char_goal_count = 1 char_act = act_std fadeOutMusicStop(100) #音楽の停止 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ end #ここから↓は省略
次に、敵キャラクターに当たった時、穴に落下した時。
#ここから↑は省略 #敵キャラクターの当たり判定範囲 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[y3]) > (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) #音楽の停止 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ end i = i + 1 end #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #穴に落下 if pos_char[y] > (gameover_pos_y - 25) #ダメージ状態開始 char_act = act_dmg; char_dmg_count = 0 fadeOutMusicStop(100) #音楽の停止 end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #ここから↓は省略
ダメージ中、ゲームクリア中の場合、設定した時間後に、
ゲームオーバー、ゲームクリアへ移動するようにします。
#ここから↑は省略 #穴に落下 if pos_char[y] > (gameover_pos_y - 25) #ダメージ状態開始 char_act = act_dmg; char_dmg_count = 0 fadeOutMusicStop(100) #音楽の停止 end #_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/ elsif char_goal_count > 0 #ゴール中 char_goal_count = char_goal_count + 1 if char_goal_count > goal_wait_time #ゲームクリアへ mainloop = false end else #ダメージ中 if pos_char[y] > gameover_pos_y #ゲームオーバーへ mainloop = false end end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #画面端との当たり判定 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 #ここから↓は省略
スコアを表示します。
#ここから↑は省略 #----- 背景のスクロール ----- setSpriteCameraOffset(-(getVariable(pos_map)[x]), 0) #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #----- スコアの表示 ----- str = "スコア " str = str + addZero(score, 5) setText(text_score, str) #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #----- 画面の更新 ----- if draw_flg drawCanvas() #描画OKならキャンバスを更新 end #ここから↓は省略
メインループを抜けた後、
ゲームクリア、ゲームオーバー画面へ移動します。
#ここから↑は省略 endInput() #入力受付の終了 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ if char_act == act_dmg feedstr = "残念 スコア " feedstr = feedstr + addZero(score, 5) feedstr = feedstr + " で ゴールできませんでした" openActivityFeedWindow(feedstr) goBadEnding() #ゲームオーバー else feedstr = "見事 スコア " feedstr = feedstr + addZero(score, 5) feedstr = feedstr + " で ゴールしました!" openActivityFeedWindow(feedstr) goEnding() #ゲームのクリア end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
スクリプト全体
これで、一通り完成です。
保存、終了をして、テストプレーを行い、
敵・アイテムの当たり判定、ゲームクリアとゲームオーバーが行えるか
確認してみましょう。
03-05 おわりに
いかがでしたでしょうか。
今回のところまでで、一通り
ACTゲームとして遊べるようになりました。
さて、次回はより面白くするために
「敵の動きや背景の演出を入れてみよう」を実践してみましょう。
第01回 関数を再利用してみよう
第02回 マップを表示してみよう
第03回 敵・アイテムを追加してみよう
第04回 敵の動きや背景の演出を入れてみよう
番外 外部ツールと連携してみよう
この記事についてご質問等がありましたら
こちらのブログ記事のコメントへご投稿、
よろしくお願いいたします。