【プチコン講座】ATB風バトルシステムを構築しよう:コマンド選択編
こんにちは。継続の錬金術士なおキーヌです。
ブログ毎日更新は153日目になります。
前回「【プチコン講座】ATB風バトルシステムを構築しよう:コマンド作成編」でバトルに使うコマンドを表示しました。
バトルシステム構築は選択肢のカーソルを動かすところまでやりましたが、まだYボタンでゲージリセットするぐらいしかしていません。
こうげき・ぼうぎょ・かいふくと3つのコマンドがありますが、一番手間がかかるのはこうげきです。
こうげきが終わってしまえばあとは分岐で防御力補正をかけるかHPを回復するかなので、
基本的なものは攻撃の処理で作り終えます。
それではプチコンでRPG作り第21回目を始めましょう。
エネミーの能力データベースを構築しよう
戦闘するにもエネミーの能力がないと何もできませんね。
まずはエネミーそれぞれのパラメータを設定します。
やり方はデータベースでパラメーターを作り、ここからここまでの数値は1匹目のエネミーという風にし、
IDによって参照する配列を決めればOKです。
まずは画面上にいるエネミーのパラメーターを定義してみましょう。
一旦はテキトーでいいです。
実際に戦ってみてからバランス調整でいいでしょう。
設定する値は
「Lv」「HP」「こうげき」「ぼうぎょ」「すばやさ」「倒したときの経験値」「ドロップアイテムの確率」
一旦これだけあればゲームらしくはなるかと思います。
Lvは今回なくてもいいのですが、例えばコウモリが2匹居て違う能力にしたい場合はLvで補正をかけてあげればいいですね。
プレイヤーはMAXHPがありますが、エネミーの場合は初期値がMAXHPなので戦闘開始時設定すればOKです。
# エネミーパラメーター変数
VAR G_ENEMY_PARAMS_LEN = 35
DIM G_ENEMY_PARAMS[0]
# エネミーパラメータ用
@ENEMYPARAMS
DATA 1,30,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
# 各種データの読み込み
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
# データベースローダー
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
数値データベースを追加すると変更点が多いので、毎回変更するのが面倒臭いですね。
本来はちゃんと設計して作っていれば楽なのですが、私の設計の未熟さが仇にになっています。
多くてもあと2回あるかないかの作業なので最適化は完成後でもいいかもですね。
直ぐに出来そうな人はやってみるとプログラミング力が向上しますよ!
一度問題なく動くか確かめてみましょう。
エラーがでたらどこがまちがっているのか探すのもプログラミングの勉強の1つです。
プログラミングなんて8割がエラーみたいなもんですから、
エラー解決能力が身に付けば色んなものを作ることが出来ます。
問題なく実行出来たら、設定したパラメーターを使ってバトルを構築しましょう。
戦闘開始時にエネミーのパラメーターを設定する
何度も言いますが、プチコンにはクラスという概念がないので
継続しておきたい値はグローバル変数に記憶しておく必要があります。
基本的にこのゲームは1:1のバトルになるのでパラメーター分の配列を用意すればいいですね。
バトル開始前にその配列にデータベースからIDに対応する位置から値を取得すればOKです。
まずはエネミーパラメータ保持用のグローバル変数を作りましょう。
プチコンではいらないかもしれませんが一応念のため、初期化のところで配列をすべて0にしておきましょう。
FILL 配列名, 全ての配列に入れたい数
で初期化できます。
他のプログラミング言語だと配列を定義して中身を参照しようとしたとき、
何もないとエラーを吐くものもあるので、お作法としての初期化です。
言語によっては定義したらすべて0が入ったりするものもあります。
DIM G_ENEMY_BATTLE_PARAMS[7]
FILL G_ENEMY_BATTLE_PARAMS, 0
各エネミーのパラメーターは7つあるので配列の数を7で定義しました(0~6)
そして一応中身を0で初期化しています。
エネミーパラメーターの設定タイミング
イベントを調べた時にエネミーIDがわかるので、バトル突入前にバトル準備イベントを設けます。
まずはバトル前に呼ばれる戦闘準備の関数を作ってみましょう。
# 戦闘準備関数
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
やってることは引数にイベントIDをとって……と思ったのですが
そうすると宝箱のイベントが間に割り込んでいた場合、後ろの方のエネミーが定義外になってしまいます。
なのでイベントを設定する時にイベント値にエネミーIDを設定するようにしましょう。
そうすれば好きなエネミーに好きなパラメーターを設定することが出来ます。
これも設計ミスな感じは否めませんが、まぁいいでしょう。
それではこの関数を使ってバトルイベントの時に呼ばれるようにしてみましょう。
コウモリイベントを作ったときにバトルの2つ目にエネミーIDを設定していましたが、
今は特に何もしていないので活用してみましょう。
# イベントキュー取り出し
DEF D_SHIFT_EV_DATA
~~~ 省略 ~~~
IF TYPE== 0 THEN
~~~ 省略 ~~~
ELSEIF TYPE == 1 THEN
~~~ 省略 ~~~
ELSEIF TYPE == 2 THEN
~~~ 省略 ~~~
ELSEIF TYPE == 3 THEN
~~~ 省略 ~~~
ELSEIF TYPE == 4 THEN
D_BATTLE_BEFORE_SETTINGS EVENT
G_SCENE_FLAG = 3
ELSEIF TYPE == 10 THEN
~~~ 省略 ~~~
ENDIF
~~~ 省略 ~~~
END
これでグローバル変数にモンスターのステータスを取得してバトルシーンに入ることが出来ました。
後はバトルシーン側で数値を変更したり表示したりしましょう。
エネミーのHPを攻撃で減らしていこう
現在行動ゲージが溜まってYボタンを押すと攻撃音がなってゲージがリセットされますね。
YボタンからAボタンに変えます。
そして、攻撃を選んだ時だけ音がなるようにしてエネミーのHPを減らしてみましょう。
まだGUIを作っていないので一旦表示はPRINTでいいでしょう。
# プレイヤーの攻撃
DEF D_BATTLE_ATTACK
IF G_BATTLE_STATUS[2] == 1 THEN
IF G_BTN_PRESS_COUNT[4] == 1 THEN
GCLS
BEEP 103, 300
D_BATTLE_DAMAGE 0
D_BATTLE_GUAGE_RESET 0
ENDIF
ENDIF
END
# ダメージ計算
DEF D_BATTLE_DAMAGE A_ACTOR
PRINT "============"
PRINT "ダメージ前のエネミーHP:" + STR$(G_ENEMY_BATTLE_PARAMS[1])
PRINT "------------"
# ダメージ計算(こうげき - ぼうぎょ)
VAR DAMAGE = G_PLAYER_STATUS[3] - G_ENEMY_BATTLE_PARAMS[3]
# 最低でもダメージは1入るようにする
IF DAMAGE <= 0 THEN
DAMAGE = 1
ENDIF
# 実際の計算
DEC G_ENEMY_BATTLE_PARAMS[1], DAMAGE
# HPが0以下になったらメッセージを出しておく
IF G_ENEMY_BATTLE_PARAMS[1] <= 0
PRINT "@@@@@@@@@@@"
PRINT "エネミーをたおしたぞ!"
PRINT "@@@@@@@@@@@"
ENDIF
PRINT "ダメージ後のエネミーHP:" + STR$(G_ENEMY_BATTLE_PARAMS[1])
END
攻撃音を出している関数のところでダメージ計算の関数を作って呼び出しました。
分かりやすいようにダメージ前と後の数値をPRINTしておきましょう。
そして文字が見辛いので攻撃時にGCLSでコマンドウィンドウを一旦消します。
HPが無くなったことが分かるようにもしています。
ダメージ計算の関数の引数には「誰が攻撃するか」を取っています。
0がプレイヤーで1がエネミーにしましょうか。
今はプレイヤーだけしか攻撃しないので使っていませんが、
エネミーの処理を作るときに使うので設定しておいてください。
それでは攻撃しにいってみましょう。
今はどのコマンドを選んでも攻撃出来ますが、数値上ではコウモリを倒せたのではないでしょうか?
これではまだまだクソゲーの部類というかゲームにすらなっていませんが、エネミーを倒すことが出来ました。
今のところ攻撃ー防御のダメージが一定なのでここに乱数を加えるとダメージのブレ幅を実装出来ます。
ゲームに乱数というのはすごく大切で、乱数がないバトルは正直バトル開始時で勝敗が決まってしまいます。
乱数を設けることでランダム性をだし、ロマンシングなバトルを表現できます。
……最初の頃に比べるとバトルの攻撃まで実装できたので大きな進歩ですね!
プログラミングも人生も小さな積み重ねが大事です。
ぼうぎょ・かいふくの実装
基本的な攻撃が実装出来たので、次はぼうぎょとかいふくの実装をします。
まずは今のところどのコマンドを選択しても攻撃になってしまっているので、
選べるように変更しましょう。
前回の記事でカーソルは座標ではなく別の数値で管理することをやりました。
……と思ってコードを見返したら「G_CURSOR_N=0」だけ定義して実装していませんでした。
なので実装してみましょう。
やることはカーソルの位置変更の時に数値を1だけインクリメントするかデクリメントするかです。
-1になったときやコマンド以上の数値になってしまったときは、
座標と同じようにちゃんと補正してあげましょう。
# プレイヤーのコマンドウィンドウ表示
DEF D_BATTLE_SELECT_COMMAND
DIM WS = G_WINDOW_SIZES
IF G_BATTLE_STATUS[2] == 1 THEN
~~~ 省略 ~~~
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
これで現在どこのカーソルにいるのかを座標ではなく「G_CURSOR_N」を参照すれば数値で判断できるようになりました。
これを使って攻撃関数を書き換えてみましょう。
# プレイヤーの行動選択
DEF D_BATTLE_ATTACK
IF G_BATTLE_STATUS[2] == 2 THEN
IF G_BTN_PRESS_COUNT[4] == 1 THEN
IF G_CURSOR_N == 0 THEN
BEEP 103, 300
D_BATTLE_DAMAGE 0
ELSE IF G_CURSOR_N == 1 THEN
BEEP 86, 600, 127
D_BATTLE_GUARD 0
ENDIF
ELSE IF G_CURSOR_N == 2 THEN
BEEP 106, 200
D_BATTLE_CURE
ENDIF
GCLS
D_BATTLE_GUAGE_RESET 0
G_CURSOR_N = 0
ENDIF
ENDIF
END
ゲージが溜まったときに決定ボタンを押すと現在のカーソルの位置に応じて処理を分岐させました。
GCLSとゲージリセットは共通しているので分岐から外しています。
これでガードと回復の関数を作れば実装完了ですね。
ただ、現段階ではカーソルの位置が記憶されたままで次のターンになったときに
前回のカーソルの位置が記憶されたままなのにカーソルはリセットされているので直さなければいけません。
ここでカーソル位置を記憶しておくか、カーソル位置を元に戻すかは好みの問題です。
FFなんかはコンフィグでカーソル位置記憶と初期化両方用意してくれてますね。
今回は記憶が面倒なので、決定を押したときにカーソル位置をリセットするようにしておきました。
ゲージリセット関数の下においてある代入がそうです。
それでは次にぼうぎょ関数を作ってみましょう
ぼうぎょ関数をつくる
ぼうぎょ関数を実行して次の行動ゲージが溜まるまでは一時的に防御力を2倍アップするようにしたいです。
実際に行動者の防御力の数値をあげるのではなく、
ダメージを受けるときに防御フラグがオンになっていれば計算式を変えるイメージです。
今回はまだエネミーの攻撃を実装していないので効果はわかりませんが、フラグをONにするだけにしましょう。
行動ゲージが溜まったらフラグをOFFにするのを忘れないようにしましょう。
ガードフラグ用の配列を作って0をプレイヤー、1をエネミーにしましょう。
DIM G_BATTLE_GUARD_FLAG[2]
FILL G_BATTLE_GUARD_FLAG, 0
DEF D_BATTLE_GURAD A_ID
G_BATTLE_GUARD_FLAG[A_ID] = 1
END
かいふく関数をつくる
続いてかいふく関数を作ります。
かいふくは無制限では面白くないので、ポーションを持っているときだけ回復するようにします。
プレイヤーのステータスにポーションの所持数は設定していますね。
あれを使って判断します。
後、エネミーの場合はポーションの保持数概念がないのでかいふくをさせないか無制限に回復すかになります。
エネミーの回復を制限するには、例えば魔法で回復させる場合MPの概念が必要になります。
それを制御するかんじですね。
チュートリアルなので複雑になるのを避けたいので、エネミー側は基本的に回復なしで進めます。
DEF D_BATTLE_CURE
DEC G_PLAYER_STATUS[7]
G_PLAYER_STATUS[1] = G_PLAYER_STATUS[2]
END
やっていることはポーションの数を減らして、現在HPを最大HPの数値に置き換えます。
ポーションは完全回復するようにしておくか、一定数値を回復するかは自由です。
一旦簡単にしたいので、HPを最大まで回復せておきます。
先ほども言ったようにこのままではポーションが無限に使えてしまうので、
行動選択時にポーションの数を監視して1以上だったら使えるようにしましょう。
# プレイヤーの行動選択
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
普通にやってしまうとポーションがない時にかいふくをおしてしまうと、
回復せずに行動が終わってしまうのは理不尽なのでコマンド成功フラグを設けました。
SELECT_SUCCESSがTRUEであれば行動したことにすれば大丈夫です。
行動失敗の時はブザー音でもならすとわかりやすいでしょう。
一度実行してみましょう。
ぼうぎょとかいふくは効果の反映がまだわからないので、効果音で判断しましょう。
何回かやってみてカーソルのズレもなく動いてたら完璧です!
更にRPGぽくなりましたね!
戦闘開始時に戦闘BGMでもならしてみると一気にゲーム感が増しますよ。
おためしあれ。
──バトルシステムの半分は出来上がりましたね。
後はエネミー側の行動を実装してどちらかが行動する度にお互いのHPをチェックして、
戦闘終了の処理を加えたらバトルシステムは一旦完了します。
ぼうぎょとかいふくはエネミー側の処理が完成してから完成させましょう。
エネミーの攻撃を実装しないとぼうぎょの効果もわからないですし、
プレイヤーがダメージを受けないとかいふくの意味もないですからね。
しかし現在では見た目がゲームっぽくありません。
次々回ぐらいには見た目にダメージや回復がわかるようにしたり、
プレイヤーのHPとポーションの数を出すのも良いですね。
ちょっとレイアウトを考えないといけませんが……
幸い上下左右1マスが森でプレイヤーが行けない位置なので、
そこにUIを置いてもいいかもしれませんね。
最後に恒例のソースコードを置いておきます。
それでは。
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 = 12
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[6]
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
# カーソル用
@SELECTDATA
DATA 3,5,15
# エネミーパラメータ用
@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
D_BATTLE_SCENE_LOOP
ENDIF
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
D_BATTLE_GAUGE_LOOP
D_BATTLE_GUAGE_GRAPH
D_BATTLE_SELECT_COMMAND
D_BATTLE_ATTACK
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
ENDIF
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
PRINT "============"
PRINT "ダメージ前のエネミーHP:" + STR$(G_ENEMY_BATTLE_PARAMS[1])
PRINT "------------"
# ダメージ計算(こうげき - ぼうぎょ)
VAR DAMAGE = G_PLAYER_STATUS[3] - G_ENEMY_BATTLE_PARAMS[3];
# 最低でもダメージは1入るようにする
IF DAMAGE <= 0 THEN
DAMAGE = 1
ENDIF
# 実際の計算
DEC G_ENEMY_BATTLE_PARAMS[1], DAMAGE
# HPが0以下になったらメッセージを出しておく
IF G_ENEMY_BATTLE_PARAMS[1] <= 0
PRINT "@@@@@@@@@@@"
PRINT "エネミーをたおしたぞ!"
PRINT "@@@@@@@@@@@"
ENDIF
PRINT "ダメージ後のエネミーHP:" + STR$(G_ENEMY_BATTLE_PARAMS[1])
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