スクリプト/RmakeでACTゲームをつくろう / 第02回 マップを表示してみよう(履歴ID:131)
最終投稿者: aoihikawa
更新:2012/03/22 18:42:47
RmakeでACTゲームをつくろう
第02回 マップを表示してみよう
こんにちは。
フリーデザイナープログラマー(自称)の
簸川 葵(ひかわ あおい)と申します。
第01回 では「関数を再利用してみよう」ということで、移植の手順についてお話しました。
今回はACTゲームの重要な基盤である、マップの表示を実践してみましょう。
02-01 マップを画面に表示する
基本的な表示の仕組みは、前回の第2回で解説したとおりです。
マップの画像から、1チップあたりのサイズに合わせて、
切り取り・貼り付けを行うスクリプトを繰り返し、マップを表示していきます。
今回もまた、お手軽にスクリプトの作成までできるよう、
サンプルの素材を準備いたしました。
こちらを参考に、クリップからリソースへの登録まで行い、
すぐにスクリプトで利用できるように、準備してください。
今回はにぃみゃん の おさんぽびよりで使用した
マップ設定関数を移植して利用します。
一部、この素材向けに作っている箇所がありますので、
ほかの素材に差し替えて利用する場合は注意してください。
まずはチャプター0にて、一番上に汎用関数を移植します。
#メニュー項目等の表示OFF setMenuItemVisible(getMenuBackLog(), false) setMenuItemVisible(getMenuSave(), false) setMenuItemVisible(getMenuLoad(), false) setHelpVisible(false) #キャンバスの初期化 setCanvasVisible(false) deleteAllSprite() drawCanvas() #----- 関数の設定 ----- #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #べき乗 def POWER(n, b) r = 1; i = 0 while i < b r = r * n; i = i + 1 end return r end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #ここから↓は省略
次に、一番下にマップを設定を設定する関数を移植します。
#ここから↑は省略 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #マップを設定 def setCreateMap(img_name, img_no, pos, set_z, map_w, map_dat) x = 0; y = 1; w = 2; h = 3 set_map = createArray(); get = createArray(); set = createArray() get[x] = 0; get[y] = 0; get[w] = 32; get[h] = 32 set[x] = 0; set[y] = 0; set[w] = 32; set[h] = 32 #レイヤーが4なら当たり判定の配列を作成 if set_z == 4 hit_map = createArray() end i = 0; ilen = getArrayLength(map_dat) while i < ilen if set_z == 4 hit_map[i] = createArray() end 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 set_z == 4 hit_map[i][(k + (j * map_w))] = 19 end else #画像の切り出しポイントを算出 if k < (klen - 1) chk = (map_d / POWER(1000, (map_w - (k + 1)))) else chk = map_d end chk3 = false #画像の貼り付けポイントを算出 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 chk3 = true end end #画像を切り出して貼り付けする chk = floor(chk) if (chk != 19) #019番目の画像の場合、画像とあたり判定をセットしない get[x] = set_map[x] * 32; get[y] = set_map[y] * 32 set[x] = (32 * k) + (32 * j * map_w); set[y] = 32 * i if (chk != 278) #278番目の画像の場合、画像をセットしない setCreateSprite(img_name, img_no, get, set, set_z, getVariable(pos)) if set_z == 2 setSpriteIndependentCamera(getVariable(img_name), true) end end if set_z == 4 hit_map[i][(k + (j * map_w))] = chk end else if set_z == 4 hit_map[i][(k + (j * map_w))] = 19 end end end k = k + 1 end j = j + 1 end i = i + 1 end if set_z == 4 setVariable("hit_map", hit_map) end end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
マップデータの配列を受け取り、
画像の切り出しと、貼り付けをする関数です。
レイヤーを指定している「set_z」変数が
2の場合、カメラにスクロールをあわせる、多重スクロール背景用のレイヤーを、
4の場合、当たり判定の「hit_map」変数を同時に設定する、実際のマップ用のレイヤーを
設定するようになっています。
なお、この素材向けに、
019番目のチップ画像は、当たり判定なしの空白チップ、
278番目のチップ画像は、当たり判定ありの空白チップを
設定するようになっていますので注意してください。
マップ画像のチップ位置番号につきましては、
こちらにわかりやすい一覧を纏めましたのでご活用ください。
チャプター1に移動して、マップデータの準備を実行後、
マップを設定する関数を呼び出すスクリプトを追加します。
#ここから↑は省略 #背景画像の設定 img_no = 79101 img_bg_name = "img_bg" get[x] = 0; get[y] = 0; get[w] = 800; get[h] = 600 set[x] = 0; set[y] = 0; set[w] = 800; set[h] = 600 set_z = 1 pos_bg = createArray() pos_bg[x] = 0; pos_bg[y] = 0 setCreateSprite(img_bg_name, img_no, get, set, set_z, pos_bg) setSpriteIndependentCamera(getVariable(img_bg_name), true) #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #マップ画像の設定 img_no = 79094 map_size = 5 img_map_name = "img_map"; pos_map = "pos_map" 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() set_z = 4 #マップデータを作成 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] = 019019019019019 map_data[06][0] = 019019019019019; 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] = 019019019019019; map_data[08][2] = 019019019019019 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] = 019005007019019 map_data[15][0] = 019019019019019; map_data[15][1] = 019019019019019; map_data[15][2] = 019037039019019 map_data[16][0] = 019019019019019; map_data[16][1] = 019019019019019; map_data[16][2] = 019037039019019 map_data[17][0] = 019019019019019; map_data[17][1] = 019019019019019; map_data[17][2] = 019037039019019 map_data[18][0] = 006006006006006; map_data[18][1] = 006006006006006; map_data[18][2] = 006038038006006 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] = 019019019019019; 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] = 019019019019019 map_data[08][3] = 019019019019019; map_data[08][4] = 019019019019019; 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] = 005006006006006 map_data[17][3] = 019019019019019; map_data[17][4] = 019019019019019; map_data[17][5] = 037038038038038 map_data[18][3] = 006006006006006; map_data[18][4] = 006006006006006; map_data[18][5] = 038038038038038 map_data[00][6] = 019019019019019; map_data[00][7] = 019019019019019; map_data[00][8] = 019019019019019 map_data[01][6] = 019019019019019; map_data[01][7] = 019019019019019; map_data[01][8] = 019019019019019 map_data[02][6] = 019019019019019; map_data[02][7] = 019019019019019; map_data[02][8] = 019019019019019 map_data[03][6] = 019019019019019; map_data[03][7] = 019019019019019; map_data[03][8] = 019019019019019 map_data[04][6] = 019019019019019; map_data[04][7] = 019019019019019; map_data[04][8] = 019019019019019 map_data[05][6] = 019019019019019; map_data[05][7] = 019019019019019; map_data[05][8] = 019019019019019 map_data[06][6] = 019019019019019; map_data[06][7] = 019019019019019; map_data[06][8] = 019019019019019 map_data[07][6] = 019019019019019; map_data[07][7] = 019019019019019; map_data[07][8] = 019019019019019 map_data[08][6] = 019019019019019; map_data[08][7] = 019019019019019; map_data[08][8] = 019019019019019 map_data[09][6] = 019019019019019; map_data[09][7] = 019019019019019; map_data[09][8] = 019019019019019 map_data[10][6] = 019019019019019; map_data[10][7] = 019019019019019; map_data[10][8] = 019019019019019 map_data[11][6] = 019019019019019; map_data[11][7] = 019019019019019; map_data[11][8] = 019019019019019 map_data[12][6] = 019019019019019; map_data[12][7] = 019019019019019; map_data[12][8] = 019019019019019 map_data[13][6] = 019019019019019; map_data[13][7] = 019019019019019; map_data[13][8] = 019019019001002 map_data[14][6] = 005006006007019; map_data[14][7] = 019019019019019; map_data[14][8] = 019019019019019 map_data[15][6] = 037038038039019; map_data[15][7] = 019019019019019; map_data[15][8] = 019019019019019 map_data[16][6] = 038038038039019; map_data[16][7] = 019019019019019; map_data[16][8] = 019019019019019 map_data[17][6] = 038038038039019; map_data[17][7] = 019019019019019; map_data[17][8] = 019019019019019 map_data[18][6] = 038038038039019; map_data[18][7] = 019019019019005; map_data[18][8] = 006006006006006 map_data[00][9] = 019019019019019; map_data[00][10] = 019019019019019; map_data[00][11] = 019019019019019 map_data[01][9] = 019019019019019; map_data[01][10] = 019019019019019; map_data[01][11] = 019019019019019 map_data[02][9] = 019019019019019; map_data[02][10] = 019019019019019; map_data[02][11] = 019019019019019 map_data[03][9] = 019019019019019; map_data[03][10] = 019019019019019; map_data[03][11] = 019019019019019 map_data[04][9] = 019019019019019; map_data[04][10] = 019019019019019; map_data[04][11] = 019019019019019 map_data[05][9] = 019019019019019; map_data[05][10] = 019019019019019; map_data[05][11] = 019019019019019 map_data[06][9] = 019019019019019; map_data[06][10] = 019019019019019; map_data[06][11] = 019019019019019 map_data[07][9] = 019019019019019; map_data[07][10] = 019019019019019; map_data[07][11] = 019019019019019 map_data[08][9] = 001003019019019; map_data[08][10] = 019019019019019; map_data[08][11] = 019019019019019 map_data[09][9] = 019019019019019; map_data[09][10] = 019019019019019; map_data[09][11] = 019019019019019 map_data[10][9] = 019019019019019; map_data[10][10] = 019019019019019; map_data[10][11] = 019019019019019 map_data[11][9] = 019019019019019; map_data[11][10] = 019019019019019; map_data[11][11] = 019019019019019 map_data[12][9] = 019019019019019; map_data[12][10] = 019019019019019; map_data[12][11] = 019019019019019 map_data[13][9] = 002002002003019; map_data[13][10] = 019019019019019; map_data[13][11] = 019019019019019 map_data[14][9] = 019019019019019; map_data[14][10] = 019019019019019; map_data[14][11] = 019019019019019 map_data[15][9] = 019019019019019; map_data[15][10] = 019019019019019; map_data[15][11] = 019019019019019 map_data[16][9] = 019019019019019; map_data[16][10] = 019019019019019; map_data[16][11] = 019019019019019 map_data[17][9] = 019019019019019; map_data[17][10] = 019019019019019; map_data[17][11] = 019019019019019 map_data[18][9] = 006006006006006; map_data[18][10] = 006006006006006; map_data[18][11] = 006006006006006 #マップデータの設定 setCreateMap(img_map_name, img_no, pos_map, set_z, map_size, map_data) #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #----- 変数の設定 ----- #ここから↓は省略
画像表示に関連した基本的な部分の設定項目は、
他の画像表示設定と同じ要領で行います。
「map_size」変数は、1つの配列データあたりのチップ数を設定しています。
「map_data」変数の配列は、先ほどの画像チップ番号情報を設定しています。
1チップあたり3桁の数字、実際の画面表示と同じ方向へデータ列が並んでいます。
最後に、マップを設定するsetCreateMap関数を利用して、画像の設定を行います。
ここまでで、マップの表示ができました。
保存、終了をして、テストプレーを行い、
マップが設定したデータ通りに表示されているか確認してみましょう。
02-02 マップをスクロールさせる
第01回で少しお話に出てきました、カメラの移動を利用して
マップのスクロールをつくってみましょう。
なお、マップのスクロールは次のような仕組みでつくります。
まずは、必要な定数の設定から。
#ここから↑は省略 #キャラクターの設定 char_speed = 7 char_w_max = 800 - 63; char_h_max = 600 - 80 char_anime_change = 6 char_hit = createArray() char_hit[x] = 30; char_hit[y] = 10 char_hit[w] = 33; char_hit[h] = 80 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #背景の設定 bg_center = 352 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #音楽・効果音の設定 #ここから↓は省略
「bg_center」変数は、画面横幅の半分となるサイズから、
キャラクター画像横幅の半分となるサイズを引いた値を設定しています。
マップをスクロールさせるとは、
マップが画面端の場合はキャラクターの座標を、
そうでない場合はマップの座標を
進行方向とは逆方向に移動させて行います。
このとき、キャラクターとマップのどちらを移動させるか
切り替えるポイントとなる中心点の座標です。
次は、必要な変数の設定。
チャプター1にて、先ほど追加したマップの設定のすぐ後ろに追加します。
#ここから↑は省略 map_data[18][9] = 006006006006006; map_data[18][10] = 006006006006006; map_data[18][11] = 006006006006006 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ 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 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #----- 変数の設定 ----- #ここから↓は省略
「map_count」変数は、全体のマップ横サイズ(チップ数)
「map_max_w」変数は、全体のマップ横サイズ(座標値)
「map_w」変数は、全体のマップ横サイズ(座標値)から画面横幅の800を引いた数を
設定しています。
マップが画面端に到達しているか、判定するために使用します。
キャラクターの移動スクリプトを差し替えて、
マップのスクロールをつくります。
#ここから↑は省略 #_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/ #----- キャラクターの移動 ----- if char_act != act_dmg if key_flg_left #左へ移動 if (pos_char[x] < bg_center) || ((pos_char[x] > bg_center) && (getVariable(pos_map)[x] == map_w)) #中心線より外側 pos_char[x] = pos_char[x] - char_speed if (pos_char[x] < bg_center) && (getVariable(pos_map)[x] == map_w) getVariable(pos_map)[x] = getVariable(pos_map)[x] - (bg_center - pos_char[x]) pos_char[x] = bg_center end else #中心線 getVariable(pos_map)[x] = getVariable(pos_map)[x] - char_speed if getVariable(pos_map)[x] < 0 pos_char[x] = pos_char[x] + getVariable(pos_map)[x] getVariable(pos_map)[x] = 0 end end char_muki = 0 elsif key_flg_right #右へ移動 if (pos_char[x] > bg_center) || ((pos_char[x] < bg_center) && (getVariable(pos_map)[x] == 0)) #中心線より外側 pos_char[x] = pos_char[x] + char_speed if (pos_char[x] > bg_center) && (getVariable(pos_map)[x] == 0) getVariable(pos_map)[x] = getVariable(pos_map)[x] + (pos_char[x] - bg_center) pos_char[x] = bg_center end else #中心線 getVariable(pos_map)[x] = getVariable(pos_map)[x] + char_speed 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 char_muki = 1 else end end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #ここから↓は省略
先ほど追加した定数・変数を元に、
キャラクターとマップのスクロールを切り替えています。
また、切り替わる瞬間のとき、
キャラクターの移動速度とキャラクターの移動量・マップの移動量を比較して
端数が出た場合、それぞれマップの移動量・キャラクターの移動量に
その端数を加算するように調整しています。
最後に、実際にマップをスクロールさせます。
マップのスクロールはカメラの移動を利用します。
#ここから↑は省略 setSpritePos(img_char_name, pos_char) end #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #----- 背景のスクロール ----- setSpriteCameraOffset(-(getVariable(pos_map)[x]), 0) #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #----- 画面の更新 ----- #ここから↓は省略
カメラが右に移動するとマップは左に、
カメラが右に移動するとマップは右に移動するため、
X座標の値をマイナスでセットしています。
ここまでで、マップのスクロールができました。
保存、終了をして、テストプレーを行い、
マップがスクロールできているか確認してみましょう。
02-03 マップの当たり判定を追加する
基本的な当たり判定の仕組みは、前回の第4回で解説したとおりです。
しかし、マップ内にあるすべてのチップひとつひとつに、
当たり判定のスクリプトを動かしていると、膨大な処理量になってしまいます。
そこで、マップ側の当たり判定を座標情報を元に簡易的に判定することで、
この処理量を軽減します。
「hit_map」変数については、setCreateMap関数を行うとき、
レイヤーが4なら同時に作っておくスクリプトになっていました。
この「hit_map」変数を元に、当たり判定を行う仕組みをつくっていきます。
まずは、チャプター0にて、一番下に座標情報を取得する関数を追加します。
#ここから↑は省略 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #当たり判定の座標を算出 def setHitMap(char_atari, map_count) x1 = 0; y1 = 1; x2 = 2; y2 = 3; x3 = 4; y3 = 5 #当たり判定を行う座標を算出 charHit_X1 = floor((char_atari[x1] + (getVariable("pos_map")[0])) / 32) charHit_X2 = floor((char_atari[x2] + (getVariable("pos_map")[0])) / 32) charHit_X3 = floor((char_atari[x3] + (getVariable("pos_map")[0])) / 32) charHit_Y1 = floor((char_atari[y1] + (getVariable("pos_map")[1] + 16)) / 32) charHit_Y2 = floor((char_atari[y2] + (getVariable("pos_map")[1] + 16)) / 32) charHit_Y3 = floor((char_atari[y3] + (getVariable("pos_map")[1] + 16)) / 32) charHit_Y4 = floor((char_atari[y3] + (getVariable("pos_map")[1] + 17)) / 32) #画面外の場合、画面端の座標とする if charHit_X1 < 0 charHit_X1 = 0 end if charHit_X3 > map_count charHit_X3 = map_count end if charHit_Y1 < 0 charHit_Y1 = 0 if charHit_Y2 < 0 charHit_Y2 = 0 if charHit_Y3 < 0 charHit_Y3 = 0 if charHit_Y4 < 0 charHit_Y4 = 0 end end end end if charHit_Y4 > 18 charHit_Y4 = 18 if charHit_Y3 > 18 charHit_Y3 = 18 if charHit_Y2 > 18 charHit_Y2 = 18 if charHit_Y1 > 18 charHit_Y1 = 18 end end end end #座標のマップ情報を取得 charHitpos = createArray() charHitpos[0] = getVariable("hit_map")[charHit_Y1][charHit_X1] charHitpos[1] = getVariable("hit_map")[charHit_Y1][charHit_X2] charHitpos[2] = getVariable("hit_map")[charHit_Y1][charHit_X3] charHitpos[3] = getVariable("hit_map")[charHit_Y2][charHit_X1] charHitpos[4] = getVariable("hit_map")[charHit_Y2][charHit_X2] charHitpos[5] = getVariable("hit_map")[charHit_Y2][charHit_X3] charHitpos[6] = getVariable("hit_map")[charHit_Y3][charHit_X1] charHitpos[7] = getVariable("hit_map")[charHit_Y3][charHit_X2] charHitpos[8] = getVariable("hit_map")[charHit_Y3][charHit_X3] charHitpos[9] = getVariable("hit_map")[charHit_Y4][charHit_X1] charHitpos[10] = getVariable("hit_map")[charHit_Y4][charHit_X2] charHitpos[11] = getVariable("hit_map")[charHit_Y4][charHit_X3] charHitpos[12] = charHit_X1 charHitpos[13] = charHit_X2 charHitpos[14] = charHit_X3 charHitpos[15] = charHit_Y1 charHitpos[16] = charHit_Y2 charHitpos[17] = charHit_Y3 charHitpos[18] = charHit_Y4 return charHitpos end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/
キャラクターとマップの座標を元に、
先ほどのイラストの黄色ポイントを算出する関数です。
各座標のhit_map情報と、座標番号を戻り値にセットしています。
なお、Y座標の3番目と4番目は、キャラクターの足元の判定より
1ドット下の当たり判定を比較することで、
着地しているかどうか判断するために使用します。
次は、定数の設定です。
#ここから↑は省略 #----- 定数の設定 ----- x = 0; y = 1; w = 2; h = 3 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ x1 = 0; y1 = 1; x2 = 2; y2 = 3; x3 = 4; y3 = 5 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ act_std = 0; act_wrk = 1; act_jmp = 2; act_dmg = 3 #ここから↓は省略
当たり判定のポイントによって、
キャラクターの座標を当たり判定外に移動させるスクリプトをつくります。
少しスクリプトの流れが複雑ですので、フローを纏めました。
・開始 ↓ <地面に埋まっている > ↓ はい |いいえ ・着地状態に変更 | | ↓ | <着地している > ↓ ↓ はい ↓ いいえ <壁にめり込んでいる > <ジャンプ中 > ↓ はい |いいえ |はい ↓ いいえ ・壁の外側へ移動 | | ・ジャンプ状態に変更 | | ↓ ↓ | | <天井にめり込んでいる > | | ↓ はい |いいえ | | ・天井の位置に変更 | | | ↓ ↓ | | <壁にめり込んでいる > | | ↓ はい |いいえ | | ・壁の外側へ移動 | ↓ ↓ ↓ ↓ ・終了
このフローにそって、スクリプトを書いていきます。
#ここから↑は省略 #_/_/_/_/_/_/_/_/_/_/_/_/ 変更分 _/_/_/_/_/_/_/_/_/_/_/_/ #マップとの当たり判定 if char_act != act_dmg HitFlgD = false; HitFlgM = false; HitFlgLD = false; HitFlgRD = false HitFlgU = false; HitFlgLU = false; HitFlgRU = false HitFlgLS = false; HitFlgRS = false xSa = 0; ySa = 0 #キャラクターの当たり判定範囲 char_atari[x1] = pos_char[x] + char_hit[x] char_atari[y1] = pos_char[y] + char_hit[y] char_atari[x2] = char_atari[x1] + (char_hit[w] * 0.5) char_atari[y2] = char_atari[y1] + (char_hit[h] * 0.5) char_atari[x3] = char_atari[x1] + char_hit[w] char_atari[y3] = char_atari[y1] + char_hit[h] #当たり判定の座標を算出 charHitpos = setHitMap(char_atari, map_count) charHit_X1 = charHitpos[12] charHit_X2 = charHitpos[13] charHit_X3 = charHitpos[14] charHit_Y1 = charHitpos[15] charHit_Y2 = charHitpos[16] charHit_Y3 = charHitpos[17] charHit_Y4 = charHitpos[18] #床の当たり判定 #右端または左端だけの場合フラグ除外するためのフラグ if (charHitpos[9] != 19) && (charHitpos[10] == 19) && (charHitpos[11] == 19) HitFlgLD = true end if (charHitpos[9] == 19) && (charHitpos[10] == 19) && (charHitpos[11] != 19) HitFlgRD = true end if ((charHitpos[6] == 19) && (charHitpos[9] != 19)) || ((charHitpos[7] == 19) && (charHitpos[10] != 19)) || ((charHitpos[8] == 19) && (charHitpos[11] != 19)) #着地中 HitFlgD = true elsif ((charHitpos[6] != 19) && (charHitpos[9] != 19)) || ((charHitpos[7] != 19) && (charHitpos[10] != 19)) || ((charHitpos[8] != 19) && (charHitpos[11] != 19)) #埋まり中 HitFlgM = true #当たり判定からの差分座標を算出 ySa = char_atari[y3] - (((charHit_Y3 - 1) * 32) - getVariable("pos_map")[y] + 15) end #天井の当たり判定 #右端または左端だけの場合フラグ除外するためのフラグ if (charHitpos[0] != 19) && (charHitpos[1] == 19) && (charHitpos[2] == 19) HitFlgLU = true end if (charHitpos[0] == 19) && (charHitpos[1] == 19) && (charHitpos[2] != 19) HitFlgRU = true end if (!(HitFlgD) || !(HitFlgM)) && !(HitFlgLU) && !(HitFlgRU) && ( (charHitpos[0] != 19) || (charHitpos[1] != 19) || (charHitpos[2] != 19)) #埋まり中 HitFlgU = true #当たり判定からの差分座標を算出 ySa = ((charHit_Y1 * 32) - getVariable("pos_map")[y] + 16) - char_atari[y1] end if pos_char[y] > 600 ySa = 0 end #キャラクターの状態変化と差分の移動 if (HitFlgD || HitFlgM) && !(HitFlgLD) && !(HitFlgRD) #着地中 if HitFlgM #床 / 差分の移動 pos_char[y] = pos_char[y] - ySa end else #落下中 end if HitFlgU #天井 / 差分の移動 pos_char[y] = pos_char[y] + ySa end #キャラクターの当たり判定範囲(座標変化後の再設定) char_atari[x1] = pos_char[x] + char_hit[x] char_atari[y1] = pos_char[y] + char_hit[y] char_atari[x2] = char_atari[x1] + (char_hit[w] * 0.5) char_atari[y2] = char_atari[y1] + (char_hit[h] * 0.5) char_atari[x3] = char_atari[x1] + char_hit[w] char_atari[y3] = char_atari[y1] + char_hit[h] #当たり判定の座標を算出(座標変化後の再設定) charHitpos = setHitMap(char_atari, map_count) charHit_X1 = charHitpos[12] charHit_X2 = charHitpos[13] charHit_X3 = charHitpos[14] charHit_Y1 = charHitpos[15] charHit_Y2 = charHitpos[16] charHit_Y3 = charHitpos[17] charHit_Y4 = charHitpos[18] if !(HitFlgU) #壁の当たり判定 if ((charHitpos[0] != 19) || (charHitpos[3] != 19) || (charHitpos[6] != 19)) #左の壁 HitFlgLS = true #当たり判定からの差分座標を算出 xSa = char_atari[x1] + (getVariable("pos_map")[x] - ((charHit_X1 + 1) * 32)) elsif ((charHitpos[2] != 19) || (charHitpos[5] != 19) || (charHitpos[8] != 19)) #右の壁 HitFlgRS = true #当たり判定からの差分座標を算出 xSa = char_atari[x3] + (getVariable("pos_map")[x] - (charHit_X3 * 32) + 1) end #キャラクターの状態変化と差分の移動 #壁 / 差分の移動 if HitFlgRS #左へ移動 if (pos_char[x] < bg_center) || ((pos_char[x] > bg_center) && (getVariable(pos_map)[x] == map_w)) #中心線より外側 pos_char[x] = pos_char[x] - xSa if (pos_char[x] < bg_center) && (getVariable(pos_map)[x] == map_w) getVariable(pos_map)[x] = getVariable(pos_map)[x] - (bg_center - pos_char[x]) pos_char[x] = bg_center end else #中心線 getVariable(pos_map)[x] = getVariable(pos_map)[x] - xSa if getVariable(pos_map)[x] < 0 pos_char[x] = pos_char[x] + getVariable(pos_map)[x] getVariable(pos_map)[x] = 0 end end elsif HitFlgLS #右へ移動 if (pos_char[x] > bg_center) || ((pos_char[x] < bg_center) && (getVariable(pos_map)[x] == 0)) #中心線より外側 pos_char[x] = pos_char[x] - xSa if (pos_char[x] > bg_center) && (getVariable(pos_map)[x] == 0) getVariable(pos_map)[x] = getVariable(pos_map)[x] + (pos_char[x] - bg_center) pos_char[x] = bg_center end else #中心線 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 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 #キャラクターの座標を移動 setSpritePos(img_char_name, pos_char) #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #ここから↓は省略
フローの状態を判定するために、沢山のフラグや変数が登場しました。
ひとつずつ、詳しく解説します。
「HitFlgD」 キャラクターの足元の当たり判定フラグ。 着地状態であればオンになります。 「HitFlgM」 キャラクターの足元の当たり判定フラグ。 地面に埋まっている状態であればオンになります。 「HitFlgLD」 キャラクターの足元の当たり判定フラグ。 左下のみ設置しているときオンになります。 「HitFlgRD」 キャラクターの足元の当たり判定フラグ。 右下のみ設置しているときオンになります。 「HitFlgU」 キャラクターの頭上の当たり判定フラグ。 「HitFlgLU」 キャラクターの頭上の当たり判定フラグ。 左上のみ設置しているときオンになります。 「HitFlgRU」 キャラクターの頭上の当たり判定フラグ。 右上のみ設置しているときオンになります。 「HitFlgLS」 キャラクターの左側の当たり判定フラグ。 「HitFlgRS」 キャラクターの右側の当たり判定フラグ。 「xSa」 キャラクターとチップの横方向重なり差分座標。 「ySa」 キャラクターとチップの縦方向重なり差分座標。
まずはフラグ関連で当たり状態を判断し、
当たっていた場合、差分座標を計算する仕組みになっています。
最後に、差分座標をキャラクター・マップに追加しています。
ここまでで、マップの当たり判定ができました。
保存、終了をして、テストプレーを行い、
マップに接触すると立ち止まるか確認してみましょう。
02-04 ジャンプができるようにする
床の当たり判定ができましたので、
キャラクターもジャンプができるようにしてみましょう。
まずは定数・変数の準備から。
#ここから↑は省略 #キャラクターの設定 char_speed = 7 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ char_jmp_h = 40 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ char_w_max = 800 - 63; char_h_max = 600 - 80 char_anime_change = 6 #中略 char_muki = 1 char_act = act_std #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ char_jmp_count = 0 char_jmp_flg = false #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #キャラクターの当たり判定範囲 char_atari = createArray() #ここから↓は省略
「char_jmp_h」変数はキャラクターのジャンプ力
「char_jmp_count」変数はジャンプしてからの経過時間
「char_jmp_flg」変数はジャンプ中かどうかの判定に使用します
Zキーを押したときにジャンプを開始するようにします。
#ここから↑は省略 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #----- キャラクターのジャンプ ----- 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 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #----- キャラクターのアニメーション ----- #ここから↓は省略
ジャンプ中の動作をつくります。
まずはジャンプ中の座標移動。
#ここから↑は省略 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ 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 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ #----- キャラクターのアニメーション ----- #ここから↓は省略
ジャンプ時間が10を頂点に、上昇中・下降中を切り替えています。
ジャンプ時間が20以上になったとき、落下速度は固定となります。
次に、表示の切り替え。
#ここから↑は省略 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 #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ 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 if key_flg_left #左へ移動 if (pos_char[x] < bg_center) || ((pos_char[x] > bg_center) && (getVariable(pos_map)[x] == map_w)) #中心線より外側 pos_char[x] = pos_char[x] - char_speed if (pos_char[x] < bg_center) && (getVariable(pos_map)[x] == map_w) getVariable(pos_map)[x] = getVariable(pos_map)[x] - (bg_center - pos_char[x]) pos_char[x] = bg_center end else #中心線 getVariable(pos_map)[x] = getVariable(pos_map)[x] - char_speed if getVariable(pos_map)[x] < 0 pos_char[x] = pos_char[x] + getVariable(pos_map)[x] getVariable(pos_map)[x] = 0 end end #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ char_muki = 0 if char_act != act_jmp char_act = act_wrk end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ elsif key_flg_right #右へ移動 if (pos_char[x] > bg_center) || ((pos_char[x] < bg_center) && (getVariable(pos_map)[x] == 0)) #中心線より外側 pos_char[x] = pos_char[x] + char_speed if (pos_char[x] > bg_center) && (getVariable(pos_map)[x] == 0) getVariable(pos_map)[x] = getVariable(pos_map)[x] + (pos_char[x] - bg_center) pos_char[x] = bg_center end else #中心線 getVariable(pos_map)[x] = getVariable(pos_map)[x] + char_speed 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 char_muki = 1 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ if char_act != act_jmp char_act = act_wrk end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ else #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ if char_act != act_jmp char_act = act_std end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ end end #ここから↓は省略
次に、当たり判定スクリプト
#ここから↑は省略 #キャラクターの状態変化と差分の移動 if (HitFlgD || HitFlgM) && !(HitFlgLD) && !(HitFlgRD) #着地中 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #ジャンプ中の場合立ち状態に変更 if char_act == act_jmp char_act = act_std; char_jmp_count = 0 end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ if HitFlgM #床 / 差分の移動 pos_char[y] = pos_char[y] - ySa end else #落下中 #_/_/_/_/_/_/_/_/_/_/_/_/ 追加分 _/_/_/_/_/_/_/_/_/_/_/_/ #立ち状態の場合ジャンプ中に変更 if char_act != act_jmp char_act = act_jmp; char_jmp_count = 10 end #_/_/_/_/_/_/_/_/_/_/_/_/ここまで_/_/_/_/_/_/_/_/_/_/_/_/ end #ここから↓は省略
スクリプト全体
これで、一通り完成です。
保存、終了をして、テストプレーを行い、
マップの当たり判定、キャラクターのジャンプが行えるか
確認してみましょう。
02-05 おわりに
いかがでしたでしょうか。
スクリプトの量も増えてきて、一度に全体を見渡すのは難しくなってきましたが、
各処理ごとに分割して見てみると、これまでの応用であることがわかると思います。
さて、次回はキャラクター以外の要素、
「敵・アイテムを追加してみよう」を実践してみましょう。
第01回 関数を再利用してみよう
第02回 マップを表示してみよう
第03回 敵・アイテムを追加してみよう
第04回 敵の動きや背景の演出を入れてみよう
番外 外部ツールと連携してみよう
この記事についてご質問等がありましたら
こちらのブログ記事のコメントへご投稿、
よろしくお願いいたします。