System4.0 のシナリオ変数(?)
えー、シナリオ変数というのは、自分が勝手にそう言ってるだけで、実際の呼び方は分かりませんし、この方法が有用であるとは限りません。
一体どういうものかというと、シナリオ内で使われるいろいろな条件分岐のための変数をグローバル変数として列挙せずに、クラス内に保持しておくというものです。これにより、シナリオ用の変数とゲームシステム用の変数が混ざってしまうと言うことを避ける狙いがあります。
実際に見てくれた方が早いです。
//名前変数 struct ExtTempStructure{ public: string Get(string name){ int i; for(i=0;i<Name.Numof();i++){ if(name==Name[i]){ return Data[i]; } } return ""; } void Set(string name,string data){ int i; for(i=0;i<Name.Numof();i++){ if(name==Name[i]){ Data.Insert(i,data); Data.Erase(i+1); return ; } } Name.PushBack(name); Data.PushBack(data); } private: array@string Name; array@string Data; }; |
使う方はこんな感じです。変数名がfeExtなのは、自分の慣習になってしまっているためです。きちんと名前を付けましょう。
ExtTempStructure feExt; void game_main(void){ while(feExt.Get("フラグ1")!="True"){ feExt.Set("フラグ1","True"); } } |
見てくれれば分かるとおり、ExtTempStructure
の内部に、文字列のキーと文字列の値を格納しています。メソッドは、値=Get(キー値) で取り出し、Set(キー値、値)で格納のみです。削除はできません。
内部構造は、二つの可変長配列で線形探索して操作しているだけです。ただし、Setで挿入削除を行っているのは、配列に対してPushBackで挿入した文字列の変更はできないためです。PushBackでなく、Reallocで行えば通常通り操作できると思います。
全く同じ内容なのですが、上記とは異なった実装をしたのが以下になります。
//名前変数 ExtTempStructureとは実装が異なります //たぶん、どっちもどっちです。 //配列上にするときはこちらの方が良いかと思います。 //互換性はありますので、入れ替えても動きます。たぶん。 // class ExtTempNode{ private: ref ExtTempNode next; string name; string data; public: string Get(string key){ if(key==name) return data; if(next!==NULL) return next.Get(key); return ""; } void Set(string key,string dat){ if(key==name) data=dat; else if(name==""){name=key;data=dat;} else{ if(next===NULL) next<- new ExtTempNode; next.Set(key,dat); } } }; |
アルゴリズム的にはこっちのがスマートですかね。わかりやすさ的にはExtTempStructureの方が分かりやすいとは思いますが。
なお、説明しなくても分かるとは思いますが、一応書いておきます。
int nNum; string szTmp; //int からstringにキャスト szTmp=nNum.String(); //stringからintにキャスト nNum=szTmp.Int(); //intからstringへは、出力変換を用いると高度に変換できます。(C言語のprintf風に) szTmp="%03d" % nNum; |
この手法は、たくさんのキャラクタごとに固有のシナリオ上の状態を持たせたい場合などに使えると思います。普通のノベルゲームなどでは、そのままグローバルに書き込んじゃっても問題ないとは思います。
それから、ものすごくまじめな人(もしくはきちんとしたゲーム)なら、状態保存用の構造体を用意してそこにそれぞれ変数を付けて、状態などはその構造体で管理するという方法を取ると思います。そのようにして管理できるなら、そう管理した方が良いと思います。