計算機

RPGツクール2000編

攻撃力や、魔法攻撃力の計算処理を作ります。

ここではわかりやすいように、攻撃力計算式
自分の攻撃力 - 相手の防御力 = ダメージ
という計算方法を使います。

計算処理を作る上で重要なのは、データベースから呼び出したアクティブデータベースへのアクセスです。
どのようにして目的のデータを効率よく呼び出すかが、課題です。

RPGツクールにもポインタと同じような機能が備わっています。



[変数ID]変数内容を扱います。
v[変数ID]変数内容に格納された数値をアドレスと見なし、アドレス先の変数内容を扱います。


※ワンポイントアドバイス
v[変数ID]を指定する時にアドレス開始位置いちいち定数値で指定することも出来ますが、ツクールの仕様上0(NULL)値を利用することで安易に取出しが出来ます。
例えば、変数[0201]に変数[0567]のアドレス値を入力するとします。
通常は、


直接定数指定[0201]569
NULL値指定[0201]v[0569]

どちらとも変数[0201]の値は569になります。
ただし、NULL値指定の場合は必ず変数[0569]の内容に0を代入してから使用します。
変数[0000]というIDは存在しないため、0=NULL=変数のIDのアドレス、となることを利用しているからです。

※ C/C++で置き換えると・・・。
変数A = * 変数D : v[変数ID](変数内容 !=0の場合)
変数B = & 変数D : v[変数ID](変数内容==0の場合)

変数A:変数Dのアドレス値先の変数の値
変数B:変数Dのアドレス値

C/C++では実際のPCのメモリを操作するので、メモリ番地が常に変動しており格納先の番地がばらつきます。
そのためポインター宣言をしたものに+1をすると変数配列で指定した"次"のメモリアドレスへ飛ぶという抽象的な動作をします。
しかし、ツクールでは固定された(最小0001番目〜最大9999番目)配列変数へと格納するため直接指定という形になります。
ポインタ変数に+1を行った場合、直接アドレス番地が+1されます。
ある意味、int rpgtkool[9999]という配列変数を用意されたようなものですね。


NULL とは値が無いことを示します。
本来、0ではなく値が入ってない空の状態ものです。


ここで言うポインタはv[変数ID]のことです。 其のポインタを使い、アクティブ変数に呼び出された数値を入出力します。

例を挙げるために、データベースページで説明したデータ値を扱います。
Char[n]経験値経験値fx_EXP
Char[n]HPHPfx_ActiveHP
Char[n]MPMPfx_ActiveMP
Char[n]最大HP最大HPfx_MAXHP
Char[n]最大MP最大MPfx_MAXMP
Char[n]攻撃力攻撃力fx_ATK
Char[n]攻撃力魔法攻撃力fx_MATK
Char[n]防御力防御力fxDEF
Char[n]防御力魔法防御力fxMDEF
Char[n]精神力命中力fxHIT
Char[n]敏捷性素早さfxSPEED
Char[n]敏捷性回避力fxFLEE

※Char[n]というのはn番目の主人公の意味です。
 攻撃の計算機で使うのは、この呼び出されたステータスの内、fxATKとfxDEFを使います


戦闘初期化時の一時格納するデータベース用の変数は、 参加させるモンスターの数の最大数xステータス 参加させる主人公の数の最大数xステータス の数だけ必要です。
0101:char01_fx_EXP
0102:char01_fx_ActiveHP
0103:char01_fx_ActiveMP
0104:char01_fx_MAXHP
0105:char01_fx_MAXMP
0106:char01_fx_ATK
0107:char01_fx_MATK
0108:char01_fx_DEF
0109:char01_fx_MDEF
0110:char01_fx_HIT
0111:char01_fx_SPEED
0112:char01_fx_FLEE
0113:char01_fx_B_ST
0114:char01_fx_D_ELEMENT
0115:none
0116:none
0117:none
0118:none
0119:none
0120:none

0121:char02_fx_EXP
0122:char02_fx_ActiveHP
0123:char02_fx_ActiveMP
0124:char02_fx_MAXHP
0125:char02_fx_MAXMP
0126:char02_fx_ATK
0127:char02_fx_MATK
0128:char02_fx_DEF
0129:char02_fx_MDEF
0130:char02_fx_HIT
0131:char02_fx_SPEED
0132:char02_fx_FLEE
0133:char02_fx_B_ST
0134:char02_fx_D_ELEMENT
0135:none
0136:none
0137:none
0138:none
0139:none
0140:none


RPGツクール2000は変数が1ページにつき20個の変数を一覧できるため、扱い安くするためにキャラクター間の変数を20置きに格納していきます。
主人公[n]の一時ステータスをここに変動した数値を入れたり、引き出したりして計算時に使います。



※char[n]_fx_B_ST とは[n]番目の主人公の状態異常の合計値を格納する変数
※char[n]_fx_D_ELEMENT とは[n]番目の主人公属性を格納する変数



0501:Enemy01_fx_EXP
0502:Enemy01_fx_ActiveHP
0503:Enemy01_fx_ActiveMP
0504:Enemy01_fx_MAXHP
0505:Enemy01_fx_MAXMP
0506:Enemy01_fx_ATK
0507:Enemy01_fx_MATK
0508:Enemy01_fx_DEF
0509:Enemy01_fx_MDEF
0510:Enemy01_fx_HIT
0511:Enemy01_fx_SPEED
0512:Enemy01_fx_FLEE
0513:Enemy01_fx_B_ST
0514:Enemy01_fx_SKILL01
0515:Enemy01_fx_SKILL02
0516:Enemy01_fx_SKILL03
0517:Enemy01_fx_SKILL04
0518:Enemy01_fx_SKILL05
0519:Enemy01_fx_(x)
0520:Enemy01_fx_(y)

0521:Enemy02_fx_EXP
0522:Enemy02_fx_ActiveHP
0523:Enemy02_fx_ActiveMP
0524:Enemy02_fx_MAXHP
0525:Enemy02_fx_MAXMP
0526:Enemy02_fx_ATK
0527:Enemy02_fx_MATK
0528:Enemy02_fx_DEF
0529:Enemy02_fx_MDEF
0530:Enemy02_fx_HIT
0531:Enemy02_fx_SPEED
0532:Enemy02_fx_FLEE
0533:Enemy02_fx_B_ST
0534:Enemy02_fx_SKILL01
0535:Enemy02_fx_SKILL02
0536:Enemy02_fx_SKILL03
0537:Enemy02_fx_SKILL04
0538:Enemy02_fx_SKILL05
0539:Enemy02_fx_(x)
0540:Enemy02_fx_(y)



Enemy(n)_fx_SKILL[s] とは敵の行動パターンを格納する変数
Enemy(n)_fx_(x)(y) とは敵のグラフィックを表示する座標(x,y)を格納しておく変数




攻撃者の攻撃力 - ターゲットの防御力 = ダメージ
この式を作り出すには、それに相応する数値を呼び出します。
例えば、主人公01が敵02へ攻撃するとします。
この時に取り出す変数は、
[0106 : char01_fx_ATK] と [0526 : Enemy02_fx_DEF] と [0521 : Enemy02_fx_ActiveHP] の三つです。
例で明確に定義されてるので、主人公01と敵02の目的のステータスを呼び出すことが安易にできますが、 変動する場合、話は違います。
主人公が02であったり、03であったり、敵が02であったり05であったりなどすると物凄い数の分岐が必要になります。
C01→E01
C01→E02
C01→E03
C01→E04
C02→E01
C02→E02
C02→E03
C02→E04
C03→E01
C03→E02
C03→E03
C03→E04

※Cは仲間、Eは敵を表します。

こんな風に一つ一つずつ計算機を作るととっても面倒です。
其の作業を上手く回避できるのがポインタの機能です。

実際に計算処理をする前に、必要な数値を変動する変数から取り出します。

[n]番目の主人公の攻撃力を取り出す場合

予め、[n]番目の主人公のコマンドが回ってきた場合、其の主人公の番号[n]を変数[305]へ代入しておきます。
(コマンドが回ってきた時に何番目の主人公を操作しているか、とある変数へ代入しておくとそれを参照して取り出したい値を自動的に割り出してくれるのです。)

戦闘参加主人公の戦闘時一時アクティブ変数は[0101]から始まっています。
其の値を元に、一人づれる度に+20されて始まります。
この+20を利用します。
主人公02の攻撃力は変数[0126]に格納されています。
これをポインタを使って取り出すと・・・

------------
変数[0301]に定数106を代入
変数[0302]に-1を代入
変数[0302]に変数[0305]を加算
変数[0302]を定数20で乗算
変数[0301]へ変数[0302]を加算
------------

変数[701]にv変数[0301]を代入

※最後の行のv変数[0301]の"v"は変数のアドレスを指し示す記号です。
C言語で言う、アスタリスク"*"と同様の効果があります。

これで変数[0701]の中身は"主人公02の攻撃力"が格納されています。
一方、変数[0301]に格納されている数値は126であり、"主人公02の攻撃力"は格納されていません。
何だか不思議な気分ですね。
RPGツクール2000ではこのポインタになる変数を計算して取り出したい変数のアドレスを算出し、それからアドレス先の変数の操作をするという妙な操作の仕方をします。
少しややこしいですが、この考え方は自作戦闘を作るにあたって多用しますので、抑えておきたいアルゴリズムの一つです。
この容量で、敵のDEF・HPを指し示すプログラムも作りましょう。

味方のATK、敵のDEF・敵のHPを取り出したら、いざダメージ計算です。
これは別キャッシュ変数
[0701:一時キャッシュ01]
[0702:一時キャッシュ02]
[0703:一時キャッシュ03]
[0705:結果]
等を用意して計算。(計算処理省略)

先ほど作った敵HPポインタプログラムを呼び出します。
変数[0301]に算出したアドレス値を代入。
v変数[0301]を変数[0705]で減算する。
あとは其の処理結果を画面に表示する処理を実行すれば完成となります。


説明を見てた人の中にはぽかーんとする人も居るかもしれませんが、こればっかりは慣れと経験が必要なのです。^^;
複雑なプログラムを組もうとすればするほど、まだまだ難しいアルゴリズムを要求されます。

自作戦闘を作りたいと思ってる人は、根性を入れて作るべし!!