uData[0]=uDataSet.dataSet(1, 1, 1, 0);
}
これだけ。しかし、この一行に膨大な変数が詰まっている。
uDataというのはUnitDataクラス。
playerPlatformがマップ移動用のデータをまとめたクラスだとすれば、
uDataはユニットの能力値を記憶するクラス。
その中身はHP,MP,STR など多くの変数のカタマリだ。
細かく解説すると果てしないので説明は省略する…。
・vst=hp,mp,kpをまとめたもの
・fst=str,prt,dex,agl 物理関連のステータス
・mst=mstr,mprt,mdex,magl 魔法関連のステータス
・eiData=装備のデータが入っている。これもItemDataクラスでまとまっている。
ItemDataクラスは何も作っていない。空データだが、もうじき手を付ける。
・lv=体レベルと魔レベルで分けている。
なぜ分けたかというと、将来的に「転生」を作るため。
長い脱線になるので読み飛ばしてもいい。
[転生]
元々ディスガイアをパクってシステムを作る予定だった名残。
転生するとなぜINTまで下がるんだろう、という疑問があった。
転生しても1レベルになるのは体レベルのみで、魔レベルは下がらない。
じゃあ魔レベルを重視した装備とスキルで固めた方が良いじゃん、
と思うだろうけど、その代わりに魔レベルは必要経験値が多く上がりにくい。
体レベルを上げまくった方が速く成長できる。しかし、転生しないと差がつく。
こういうジレンマを再現しようとぼんやり思っていた。
…というシステムを組み込もうと思っているので二つのレベルに分けてある。
めんどくさかったら一本化してもいい。
ステータスを計算する箇所でレベルの反映を一つにまとめれば一本化できる。
ステータスに関しては詳しく書くとキリがないので端折る。
しかし、何もかも説明しないのもいかんので、一か所だけ抜き出して説明する。
マイルールみたいなもんを詳しく説明するのもなんか変だけど…。
[UnitData クラス]
public void statusLvBonusSet2() {
int flv=lv[0];
int mlv=lv[1];
int clv=flv;
for (int i=0;i<=2;i++) {
if (i>=1) clv=mlv; //hpは体LV、mp,kpは精神Lv
vst_up[i]=(vst_base[i]+vst_base_bp[i])*10/4; //up値も再計算する。bpが増えるとレベルが高い程一気に上がる。
vst_max[i]=vst_base[i]+vst_base_bp[i] +vst_up[i]*clv/4;
vst[i]=vst_max[i];
}
clv=flv;
for (int i=0;i<=3;i++) {
fst_up[i]=(fst_base[i]+fst_base_bp[i])*10/4
fst_max[i]=fst_base[i]+fst_base_bp[i] +fst_up[i]*clv/4;
fst[i]=fst_max[i];
}
clv=mlv; //str-dexは体LV,mstr以降は精神LV。
for (int i=0;i<=3;i++) {
mst_up[i]=(mst_base[i]+mst_base_bp[i])*10/4
mst_max[i]=mst_base[i]+mst_base_bp[i] +mst_up[i]*clv/4;
mst[i]=mst_max[i];
}
}
この処理はステータスとレベルを説明するのに適している。
vst_max[i]=vst_base[i]+vst_base_bp[i] +vst_up[i]*clv/4;
vst_maxというのが、hp,mp,kpの装備を含めない素の状態のステータス最大値。
装備を含めるとvst_totalという値になる。これが実際に使うhp,mp,kpになる。
kpってなによ、と言われると、「気 ki」point。ドラゴンボールのアレです。
ロマサガをやっているならWPのようなもの、というのが分かりやすいかも。
魔法を使うとmpが減り、技を使うとkpが減る、と考えるのが基本。
両方使う「術技」も設定できる予定だが、それはあとで決めていけばいい。
vst_base=ベース値。これの1/4がレベルアップ時の上昇値、vst_upになる。
vst_up=アップ値。レベル×コレ+ベース値がステータス計算の基本。
ベース値が高い程up値も高くなるが、先天的な物なのでup値自体は種族で固定。
後天的な修行などで変動するのが、vst_base_bp。
これが上がるほどベース値が増える=up値も増える。
人間よりもドラゴンの方がベース値が高く、
base_bpの上がり具合もドラゴンの方が遥かに高い。
しかし、人間も極限まで鍛えぬけば常人の数倍の能力まで上げられる。
ドラゴンなどの種族は必要経験値が多く、レベルアップに時間がかかる。
paintに行く前にUnitDataSetクラスの説明がいるか…。
[UnitDataSet クラス]
public UnitData dataSet(int unum, int flv, int mlv, int stbp) {
unumというのはユニット固有のナンバー。1-10は味方キャラ、
11-敵キャラのデータを入力する予定。
番号ごとに固有のデータがあり、外見なども番号とリンクする。
flv,mlvはユニットのレベル。
stbpはいわゆるボス補正のようなもの。
base値が高くなるので、とうぜんup値も増える。レベルが高いほどより強くなる。
さらに耐性値も上がるので、即死魔法が聞かなかったり眠らなかったりと色々設定できる。
まだなにもそこらへん入力してないけど。
他は…細かく説明すると果てしないので省略。
気がついたら書き足す。
ItemData, ItemDataSetクラスを形だけ作ったが、中身は何も設定してない。
次の講座で作る予定。
[最後。再び StatusWindow クラス - paint]
public void paint(Graphics gr) {
g=gr;
Font font2 = new Font("Meiryo UI", Font.PLAIN, 24);
int[] stxy= {56,88};
//0 メインメニューは常時出続ける。
if (mode>=1) {
String[] word= {"能力確認","特技","装備","アイテム","スキル習得","セーブ","ロード"};
g.setFont(font2);
gSet.rectSet2(g,32,64,144,190,0,0);
stxy[0]=56;
stxy[1]=88;
for (int i=0;i<=word.length-1;i++) {
gSet.wordDisp_short(gr,word[i],stxy[0],stxy[1]+i*22);
}
gSet.wordDisp_short(g,"→",cursorX[1],cursorY[1]+cursorPos[1]*22);
//所持金も表示しておく。
int sx=32;
int sy=254;
gSet.rectSet2(g,sx,sy,144,55,0,200);
gSet.wordDisp_short(g,"[所持金]",sx+24,sy+24);
gSet.wordDisp_short(g,String.valueOf(gData.money),sx+34,sy+48);
}
ここまでが最初のメインメニュー描画。
四角を描き、その上に文字を打ち込んでいるだけ。
それほど複雑な処理をしていないが、
ポイントはGraSetクラスで四角と文字を描画している事。
一個前のメッセージ表示プログラムではGameDataクラスに同じものを作って、
そこで描画するようにしていた。
その機能を丸ごとGraSetクラスに移行した。
画像を扱う処理全般を一つのクラスにまとめた方が感覚的に分かりやすい。
コロコロ仕様を変えて申し訳ないが、今後このやり方で進める。
良いと思ったら多少遠回りになっても何度でも作り直す。
if (mode==2 || mode==3) {
int sx=32;
int sy=208;
cSelWinDraw(mode);
}
cSelWinDrawというのはどのキャラクターに働きかけるか、
という名前と矢印を表示する描画をまとめた関数。詳しくはあとで書く。
ステータスの確認以外に、アイテム使用、スキル習得、魔法をかける相手、
装備を変更するキャラの選択…などこの先も使いまわすので、
どのmodeからでも参照できるように関数にまとめてある。
二か所以上で同じ処理をする場合はどんどん下請けの関数に振ったほうがいい。
修正が一度で済むし、エラーが出ても見る箇所1つに絞れるからだ。
//能力表示モード。
if (mode==3) {
//charaSelectWinDraw(10);
gSet.rectSet2(g,32,200,450,340,0,220);
//選んだキャラのデータを頻繁に使うので一時的に使いやすい形にする。
UnitData udt=gData.uData[selectUnitNumber];
int kx=40;
int ky=220;
String[] wd1= {"NAME","FLV","MLV"};
String[] nd1= {udt.name,String.valueOf(udt.lv[0]),String.valueOf(udt.lv[1])};
for (int i=0;i<=2;i++) {
gSet.wordDisp_short2(g,wd1[i],kx,ky+i*20,2);
gSet.wordDisp_short2(g,nd1[i],kx+70,ky+i*20,0);
}
for (int i=0;i<=1;i++) {
gSet.wordDisp_short2(g,"EXP",kx+120,ky+20+i*20,2);
gSet.wordDisp_short2(g,Integer.toString(udt.exp[i]),kx+170,ky+20+i*20,0);
gSet.wordDisp_short2(g,"/",kx+270,ky+20+i*20,2);
gSet.wordDisp_short2(g,Integer.toString(udt.exp_next[i]),kx+290,ky+20+i*20,0);
}
//HPなどを描画 アイテムなどの補正値を加算した最終ステータス
String[] wd2= {"HP","MP","KP"};
kx=40;
ky=300;
for (int i=0;i<=2;i++) {
gSet.wordDisp_short2(g,wd2[i],kx,ky+i*20,2);
gSet.wordDisp_short2(g,Integer.toString(udt.vst_total[i]),kx+70,ky+i*20,0);
gSet.wordDisp_short2(g,"/",kx+150,ky+i*20,2);
gSet.wordDisp_short2(g,Integer.toString(udt.vst_max_total[i]),kx+170,ky+i*20,0);
}
//基礎ステータス描画
kx=40;
ky=380;
String[] wd3= {"STR","PRT","DEX","AGL","MSTR","MPRT","MDEX","MAGL"};
for (int i=0;i<=wd3.length-1;i++) {
gSet.wordDisp_short2(g,wd3[i],kx,ky+i*20,2);
}
for (int i=0;i<=3;i++) {
gSet.wordDisp_short2(g,Integer.toString(udt.fst[i]),kx+70,ky+i*20,0);
gSet.wordDisp_short2(g,Integer.toString(udt.mst[i]),kx+70,ky+80+i*20,0);
}
kx=240;
String[] wd4= {"AP","DP","HIT","AVD","MAP","MDP","MHIT","MAVD"};
for (int i=0;i<=wd4.length-1;i++) {
gSet.wordDisp_short2(g,wd4[i],kx,ky+i*20,2);
}
for (int i=0;i<=3;i++) {
gSet.wordDisp_short2(g,Integer.toString(udt.fst_total[i]),kx+100,ky+i*20,0);
gSet.wordDisp_short2(g,Integer.toString(udt.mst_total[i]),kx+100,ky+80+i*20,0);
}
}
}
とくに難しい事はやっていない。HP,MPとかの項目を表示し、
実数値を各ステータスから読み込んで描画しているだけ。
g,Integer.toString(udt.fst_total[i])
というのは、数値を文字列に変換する処理。
数値を直接渡すとエラーになる。
String(udt.fst_total[i])
ではなぜかダメなので、長いけど上記のやり方で書かないといけない。
[cSelWinDraw関数]
private void cSelWinDraw(int setMode) {
String[] moji= {charaName[0],charaName[1],charaName[2],charaName[3]};
gSet.rectSet2(g,177,64,144,100,0,0);
int stx=204;
int sty=88;
for (int i=0;i<=moji.length-1;i++) {
if (unitLiveCheck(i)==true) gSet.wordDisp_short(g,moji[i],stx,sty+i*22);
}
gSet.wordDisp_short(g,"→",cursorX[setMode],cursorY[setMode]+cursorPos[setMode]*22);
}
charaNameというのはこのクラスにデータを渡すときに設定してある。
プレイヤーのパーティー全員の名前を格納してある変数。
live==0 存在しない名前は空欄に置き換えてある。
sursorX、Yは、モードごとに管理している。
このクラスから抜けない限り前回の値を保持し続ける為、
戻るボタンを押してもカーソルの位置がリセットされない。
毎回リセットした方が安全なのだが、不具合が起きないならこのまま使う。
説明不足の気がするが、次に移る。
今度はアイテムの取得イベントを作る。
そしてそれを使う。
さらにもう一つ、装備品を拾うイベントも作る。
まだ装備する段階まではいかない。
それをやりだすと今回以上に複雑な処理になるので、
前段階としてアイテムの取得と管理、消耗アイテムの使用まで作る。
こんなペースでRPGができるのかよ?
と疑問に思うかもしれないが、もう少しの辛抱だ。
装備まで作ったらいよいよ戦闘シーンに取り掛かるので、
・まずはアイテム取得、使用
・次が装備
・その次が戦闘
そういう順番で作る予定。
全ては戦闘シーンを作るための下準備なので、
データのやり取りが適当だとゲームにならない。
・トップページへ戻る