【プチコン講座】ATB風バトルシステムを構築しよう:ゲームオーバー編
こんにちは。継続の錬金術士なおキーヌです。
ブログ毎日更新は156日目になります。
前回「【プチコン講座】ATB風バトルシステムを構築しよう:バトルUI編」でバトルの見た目的な要素を追加しました。
残るは結果ですね。
現在はエネミーを倒してもこちらが負けても何もなりませんでした。
PRINTで勝利か敗北かは出すようにしましたが問答無用でバトルが継続します。
これではバトルが終わらず無限ループになってしまうのでまずはゲームオーバー処理を実装しましょう。
それではプチコンでRPG作り第24回目を始めましょう。
ゲームオーバーを実装してみよう
どちらかのHPがなくなるまで戦闘は続きます。
現在はHPがなくなったらPRINTでGAMEOVERと表示するようにしていますね。
そこにゲームオーバーの処理を呼び出せばいいだけです。
ゲーム開始時にゲームオーバー用のスプライトを用意して非表示にしておきます。
D_GAMEOVER_SETUP # シーンの大元 DEF SCENE_PARENT IF G_SCENE_FLAG == 0 THEN D_CTRL_MAP_MODE ELSEIF G_SCENE_FLAG == 1 THEN IF G_EV_Q_FLAG == 0 THEN D_SHIFT_EV_DATA ELSEIF EV_Q_FLAG == 1 THEN D_EV_STOP_A_BTN ENDIF ELSEIF G_SCENE_FLAG == 2 THEN D_STATUS_MODE ELSEIF G_SCENE_FLAG == 3 THEN BATTLE_MODE ELSEIF G_SCENE_FLAG == 4 THEN D_GAMEOVER_MODE ENDIF D_MINI_STATUS_DRAW D_BTN_PRESS END # ゲームオーバーモード DEF D_GAMEOVER_MODE D_GAMEOVER_PROCESS END # ゲームオーバーセットアップ DEF D_GAMEOVEER_SETUP SPSET 100, 71 SPSET 101, 65 SPSET 102, 77 SPSET 103, 69 SPSET 104, 79 SPSET 105, 86 SPSET 106, 69 SPSET 107, 82 SPVAR 100, 1, 0 FOR G_I=100 TO 107 SPHIDE G_I IF G_I < 104 THEN SPVAR G_I, 0, 136 + (G_I-100) * (G_SZ) - (G_SZ/2) ELSE SPVAR G_I, 0, 136 + (G_I-100) * (G_SZ) + (G_SZ/2) ENDIF SPOFS G_I, SPVAR(G_I, 0), 120 SPCOLOR G_I, RGB(0,255,255,255) NEXT END # ゲームオーバー処理 DEF D_GAMEOVER_PROCESS VAR A = SPVAR(100,1) IF A <= 254 THEN INC A, 2 IF A >= 255 THEN A=255 SPVAR 100,1, A FOR G_I=100 TO 107 SPSHOW G_I SPCOLOR G_I, RGB(A,255,255,255) NEXT ENDIF IF A == 255 THEN G_CURSOR_X = 144 + 3 G_CURSOR_Y = 140 + G_SZ + (G_SZ/2) G_CURSOR_N = 0 D_WINDOW_DRAW 144, 140+G_SZ, 112, 24 GPUTCHR G_CURSOR_X+10, G_CURSOR_Y, "リトライ" GPUTCHR G_CURSOR_X+56+10, G_CURSOR_Y, "あきらめる" SPVAR 100,1, 256 BREPEAT #LEFT, 30, 5 BREPEAT #RIGHT, 30, 5 ENDIF IF A == 256 THEN GPUTCHR G_CURSOR_X, G_CURSOR_Y, "|>",RGB(0,21,151) VAR B = BUTTON(1) IF (B AND #LEFT) > 0 || (B AND #RIGHT) > 0 THEN IF G_CURSOR_ N == 0 THEN G_CURSOR_N = 1 G_CURSOR_X = G_CURSOR_X + 56 ELSE G_CURSOR_N = 0 G_CURSOR_X = G_CURSOR_X - 56 ENDIF BEEP 9, 400 ENDIF GPUTCHR G_CURSOR_X, G_CURSOR_Y, "|>",RGB(255,255,255) IF (B AND #A) > 0 THEN IF G_CURSOR_N == 0 THEN SPVAR 100,1, 257 ELSE SPVAR 100,1, 258 ENDIF ENDIF ENDIF IF A == 257 THEN ACLS D_INIT_VARIABLES G_STOP_FLAG = FALSE ELSEIF A == 258 THEN G_STOP_FLAG = FALSE ENDIF END DEF D_INIT_VARIABLES END
ちょっと長いですが、ゲームオーバー処理を一気に書いてみました。
やっていることはまず初期化のところで「D_GAMEOVER_SETUP」を呼び出しておいて、
ゲームオーバーシーンの準備をしておきます。
次に、シーン大本のところにシーンフラグが4のときにゲームオーバー処理にいくようにします。
ゲームオーバー処理について
ゲームオーバー処理は「D_GAMEOVER_PROCESS」に一気にまとめました。
やっていることは「D_GAMEOVER_SETUP」で用意したスプライトをフェードインさせます。
フェードイン用の数値は「G」のスプライト変数を利用しています。
0~255になるまでフェードイン処理を行い、スプライト変数が255を越えたら255に補正します。
255になったら完全に表示されたことになるので、コンティニュー処理の準備をし256にします。
256になったらコンティニューの選択処理を受け付けるようにし、
Aボタンが押されたら選択に応じて257か258にします。
257はコンティニューです。
最初からゲームをやり直すのですが、変数などを全て初期化しないといけません。
そのままGOTOで戻ってしまうと変数がそのままだったりで色々バグが発生します。
必ず初期化処理を行ってからリトライしましょう。
現在変数や配列の初期化はメインループが始まる前に乱雑においていますが、
「D_INIT_VARIABLES」に全てまとめてしまいましょう。
スプライト変数なんかは今回のGAMEOVERも含めその都度SPSETしてたと思いますが
本来は初期化のところで一度使用宣言をしておくべきです。
初期化関数を用意しておいて、後から出てきた初期化っぽい処理は移し替えていくといった感じがいいでしょう。
本来は設計して最初に定義しておくべきなのかとは思いますが、初心者のうちはそんなことはできないので
後から初期化処理を退避できるように準備だけしておけばよいかなと思います。
なのでゲームを作り終えるまではコンティニューの処理は後回しにします。
一旦どちらもメインループを管理しているフラグをFALSEにしてプログラムを終了させます。
ENDという命令を使ってもいいですが、せっかくループフラグを作ったのですから
フラグを消してプログラムを終了させましょう。
──エネミーを倒したりレベルアップ処理まで組み込もうと思ったのですが、
結構長くなってしまったので切り分けました。
流石にここまでくると平日に書きあげるのは難しくなりますね。
この辺の処理はやっていることは単純ですが見通しが悪くなってくるので、
いっきにやるよりこれぐらいで止めておく方が良いかもしれません。
最後に恒例のソースコードを置いておきます。
それでは。
@LABEL GAMERESET ACLS #------------------ # 変数定義 #------------------ VAR G_STOP_FLAG = TRUE # ゲームループフラグ VAR G_I # 汎用変数 # シーンフラグ VAR G_SCENE_FLAG = 0 VAR G_STATUS_FLAG = FALSE # イベント用 VAR G_EV_Q_FLAG = 0 # イベントキューがあるかどうか DIM G_EV_ID[32] # イベント用情報の配列(初回DATA読み込み用) VAR G_EV_ID_NOW = 0 # 現在のイベントナンバー VAR G_EV_STEP = 4 # 1つのイベントデータ数 DIM G_EV_QUEUE[0] # イベントキュー配列 # プレイヤー用 VAR G_PLAYER_NAME$ = "" VAR G_PLAYER_STATUS_LEN = 8 DIM G_PLAYER_STATUS[0] # ウィンドウサイズ用 VAR G_WINDOW_SIZES_LEN = 16 DIM G_WINDOW_SIZES[0] # カーソル用 VAR G_CURSOR_X = 0 VAR G_CURSOR_Y = 0 VAR G_CURSOR_N = 0 VAR G_CURSOR_POS_LEN = 3 DIM G_CURSOR_POS[0] # アイテム名用 VAR G_ITEMS_NAMES_LEN = 2 DIM G_ITEMS_NAMES[0] # システムワード VAR G_SYSTEM_WORDS_LEN = 7 DIM G_SYSTEM_WORDS[0] # エネミー用 VAR G_ENEMY_NAMES_LEN = 5 DIM G_ENEMY_NAMES[0] VAR G_ENEMY_PARAMS_LEN = 35 DIM G_ENEMY_PARAMS[0] DIM G_ENEMY_BATTLE_PARAMS[7] # メッセージ用 VAR G_MSG_DATAS_LEN = 4 DIM G_MSG_DATAS[0] # ボタン分の配列を用意 DIM G_BTN_PRESS_COUNT[13] # 全ボタンカウント配列 FILL G_BTN_PRESS_COUNT,0 # 一応定義したボタン配列を0で初期化しておく # BG関連 VAR G_OX = 0, G_OY = 0 # BG読み込みのオフセット VAR G_SZ=16, G_MW, G_MH # チップサイズ、マップ幅、マップ高さ VAR G_BGW = CEIL(400/G_SZ), G_BGH = CEIL(240/G_SZ) # BG読み込み準備 DIM G_MAP[0] # マップレイヤー4枚+イベントレイヤー分 # スプライト用 VAR G_SP_PLAYER = 0 # PLAYERスプライトNo. DIM G_SP_ANIM_NO[9] # スプライトアニメーション初期値変数 添え字=ID # バトル用 DIM G_BATTLE_STATUS[16] DIM G_BATTLE_GUARD_FLAG[2] #------------------ # データベース定義 #------------------ # 開始時に読み込むDATA軍(ラベル付けたほうが安全かもしれない DATA 500,1040,920,1000,980,1020,269,269,269 DATA 1,5,5,2, 2,23,13,2, 3,4,11,2, 4,13,3,2, 5,22,4,2 DATA 6,6,7,1, 7,3,11,1, 8,22,3,1 # コウモリイベントデータ @EVENT001 DATA 3, 4,1,0, 3,1,0, 0,1,1 @EVENT001_1 DATA 1, 0,0,0 # 宝箱イベントデータ @EVENT006 DATA 7, 10,95,400 3,1,268 2,0,1 1,1,0, 10,12,0 1,2,0, 0,1,1 @EVENT006_1 DATA 2, 1,3,0, 0,0,0 # プレイヤー初期ステータス @PLAYER_INIT_STATUS DATA 1,20,20,3,2,3,0,1 # ウィンドウサイズ用 @WINDOWSIZE DATA 80,150,240,58, 10,10,112,77, 10,10,80,50, 208,-32,167,42 # カーソル用 @SELECTDATA DATA 3,5,15 # ゲームオーバー用 D_GAMEOVER_SETUP # エネミーパラメータ用 @ENEMYPARAMS DATA 1,4,3,1,3,2,20 DATA 2,8,3,1,3,2,20 DATA 3,12,3,1,3,2,20 DATA 4,16,3,1,3,2,20 DATA 5,30,3,1,3,2,20 # ステータスウィンドウ用ワード @SYSTEMWORD DATA "Lv", "HP", "こうげき", "ぼうぎょ", "すばやさ", "けいけんち", "ポーション" # アイテム名リスト @ITEMDATA DATA "ライフポーション", "せいすい" # モンスター名リスト @ENEMYNAME DATA "リトルバット", "ゴブリン", "スケルトン", "マミー", "ゴースト" # 定型文リスト @MESSAGEDATA DATA "は たからばこを あけた", "たからばこ には", "が はいっていた!", "からっぽ!" # アニメーション配列初期値代入 D_FIRST_DATA_READ G_SP_ANIM_NO # イベントID,X座標,Y座標代入 D_FIRST_DATA_READ G_EV_ID # マップデータ準備 LOAD "DAT:TEST", G_MAP, 0 # マップデータのロード G_MW = SHIFT(G_MAP) # 読み込んだデータ配列の0個目を配列から切り離して取得(1638415という数字が入ってる) G_MH = G_MW AND &HFFFF : G_MW = G_MW >> 16 AND &HFFFF # 取り出したデータからシフト演算やらビット演算をする # マップデータ描写 FOR G_I=0 TO 3 BGSCREEN G_I, G_BGW, G_BGH, G_SZ # 1画面分のBG BGOFS 0,0,4-G_I BGLOAD I, -G_OX, ( -G_OY - ( G_I * G_MH )), G_MW, G_MH * ( G_I + 1 ), G_MAP # マップ描写 NEXT # プレイヤー配置 D_SP_SETUP G_SP_PLAYER, 1, 0 # イベント配置 FOR G_I=0 TO LEN(G_EV_ID)-1 STEP G_EV_STEP D_SP_SETUP G_EV_ID[G_I], G_EV_ID[G_I+1], EV_ID[G_I+2] NEXT # 配列初期化 FILL G_ENEMY_BATTLE_PARAMS, 0 FILL G_BATTLE_GUARD_FLAG, 0 # 各種データの読み込み D_DB_LOAD 0, G_PLAYER_STATUS_LEN, G_PLAYER_STATUS D_DB_LOAD,1, G_WINDOW_SIZES_LEN, G_WINDOW_SIZES D_DB_LOAD 2, G_CURSOR_POS_LEN, G_CURSOR_POS D_DB_LOAD 3, G_ENEMY_PARANS_LEN, G_ENEMY_PARANS D_DB_LOAD 4, G_SYSTEM_WORDS_LEN, G_SYSTEM_WORDS D_DB_LOAD 5, G_ITEM_NAMES_LEN, G_ITEM_NAMES D_DB_LOAD 6, G_ENEMY_NAMES_LEN, G_ENEMY_NAMES D_DB_LOAD 7, G_MSG_DATAS_LEN, G_MSD_DATAS # グラフィック画面を一番手前に GPRIO 0 # ゲームループ WHILE G_STOP_FLAG D_SCENE_PARENT VSYNC 1 WEND # シーンの大元 DEF SCENE_PARENT IF G_SCENE_FLAG == 0 THEN D_CTRL_MAP_MODE ELSEIF G_SCENE_FLAG == 1 THEN IF G_EV_Q_FLAG == 0 THEN D_SHIFT_EV_DATA ELSEIF EV_Q_FLAG == 1 THEN D_EV_STOP_A_BTN ENDIF ELSEIF G_SCENE_FLAG == 2 THEN D_STATUS_MODE ELSEIF G_SCENE_FLAG == 3 THEN BATTLE_MODE ELSEIF G_SCENE_FLAG == 4 THEN D_GAMEOVER_MODE ENDIF D_MINI_STATUS_DRAW D_BTN_PRESS END # マップ用コントローラー関数 DEF D_CTRL_MAP_MODE IF SPVAR(SP_PLAYER, 2) != 1 THEN VAR B = BUTTON() IF (B AND #UP) > 0 THEN IF D_CHECK_COLLISION(G_SP_PLAYER, #UP) == 1 THEN D_DIRECTION_MOVE SP_PLAYER, #UP ENDIF ELSEIF (B AND #DOWN) > 0 THEN IF D_CHECK_COLLISION(G_SP_PLAYER, #DOWN) == 1 THEN D_DIRECTION_MOVE SP_PLAYER, #DOWN ENDIF ELSEIF (B AND #LEFT) > 0 THEN IF D_CHECK_COLLISION(G_SP_PLAYER, #LEFT) == 1 THEN D_DIRECTION_MOVE SP_PLAYER, #LEFT ENDIF ELSEIF (B AND #RIGHT) > 0 THEN IF D_CHECK_COLLISION(G_SP_PLAYER, #RIGHT) == 1 THEN D_DIRECTION_MOVE SP_PLAYER, #RIGHT ENDIF ENDIF ELSE D_GRID_MOVE SP_PLAYER, (SPVAR SP_PLAYER, 3) ENDIF # 移動中もボタンを押せるようにしておく IF G_BTN_PRESS_COUNT[4] == 1 THEN PRINT "Aボタンが押されたよ!" D_EV_CHECK G_SP_PLAYER SPVAR(G_SP_PLAYER, 3) ENDIF IF G_BTN_PRESS_COUNT[6] == 1 THEN PRINT "Xボタンが押されたよ!" G_SCENE_FLAG = 2 ENDIF END # 向きと移動フラグを設定 DEF D_DIRECTION_MOVE A_SPRITE_NO, A_SPRITE_DIRECTION SPVAR A_SPRITE_NO, 2, 1 SPVAR A_SPRITE_NO, 3, A_DIRECTION END # 向いている方向に止まるまで歩き続ける(グリッド移動) DEF D_GRID_MOVE SPRITE_NO, SPRITE_DIRECTION # 渡されたスプライトと向きによって移動方向を決定 IF SPRITE_DIRECTION == #UP THEN SPVAR SPRITE_NO, 1, (SPVAR SPRITE_NO, 1) - 1 ELSEIF SPRITE_DIRECTION == #DOWN THEN SPVAR SPRITE_NO, 1, (SPVAR SPRITE_NO, 1) + 1 ELSEIF SPRITE_DIRECTION == #LEFT THEN SPVAR SPRITE_NO, 0, (SPVAR SPRITE_NO, 0) - 1 ELSEIF SPRITE_DIRECTION == #RIGHT THEN SPVAR SPRITE_NO, 0, (SPVAR SPRITE_NO, 0) + 1 ENDIF # 移動させる SPOFS SPRITE_NO,(SPVAR SPRITE_NO, 0),(SPVAR SPRITE_NO, 1) # 割った余りが0になったら動きを止める IF (SPVAR SPRITE_NO, 0) MOD G_SZ == 0 && (SPVAR G_SPRITE_NO, 1) MOD G_SZ == 0 THEN SPVAR G_SPRITE_NO, 2, 0 ENDIF END # ドット座標からグリッド座標に変換 DEF D_GET_GRID_XY(A_X_OR_Y) RETURN A_X_OR_Y / G_SZ END # MAP配列のどこにいるかチェック DEF D_GET_MAP_POSITION(A_X, A_Y, A_LAYER) VAR RETURN_POS = 0 VAR GRID_X = D_GET_GRID_XY(A_X) VAR GRID_Y = D_GET_GRID_XY(A_Y) VAR PULS_LAYER = (G_MW * G_MH) * A_LAYER IF A_Y <= 0 THEN RETURN_POS = GRID_X + PLUS_LAYER ELSE RETURN_POS = (GRID_X + (GRID_Y * G_MW)) + PLUS_LAYER ENDIF RETURN RETURN_POS END # 当たり判定チェック DEF D_CHECK_COLLISION(A_NO, A_DIRECTION) VAR MP1_SUM_POS = 0 VAR EV_SUM_POS = 0 VAR DIRECT = D_GET_DIRECT_POINT(A_DIRECTION) VAR MAP_POS = D_GET_MAP_POSITION(SPVAR(A_NO,0), SPVAR(A_NO,1), 1) VAR EVENT_POS = D_GET_MAP_POSITION(SPVAR(A_NO,0), SPVAR(A_NO,1), 3) MP1_SUM_POS = MAP_POS + DIRECT EV_SUM_POS = EVENT_POS + DIRECT IF G_MAP[MP1_SUM_POS] == 0 THEN IF G_MAP[EV_SUM_POS] == 0 THEN D_EV_LAYER_REWRITE A_NO, A_DIRECTION, 1 RETURN 1 ELSE RETURN 0 ENDIF ELSE RETURN 0 ENDIF END # スプライトセットアップ DEF D_SP_SETUP A_NO, A_X, A_Y VAR F = 20 VAR ANIM = G_SP_ANIM_NO[A_NO] SPSET A_NO ANIM SPVAR A_NO 0, G_SZ * A_X SPVAR A_NO 1, G_SZ * A_Y SPVAR A_NO 2, 0 SPVAR A_NO 3, #DOWN SPOFS A_NO SPVAR(A_NO,0), SPVAR(A_NO,1),1 D_EV_LAYER_REWRITE A_NO, 0, 1 IF A_NO == 0 || G_EV_ID[(G_EV_STEP * A_NO)-1] == 2 THEN SPANIM A_NO, "I", F,ANIM, F,ANIM+1, F,ANIM+2, F,ANIM+3, 0 ENDIF END # イベントレイヤー書き換え DEF D_EV_LAYER_REWRITE A_NO, A_DIRECT, A_FLAG VAR POS = D_GET_MAP_POSITION(SPVAR(A_NO,0), SPVAR(A_NO,1), 3) IF A_FLAG > 0 THEN IF A_DIRECT > 0 THEN VAR AFTER_POS = POS + D_GET_DIRECT_POINT(A_DIRECT) G_MAP[AFTER_POS] = A_NO ELSE G_MAP[POS] = A_NO ENDIF ELSE VAR BEFORE_POS = POS - D_GET_DIRECT_POINT(A_DIRECT) G_MAP[BEFORE_POS] = 0 ENDIF END # 方向定数から1歩前のグリッド座標を得るための値を得る DEF D_GET_DIRECT_POINT(A_DIRECTION) IF A_DIRECTION == #UP THEN RETURN DIRECT = -MW ELSEIF A_DIRECTION == #DOWN THEN RETURN DIRECT = MW ELSEIF A_DIRECTION == #LEFT THEN RETURN DIRECT = -1 ELSEIF A_DIRECTION == #RIGHT THEN RETURN DIRECT = 1 ENDIF END # DATA初期読み込み DEF D_FIRST_DATA_READ A_ARRAY FOR G_I=0 TO LEN(G_EV_ID)-1 VAR N=0: READ N G_EV_ID[G_I] = N NEXT END # ボタンカウント関数 DEF D_BTN_PRESS_COUNT VAR B = BUTTON() # Aボタンカウント IF (B AND #A) > 0 THEN IF G_BTN_PRESS_COUNT[4] < 255 THEN INC G_BTN_PRESS_COUNT[4] ENDIF ELSE # 1回でも離されたらカウントリセット G_BTN_PRESS_COUNT[4] = 0 ENDIF # Xボタンカウント IF (B AND #X) > 0 THEN IF G_BTN_PRESS_COUNT[6] < 255 THEN INC G_BTN_PRESS_COUNT[6] ENDIF ELSE # 1回でも離されたらカウントリセット G_BTN_PRESS_COUNT[6] = 0 ENDIF # Yボタンカウント IF (B AND #Y) > 0 THEN IF G_BTN_PRESS_COUNT[7] < 255 THEN INC G_BTN_PRESS_COUNT[7] ENDIF ELSE # 1回でも離されたらカウントリセット G_BTN_PRESS_COUNT[7] = 0 ENDIF END # 前方のイベントをチェックする DEF D_EV_CHECK A_NO A_DIRECT VAR POS = D_GET_MAP_POSITION(SPVAR(A_NO,0), SPVAR(A_NO,1), 3) VAR AFTER_POS = POS + D_GET_DIRECT_POINT(A_DIRECT) VAR EV_ID = G_MAP[AFTER_POS] D_GET_EV_DATA EV_ID END # イベントリストからイベントキューへ挿入 DEF D_GET_EV_DATA A_ID D_EV_SELECT_ A_ID IF LEN(G_EV_QUEUE) > 0 THEN G_EV_ID_NOW = A_ID G_SCENE_FLAG = 1 ENDIF END # イベントID毎のイベントキュー作成 DEF D_EV_SELECT A_ID IF A_ID != 0 THEN # IDラベル作成 VAR LABEL$ = "@EVENT" + FORMAT$("%03D", A_ID) VAR EV_COUNT = 0 VAR EV_DATA = 0 IF SPVAR(A_ID, 4) == 0 THEN RESTORE LABEL$ ELSEIF SPVAR(A_ID, 4) == 1 THEN RESTORE LABEL$ + "_1" ENDIF READ EV_COUNT FOR G_I=1 TO (EV_COUNT * 3)-1 READ EV_DATA PUSH G_EV_QUEUE, EV_DATA NEXT ENDIF END # イベントキュー取り出し DEF D_SHIFT_EV_DATA VAR TYPE = SHIFT(G_EV_QUEUE) VAR EVENT = SHIFT(G_EV_QUEUE) VAR RESERVE = SHIFT(G_EV_QUEUE) IF TYPE== 0 THEN IF EVENT == 1 THEN SPVAR G_EV_ID_NOW, 4, RESERVE ENDIF ELSEIF TYPE == 1 THEN GCLS D_WINDOW_DRAW G_WINDOW_SIZES[0], G_WINDOW_SIZES[1], G_WINDOW_SIZES[2], G_WINDOW_SIZES[3] D_MSG_DRAW G_WINDOW_SIZES[0], G_WINDOW_SIZES[1], EVENT RESERVE G_EV_Q_FLAG = 1 ELSEIF TYPE == 2 THEN IF EVENT == 1 THEN INC G_PLAYER_STATUS[7], RESERVE ENDIF ELSEIF TYPE == 3 THEN IF EVENT == 1 THEN SPSET G_EV_ID_NOW, RESERVE ENDIF ELSEIF TYPE == 4 THEN D_BATTLE_BEFORE_SETTINGS EVENT G_SCENE_FLAG = 3 ELSEIF TYPE == 10 THEN BEEP EVENT, RESERVE ENDIF IF LEN(G_EV_QUEUE) <= 0 THEN GCLS G_SCENE_FLAG = 0 ENDIF END # ウィンドウクリエイター DEF D_WINDOW_DRAW A_X, A_Y, A_W, A_H # カラー配列を定義 VAR WC_BACK = RGB(0, 21, 151) # 背景色 VAR WC_FRAME = RGB(128,126,129) # フレーム色 VAR WC_HIGHLITE = RGB(255,255,255) # ハイライト色 # 右下を計算 VAR EX = A_W + A_X VAR EY = A_H + A_Y # 背景描写(塗りつぶし有り矩形) GFILL A_X, A_Y, EX, EY, WC_BACK # 矩形フレーム描写(塗りつぶし無し矩形) GBOX A_X-1, A_Y-1, EX+1, EY+1, WC_FRAME GBOX A_X-2, A_Y-2, EX+2, EY+2, WC_FRAME GBOX A_X-3, A_Y-3, EX+3, EY+3, WC_FRAME # ハイライトの角の部分(点) GPSET A_X-2, A_Y-2, WC_HIGHLITE GPSET A_X-2, EY+2, WC_HIGHLITE GPSET EX+2, A_Y-2, WC_HIGHLITE GPSET EX+2, EY+2, WC_HIGHLITE # ハイライトとフレームの直線部分 GLINE A_X-3, A_Y-1, A_X-3, EY+1, WC_HIGHLITE GLINE A_X-4, A_Y-1, A_X-4, EY+1, WC_FRAME GLINE EX+3, A_Y-1, EX+3, EY+1, WC_HIGHLITE GLINE EX+4, A_Y-1, EX+4, EY+1, WC_FRAME GLINE A_X-1, A_Y-3, EX+1, A_Y-3, WC_HIGHLITE GLINE A_X-1, A_Y-4, EX+1, A_Y-4, WC_FRAME GLINE A_X-1, EY+3, EX+1, EY+3, WC_HIGHLITE GLINE A_X-1, EY+4, EX+1, EY+4, WC_FRAME END # メッセージ送り用 DEF D_EV_STOP_A_BTN IF G_BTN_PRESS_COUNT[4] == 1 THEN G_EV_Q_FLAG = 0 ENDIF END # メッセージイベント DEF D_MSG_DRAW A_X, A_Y, A_EVENT A_RESERVE IF A_EVENT == 1 THEN GPUTCHR A_X+5, A_Y+5, "プレイヤー" + G_MSG_DATAS[0] ELSEIF A_EVENT == 2 THEN GPUTCHR A_X+5, A_Y+5, G_MSG_DATAS[1] + G_ITEMS_NAMES[A_RESERVE] + G_MSG_DATAS[2] ELSEIF A_EVENT == 3 THEN GPUTCHR A_X+5, A_Y+5, G_MSG_DATAS[3] ENDIF END # データベースローダー DEF D_DB_LOAD A_ID, A_LEN, A_ARY IF A_ID < 4 THEN VAR ARY_WORD = 0 ELSE VAR ARY_WORD$ = "" ENDIF IF A_ID == 0 THEN RESTORE @PLAYER_INIT_STATUS ELSEIF A_ID == 1 THEN RESTORE @WINDOWSIZE ELSEIF A_ID == 2 THEN RESTORE @SYSTEMWORD ELSEIF A_ID == 3 THEN RESTORE @ENEMYPARAMS ELSEIF A_ID == 4 THEN RESTPRE @SELECTDATA ELSEIF A_ID == 5 THEN RESTORE @ITEMNAME ELSEIF A_ID == 6 THEN RESTORE @ENEMYNAME ELSEIF A_ID == 7 THEN RESTPRE @MESSAGEDATA ENDIF FOR G_I=0 to A_LEN-1 IF A_ID < 4 THEN READ ARY_WORD PUSH A_ARY, ARY_WORD ELSE READ ARY_WORD$ PUSH A_ARY, ARY_WORD$ ENDIF NEXT END # ステータスウィンドウ描写 DEF D_STATUS_WINDOW_DRAW # ローカル配列定義 VAR STATUS = "" DIM WS[0] # グローバル配列の参照を格納 WS = G_WINDOW_SIZES # ウィンドウの描写 D_WINDOW_DRAW WS[4], WS[5], WS[6], WS[7] # ステータス文字の描写 FOR G_I = 0 TO G_SYSTEM_WORDS_LEN-1 # ステータス文字の描写準備 IF G_I == 0 THEN STATUS = G_SYSTEM_WORDS[G_I]+":"+ STR$(G_PLAYER_STATUS[0]) ELSEIF G_I == 1 THEN STATUS = G_SYSTEM_WORDS[G_I]+":"+ STR$(G_PLAYER_STATUS[1])+"/"+STR$(G_PLAYER_STATUS[2]) ELSEIF G_I == 2 THEN STATUS = G_SYSTEM_WORDS[G_I]+":"+ STR$(G_PLAYER_STATUS[3]) ELSEIF G_I == 3 THEN STATUS = G_SYSTEM_WORDS[G_I]+":"+ STR$(G_PLAYER_STATUS[4]) ELSEIF G_I == 4 THEN STATUS = G_SYSTEM_WORDS[G_I]+":"+ STR$(G_PLAYER_STATUS[5]) ELSEIF G_I == 5 THEN STATUS = G_SYSTEM_WORDS[G_I]+":"+ STR$(G_PLAYER_STATUS[6])+"/999" ELSEIF G_I == 6 THEN STATUS = G_SYSTEM_WORDS[G_I]+":"+ STR$(G_PLAYER_STATUS[7]) ENDIF # 実際のステータスの描写 GPUCHR WS[4]+5, WS[5]+5 + (G_I*10), STATUS NEXT END # ウィンドウトグル DEF D_STATUS_WINDOW_TOGGLE # フラグを反転させる G_STATUS_FLAG = NOT G_STATUS_FLAG # フラグによって開くか閉じるかを決める IF STATUS_FLAG THEN D_STATUS_WINDOW_DRAW ELSE GCLS ENDIF END # ステータスモード DEF D_STATUS_MODE # 初回にステータスウィンドウフラグをONにしておく IF NOT G_STATUS_FLAG THEN D_STATUS_WINDOW_TOGGLE ENDIF # Xボタン監視 IF G_BTN_PRESS_COUNT[6] == 1 THEN D_STATUS_WINDOW_TOGGLE ENDIF END # バトルシーンループ DEF BATTLE_MODE IF G_BATTLE_STATUS[15] == 0 D_BATTLE_GAUGE_LOOP D_BATTLE_GUAGE_GRAPH D_BATTLE_ENEMY_ACTION D_BATTLE_SELECT_COMMAND D_BATTLE_ATTACK D_BATTLE_PLAYER_FLASH ELSE G_BATTLE_STATUS[15] == 1 D_BATTLE_WINNER D_BATTLE_RESULT ENDIF END # ゲージループ DEF D_BATTLE_GAUGE_LOOP # プレイヤーゲージ IF G_BATTLE_STATUS[0] < 180 THEN INC G_BATTLE_STATUS[0] ELSEIF G_BATTLE_STATUS[2] == 0 THEN BEEP 7, 600 INC G_BATTLE_STATUS[2] ENDIF # エネミーゲージ IF G_BATTLE_STATUS[1] < 360 THEN INC G_BATTLE_STATUS[1] ELSEIF G_BATTLE_STATUS[3] != 0 THEN BEEP 7, 600 INC G_BATTLE_STATUS[3] ENDIF END # ゲージグラフィック表示 DEF D_BATTLE_GUAGE_GRAPH # 背景として下地を黒く塗りつぶす GFILL SPVAR(0,0)-2, SPVAR(0,1)+G_SZ+2, SPVAR(0,0)+G_SZ+2, SPVAR(0,1)+G_SZ+5, RGB(255,255,255) GFILL SPVAR(0,0)-1, SPVAR(0,1)+G_SZ+1, SPVAR(0,0)+G_SZ+1, SPVAR(0,1)+G_SZ+4, RGB(0,0,0) VAR INC_GUAGE = FLOOR( G_BATTLE_STATUS[0] / 180 * G_SZ ) GLINE SPVAR(0,0) , SPVAR(0,1)+G_SZ, SPVAR(0,0) + INC_GUAGE , SPVAR(0,1)+G_SZ+3, END # バトルゲージリセット DEF D_BATTLE_GUAGE_RESET A_ACTOR IF A_ACTOR == 0 THEN G_BATTLE_STATUS[0] = 0 G_BATTLE_STATUS[2] = 0 ELSE G_BATTLE_STATUS[1] = 0 G_BATTLE_STATUS[3] = 0 ENDIF G_BATTLE_GUARD_FLAG[A_ACTOR] END # プレイヤーの行動選択 DEF D_BATTLE_ATTACK VAR SELECT_SUCCESS = FALSE IF G_BATTLE_STATUS[2] == 1 THEN IF G_BTN_PRESS_COUNT[4] == 1 THEN IF G_CURSOR_N == 0 THEN BEEP 103, 300 D_BATTLE_DAMAGE 0 SELECT_SUCSESS = TRUE ELSE IF G_CURSOR_N == 1 THEN PRINT "ぼうぎょ!" BEEP 86, 600, 127 D_BATTLE_GUARD 0 SELECT_SUCSESS = TRUE ENDIF ELSE IF G_CURSOR_N == 2 THEN IF G_PLAYER_STATUS[7] >= 1 THEN PRINT "かいふく!" BEEP 106, 200 D_BATTLE_CURE SELECT_SUCSESS = TRUE ENDIF ENDIF IF SELECT_SUCCESS THEN GCLS D_BATTLE_GUAGE_RESET 0 G_CURSOR_N = 0 ELSE BEEP 0, -500, 127 ENDIF ENDIF ENDIF END # プレイヤーのコマンドウィンドウ表示 DEF D_BATTLE_SELECT_COMMAND DIM WS = G_WINDOW_SIZES IF G_BATTLE_STATUS[2] == 1 THEN G_BATTLE_STATUS[2] = 2 G_CURSOR_X = WS[8] + G_CURSOR_POS[0] G_CURSOR_X = WS[9] + G_CURSOR_POS[1] D_WINDOW_DRAW WS[8], WS[9], WS[10], WS[11] GPUTCHR WS[8] + G_CURSOR_POS[1] + (G_SZ/2), WS[9] + G_CURSOR_POS[0], "こうげき" GPUTCHR WS[8] + G_CURSOR_POS[1] + (G_SZ/2), WS[9] + (G_CURSOR_POS[1]*2) + (G_SZ/2), "ぼうぎょ" GPUTCHR WS[8] + G_CURSOR_POS[1] + (G_SZ/2), WS[9] + (G_CURSOR_POS[1]*3) + G_SZ, "かいふく" BREPEAT #UP, 30, 5 BREPEAT #DOWN, 30, 5 ELSEIF G_BATTLE_STATUS[2] == 2 THEN GPUTCHR G_CURSOR_X, G_CURSOR_Y, "|>",RGB(0,21,151) VAR B = BUTTON(1) IF (B AND #UP) > 0 THEN DEC G_CURSOR_Y, G_CURSOR_POS[2] DEC G_CURSOR_N IF G_CURSOR_Y < WS[9] + G_CURSOR_POS[1] THEN G_CURSOR_Y = WS[9] + G_CURSOR_POS[1] + (G_CURSOR_POS[2]*2) G_CURSOR_N = 2 ENDIF BEEP 9, 400 ELSEIF (B AND #DOWN) > 0 THEN INC G_CURSOR_Y, G_CURSOR_POS[2] INC G_CURSOR_N IF G_CURSOR_Y > WS[9] + G_CURSOR_POS[1] + (G_CURSOR_POS[2]*2) THEN G_CURSOR_Y = WS[9] + G_CURSOR_POS[1] G_CURSOR_N = 0 ENDIF BEEP 9, 400 ENDIF GPUTCHR G_CURSOR_X, G_CURSOR_Y, "|>",RGB(255,255,255) ENDIF END # 戦闘準備関数 DEF D_BATTLE_BEFORE_SETTINGS A_ID # エネミーステータス初期化 VAR ST_POS = (A_ID-1) * LEN(G_ENEMY_BATTLE_PARAMS) FOR G_I=0 TO LEN(G_ENEMY_BATTLE_PARAMS)-1 G_ENEMY_BATTLE_PARAMS[G_I] = G_ENEMY_PARAMS[ G_I + ST_POS] NEXT END # ダメージ計算 DEF D_BATTLE_DAMAGE A_ACTOR VAR DAMAGE = 0 IF A_ACTOR == 0 THEN PRINT "エネミーHP @ダメージまえ:" + STR$(G_ENEMY_BATTLE_PARAMS[1]) DAMAGE = G_PLAYER_STATUS[3] - ( G_ENEMY_BATTLE_PARAMS[3] + ( G_ENEMY_BATTLE_PARAMS[3] * G_BATTLE_GUARD_FLAG[A_ACTOR] )) ELSE PRINT "プレイヤーHP @ダメージまえ:" + STR$(G_PLAYER_STATUS[1]) DAMAGE = G_ENEMY_BATTLE_PARAMS[2] - ( G_PLAYER_STATUS[4] + ( G_PLAYER_STATUS[4] * G_BATTLE_GUARD_FLAG[A_ACTOR] )) ENDIF # 最低でもダメージは1入るようにする IF DAMAGE <= 0 THEN DAMAGE = 1 ENDIF # ダメージ保存 IF A_ACTOR == 0 THEN G_BATTLE_STATUS[4] = DAMAGE G_BATTLE_STATUS[7] = DAMAGE G_BATTLE_STATUS[8] = 1 ELSE G_BATTLE_STATUS[5] = DAMAGE G_BATTLE_STATUS[6] = DAMAGE G_BATTLE_STATUS[9] = 1 ENDIF IF A_ACTOR == 0 THEN DEC G_ENEMY_BATTLE_PARAMS[1], DAMAGE IF G_ENEMY_BATTLE_PARAMS[1] <= 0 PRINT "エネミーをたおしたぞ!" ENDIF PRINT "エネミーHP @ダメージあと:" + STR$(G_ENEMY_BATTLE_PARAMS[1]) ELSE DEC G_PLAYER_STATUS[1], DAMAGE IF G_PLAYER_STATUS[1] <= 0 PRINT "GAME OVER!" ENDIF PRINT "プレイヤーHP @ダメージあと:" + STR$(G_PLAYER_STATUS[1]) ENDIF END # ぼうぎょ関数 DEF D_BATTLE_GURAD A_ID G_BATTLE_GUARD_FLAG[A_ID] = 1 END # かいふく関数 DEF D_BATTLE_CURE DEC G_PLAYER_STATUS[7] G_PLAYER_STATUS[1] = G_PLAYER_STATUS[2] END # エネミーの行動選択 DEF D_BATTLE_ENEMY_ACTION IF G_BATTLE_STATUS[3] == 1 THEN VAR ACTION_NUM = RND(10) IF ACTION_NUM < 8 THEN PRINT "エネミーのこうげき!" BEEP 40, 200 D_BATTLE_DAMAGE 1 SPCOLOR 0, RGB(255,0,0) G_BATTLE_STATUS[13] = 10 ELSE PRINT "エネミーのぼうぎょ!" D_BATTLE_GUARD 1 ENDIF D_BATTLE_GUAGE_RESET 1 ENDIF END # ミニウィンドウ表示 DEF D_MINI_STATUS_DRAW # ローカル配列定義 DIM WS[0] # グローバル配列の参照を格納 WS = G_WINDOW_SIZES # ウィンドウの描写 D_WINDOW_DRAW WS[12], WS[13], WS[14], WS[15] # HPの表示 GPUTCHR WS[12]+5, WS[13]+34, G_SYSTEM_WORDS[1]+":"+ STR$(G_PLAYER_STATUS[1])+"/"+STR$(G_PLAYER_STATUS[2]) # ポーションの表示 GPUTCHR WS[12]+5+80, WS[13]+34, G_SYSTEM_WORDS[6]+":"+ STR$(G_PLAYER_STATUS[7])+"/10" END # ダメージポップアップ DEF D_BATTLE_POPUP_DAMAGE IF G_BATTLE_STATUS[8] == 0 THEN GFILL SPVAR(G_EVENT_ID_NOW, 0) + (G_SZ/4), SPVAR(G_EVENT_ID_NOW, 1) - (G_SZ/2),(G_EVENT_ID_NOW, 0) + G_SZ, SPVAR(G_EVENT_ID_NOW, 1), RGB(0,0,0,0) G_BATTLE_STATUS[10] = 0 ELSE G_BATTLE_STATUS[8] == 1 THEN GFILL SPVAR(G_EVENT_ID_NOW, 0) + (G_SZ/4), SPVAR(G_EVENT_ID_NOW, 1) - (G_SZ/2),(G_EVENT_ID_NOW, 0) + G_SZ, SPVAR(G_EVENT_ID_NOW, 1), RGB(0,0,0,0) GPUTCHR SPVAR(G_EVENT_ID_NOW, 0) + (G_SZ/4), SPVAR(G_EVENT_ID_NOW, 1) - G_SZ, A_DAMAGE ENDIF D_BATTLE_POP_DAMAGE_COUNT END # ダメージポップアップカウント DEF D_BATTLE_POP_DAMAGE_COUNT IF G_BATTLE_STATUS[8] == 1 THEN G_BATTLE_STATUS[8] = 2 ENDIF IF G_BATTLE_STATUS[8] == 2 THEN INC G_BATTLE_STATUS[10] IF G_BATTLE_STATUS[10] > 60 THEN G_BATTLE_STATUS[8] = 0 ENDIF ENIDF END # プレイヤーフラッシュ DEF D_BATTLE_PLAYER_FLASH IF G_BATTLE_STATUS[13] > 0 THEN DEC G_BATTLE_STATUS[13] IF G_BATTLE_STATUS[13] > 0 THEN SPCOLOR 0, RGB(255,(255/G_BATTLE_STATUS[13]),(255/G_BATTLE_STATUS[13])) ELSE SPCOLOR 0, RGB(255,255,255) ENDIF ENDIF END # ゲームオーバーモード DEF D_GAMEOVER_MODE D_GAMEOVER_PROCESS END # ゲームオーバーセットアップ DEF D_GAMEOVEER_SETUP SPSET 100, 71 SPSET 101, 65 SPSET 102, 77 SPSET 103, 69 SPSET 104, 79 SPSET 105, 86 SPSET 106, 69 SPSET 107, 82 SPVAR 100, 1, 0 FOR G_I=100 TO 107 SPHIDE G_I IF G_I < 104 THEN SPVAR G_I, 0, 136 + (G_I-100) * (G_SZ) - (G_SZ/2) ELSE SPVAR G_I, 0, 136 + (G_I-100) * (G_SZ) + (G_SZ/2) ENDIF SPOFS G_I, SPVAR(G_I, 0), 120 SPCOLOR G_I, RGB(0,255,255,255) NEXT END # ゲームオーバー処理 DEF D_GAMEOVER_PROCESS VAR A = SPVAR(100,1) IF A <= 254 THEN INC A, 2 IF A >= 255 THEN A=255 SPVAR 100,1, A FOR G_I=100 TO 107 SPSHOW G_I SPCOLOR G_I, RGB(A,255,255,255) NEXT ENDIF IF A == 255 THEN G_CURSOR_X = 144 + 3 G_CURSOR_Y = 140 + G_SZ + (G_SZ/2) G_CURSOR_N = 0 D_WINDOW_DRAW 144, 140+G_SZ, 112, 24 GPUTCHR G_CURSOR_X+10, G_CURSOR_Y, "リトライ" GPUTCHR G_CURSOR_X+56+10, G_CURSOR_Y, "あきらめる" SPVAR 100,1, 256 BREPEAT #LEFT, 30, 5 BREPEAT #RIGHT, 30, 5 ENDIF IF A == 256 THEN GPUTCHR G_CURSOR_X, G_CURSOR_Y, "|>",RGB(0,21,151) VAR B = BUTTON(1) IF (B AND #LEFT) > 0 || (B AND #RIGHT) > 0 THEN IF G_CURSOR_ N == 0 THEN G_CURSOR_N = 1 G_CURSOR_X = G_CURSOR_X + 56 ELSE G_CURSOR_N = 0 G_CURSOR_X = G_CURSOR_X - 56 ENDIF BEEP 9, 400 ENDIF GPUTCHR G_CURSOR_X, G_CURSOR_Y, "|>",RGB(255,255,255) IF (B AND #A) > 0 THEN IF G_CURSOR_N == 0 THEN SPVAR 100,1, 257 ELSE SPVAR 100,1, 258 ENDIF ENDIF ENDIF IF A == 257 THEN ACLS D_INIT_VARIABLES G_STOP_FLAG = FALSE ELSEIF A == 258 THEN G_STOP_FLAG = FALSE ENDIF END # 初期化処理 DEF D_INIT_VARIABLES END