ホーム < ゲームつくろー! < 新・ゲーム制作技術編
その1 表計算ソフトからデータテーブルを作る
ゲームはとてつもなく沢山のデータの塊です。ステージ構成から敵の位置から画面レイアウトまで、あらゆるものが数値化されます。プログラムはその数値を読み込んでゲーム画面やシステムに反映させていきます。プログラム上には通常生のデータ値は書き込みません…と言うより、書き込んではいけません。プログラムに書き込んでしまうと変更を反絵するために再度コンパイルが必要になりますが、それにはプログラマの立会が必要になってしまいます。データの調整は企画の人のみで完結するようにするのが理想です。そのためにはあらゆるデータ値をプログラムの外に出さないとまずいわけです。
さて、ゲームで扱うデータには「プロパティ」と「テーブル」があるように思います。プロパティは例えばSTGの自機の速度とか弾の発射間隔、使用するテクスチャの名前などなど、あるオブジェクトに適用される様々な値を指します。一方テーブルはRPGに出てくる敵のHPやMP、使える呪文など「沢山の同じような物」に変化を与えるデータ群をまとめた物です。プロパティは特殊な物(主人公、ウィンドウパラメータなど)に使われますが、同じようなパラメータを持つ物量の多い物(ザコ敵パラメータ、弾パラメータなど)はテーブルにそのパラメータ値が記載される事が普通です。
テーブルを作成する時に多分一番効率が良いのが「表計算ソフト」です。ExcelとかOpen Officeなどがありますね。表計算ソフトは入力支援もありますし、何より沢山のまとまったデータを扱う事を得意としています。これらソフトの力を使わない手は無いわけです。しかし、これら表計算ソフトは元々はゲーム用になど設計されていないため、そのままではゲーム用のデータを出力してくれません。ではどうするか?この章では表計算ソフトからゲーム用のテーブルデータを出力する方法について試行錯誤してみます。
@ テキストファイルじゃ駄目?
表計算ソフトを使う云々の前に、そもそもデータを打ち込む方法として「テキストファイル」も候補にはあります。単純な話で、例えば、
Enemy_0001,64,64,enemy001
Enemy_0002,64,64,enemy002
Enemy_0003,128,64,enemy003
とCSV(Comma Separated Values)で記述していけばいいじゃん、という話もあります。もちろん、これでゲーム用のデータは作れますし、表計算ソフトから作るゲームデータもこれとほぼ一緒です。でも、これは実はあまり良くありません。理由は「間違う」からです。
テキストファイルは完全に自由記述ができます。自由に書けるという事は、間違いも記述できるという事です。上のCSVはスペースを許可していません。コメント文も入れてはいけませんし、途中で改行を挟むのもご法度。そういう決まりを作ったとしても、全部破るのが人です。そういうヒューマンエラーを回避するのはテーブルが巨大になるとほぼ不可能になってしまいます。もう一つ、テキストファイルで直書きするテーブルは可読性が酷く下がります。ぶっちゃげ読みにくいですよね、上のデータですらも。64って何?という話もあります。
ヒューマンエラーを極力排除するためには、表計算ソフトなどのある程度制約のある整ったデータ入力支援を使った方が良いんです。
A Excelのマクロ「VBA」でCSVを
表計算ソフトはその出力機能としてCSVをサポートしています。でも、それは空白もコメント行も何から何まですべてをCSVで吐き出してしまいます。これではゲーム用のデータテーブルとしては使い物になりません。ゲーム用のデータテーブルは@にあるようにデータだけが理路整然と並んでいる物です。余計な物は一切無し!これによって最大限の効率化とエラー回避が保障されるわけです。では、Excelなどの表計算ソフトからどうやってそれを出力するのか?
表計算ソフトには「マクロ機能」が備わっています。これは表計算ソフトの基本機能では賄いきれないような複雑な処理をプログラマブルに行わせる機能です。Excelの場合は「VBA(Visual Basic for Application)」が入っています。これを使うと表計算ソフトの表に記述されている項目であれば実質何でも出力(テキスト出力)できます。ただし、バイナリファイル化はちょっと厳しいようです(出来なくはないそうですが…)。
つまり「Excelの表のある部分をテーブルとしてCSVとして出力するマクロを書く」というのがこの章の方針です。
B VBA事始め、VBAからテキストファイル出力
ではここからはExcelのVBAで話を進めていきますが、Open Officeでも同じような事ができます。VBAは中身はVisual Basicなのでとっても簡単です。まずは事始めとして、VBAから適当なテキストファイルを出力してみましょう。
まず適当なフォルダを用意します。ここでは「Test」というフォルダにしておきます。そこに空のExcelファイル「test.xls」を一つ作りましょう。Excelを立ち上げてTestフォルダに保存しておきます:
次にExcelのメニューの中から[ツール]→[マクロ]→[新しいマクロの記録]を選択します。尚、これはExcel2003等のちょっと前のExcelの場合です。メニューが一新された最近のExcelについてはWebで探してみて下さい(持ってないのでわからんのです(T-T))。
マクロの記録ウィンドウが出てきますが、これはそのままでOKしてマクロの記録を始めます。記録が始まったら何も考えずに「Ctrl+C」つまりセルのコピーを実行します。これで記録を止めます(■をクリック)。これでマクロが記録されました。「はい?」と思うかもしれません。何をしているかというと、マクロを記述する部分を作りたいだけなんです。今記録したものはこの後すっきり全部消します(^-^)。
先ほどの作業でマクロが記録されました。それを見るには[ツール]→[マクロ]→[Visual Basic Editor]を選択します。すると、「Microsoft Visual Basic」というウィンドウが開きます。先ほど記録したマクロはプロジェクト内の「標準モジュール」の中の「Module1」にあります:
Macro1に「Selection.Copy」という一文がありますね。これ「選択範囲をコピーせよ」というVBAの命令です。ちゃんと記録されています(^-^)。これを改造していきます。
まず、このプログラムをきれいさっぱり消してしまいます。そして、次のように記述してみましょう:
テキスト出力 Option Explicit
Sub Output()
Dim fileId As Integer
Dim fileName As String
fileName = ThisWorkbook.Path & "\test.txt"
fileId = FreeFile()
Open fileName For Output As #fileId
Print #fileId, "最初の一歩"
Close fileId
End Sub
ポイントを説明します。
fileNameには出力するファイルのパスが格納されます。ThisWorkbook.Pathとすると、今開いているExcelファイルのフォルダパスが取得できます。そこにtest.txtというファイル名を付ける事でフルパスにしているわけです。
次のfileIdというのは出力するファイルを表すIDでFreeFile()という関数で取得できます。以後このIDをファイル名の代わりとして使います。
Openがファイルを開く(作成する)関数で、引数にファイルパスを渡します。その後に「For
Output As #fileId」というおまじないが付きます。これは「ファイルIDを出力用で開いてね」と命令しています。
Print関数にファイルIDを渡し、その次に文字列を渡すと、それをテキストファイルとして出力してくれます。
開いたファイルは最後にClose関数で閉じます。
これでVBAからtest.txtというテキストファイルが出力されます。実際先ほどのフォルダに作成されました:
これで、後はPrint関数に渡す文字列を作れば、どんなテキストもテキストファイルとして出力できるわけです!いえい。
C データテーブルを作る
では次に、Excelの表に実際にデータテーブルを作ってみましょう。
データテーブルの作り方にも色々あるのですが、典型的なのは「最初の列にKey値を、その後にValue値群を記述する」という物です。ここでは例として、RPGのアイテムのパラメータのデータテーブルを作ってみます。
RPGのアイテムには、
・ 名前(name)
・ 属性(attribute)
・ 値段(price)
・ 攻撃力(attack)
・ 防御力(defence)
などがあります。これにKeyであるidを項目に加えた表を作るとこうなります:
さて、もちろんこのままでも読み込めるのですが、例えば項目を増やすとか、注意事項を記入しておきたいなどとなると、自由記述スペースが欲しいんですよね。そのため、実際には「どこからがデータの始まりなのか」という範囲指定をしてあげます。典型的なデータテーブルは例えばこんな感じです:
データ列、データ行という欄ができました。ここにデータテーブルの左上位置を指定します。エクセルは1基底なので左から3番目、上から8番目のセルと指定しています。VBA側からはこの値を参照する事で確実にデータテーブルを読み取る事ができます。
ではこのテンプレートに従ってデータ列を実際に読み込んでテキスト出力してみます:
データテーブルをCSVで出力 Option Explicit
Sub Output()
Dim fileId As Integer
Dim fileName As String
Dim col As Integer
Dim row As Integer
Dim c, r As Integer
Dim colEnd As Integer
Dim rowEnd As Integer
Dim outStr As String
Dim retStr As String
retStr = Chr(13) & Chr(10) 'リターン文字
'データテーブルの範囲を取得
col = Cells(3, 2)
row = Cells(4, 2)
colEnd = Range(Cells(row , 256), Cells(row , 256)).End(xlToLeft).Column
rowEnd = Range(Cells(65536, col), Cells(65536, col)).End(xlUp).Row
'データ範囲を文字列へ
outStr = (colEnd - col + 1) & retStr
outStr = outStr & (rowEnd - row) & retStr
'データを文字列へ
For r = row To rowEnd
For c = col To colEnd - 1
outStr = outStr & Cells(r, c).Value & ","
Next
outStr = outStr & Cells(r, c).Value & Chr(13) & Chr(10)
Next
'テキストファイルで出力
fileName = ThisWorkbook.FullName
fileName = Left(fileName, InStrRev(fileName, ".")) & "txt"
fileId = freeFile()
Open fileName For Output As #fileId
Print #fileId, outStr
Close fileId
End Sub
最初にデータの列数と行数を出力します。これはプログラム上から読み込む時に役立ちます。
Range関数にExcelの右端、もしくは下端の位置を与え、End関数を呼ぶと、データの最後の列や行の位置を返してくれます。こういうもんだで十分です。outStrという文字変数にセルの値を文字列としてどんどん追加し、コンマで区切っていきます。最後の列だけはコンマの代わりに改行(Chr(13)
& Chr(10))を入れています。
出力ファイル名は開いているExcelのファイル名で拡張子をtxtに変更したものとしました。
これでCSV化ができていますので、あとはそれをテキストとして出力しています。実際に出力された結果はこうです:
出力結果 6
3
id,name,attribute,price,attack,defence
item_w_0001,木刀,weapon,100,10,0
item_w_0002,銅の剣,weapon,500,20,0
item_w_0003,鉄の剣,weapon,1200,35,0
行数と列数の情報が入ったCSVデータテーブルになっています(^-^)。
マクロを実行するには[ツール]→[マクロ]→[マクロ]で「Output」を選択して「実行」とする方法がありますが、もっと手っ取り早くするならば、画面にボタンを配置して、それにマクロ実行を割り当ててしまう事です。これには「フォーム」というのを使います。
フォームはデフォルトでメニューに出ていない事があります。メニューの何もない所で右クリックし、「フォーム」を選択すると、フォーム項目が出てきます:
このボタンを選択して、表の適当な所をクリックするとボタンが配置されます。その時同時にマクロの選択画面も出ます。ここで「Output」を選択すれば、そのボタンにマクロがアタッチされます。これで、そのボタンを押すだけでCSVが出力されます。
これでExcelからデータテーブルを出力する機構ができました。後はプログラムからCSVを解析してプログラム上で扱える状態にするだけです。それは、次の章で考えてみる事にしましょう。