CastleDB/Haxe の変更点


[[CastleDB]]

* CastleDBをHaxeで使う方法 [#zf1f1078]

* 概要 [#ic413d9e]
このページではCastleDBをHaxeで使う方法を紹介します

----
#contents
----

* 1. データベースの作成 [#v63db61d]
まずはデータベースを作成します。

** シートの作成 [#e46cd183]
CastleDBを起動したら「Create a sheet」をクリックして、シートを作成します。

#ref(001.png);

シート名には「enemies」と入力して「Create」ボタンをクリックします。

#ref(002.png);

** 項目の作成 [#xbaec8b3]

次に「Add a column」をクリックして項目を作成します。

#ref(003.png);

項目のプロパティが表示されるので、以下のように入力します。

#ref(004.png);

- Column name: id
- Column type: Unique Identifier
- Required: チェックを入れたままにする

項目名を「id」、データ型は「ユニークID」、必須入力とする、という設定となります。
設定できたら、Createをクリックします。

続けて、作成した項目「id」のところにマウスを移動させて右クリックし、ポップアップから「Add Column」を選びます。

#ref(005.png);

項目のプロパティは以下のように入力します。

#ref(006.png);

- Column name: hp
- Column type: Integer
- Display: Default
- Required: チェックを入れたままにする

これは敵のHPとなります。
入力できたらCreateをクリックして項目を作成します。

** データ入力 [#u8780708]

項目ができたので、敵のデータを入力します。「Insert Line」をクリックします。

#ref(007.png);

するとデータ行が追加されます。

#ref(008.png);

id項目が「#MISSING」となっているのでユニークIDを設定します。idは「Slime」として、hpには「10」と入力します。

#ref(009.png);

入力できたら、入力した行を右クリックして、ポップアップから「Insert」を選びます。

#ref(010.png);

idには「Dragon」、hpには「9999」と入力します。

#ref(011.png);

これでデータベースは完成です。

** 保存 [#ua1ecfd3]

メニューから「File > Save As...」を選んでファイル名を「MyDB.cdb」として任意の場所に保存します。

#ref(012.png);

* 2. castleライブラリのインストール [#ff481a7b]
以下のコマンドで、castleライブラリをインストールします
 haxelib install castle

* 3. テストプロジェクトの作成 [#me39325a]
任意の場所でテストプロジェクトを作成します。
 flixel tpl -n "Test"

* 4. CastleDBの読み込み [#t7b24a4b]

** Project.xmlの設定 [#y2bfc68e]
以下の記述で castleライブラリを有効にします

#geshi(xml){{
  <!-- castleライブラリ有効 -->
  <haxelib name="castle"/>
}}

** MyDB.cdbの配置 [#b6bc39ae]
作成したデータベース「MyDB.cdb」を 「Test/source/dat」(datフォルダは新規作成) に配置します

#ref(020.png);

sourceフォルダに配置するのは、Haxeのコードから直接読み込んでマクロで展開するためです。

** Data.hxの作成 [#jbddf559]
CastleDBを展開するモジュール「Data.hx」を作成します。場所は「Test/source/dat」に配置します。

#ref(021.png);

Data.hxは以下のように記述します。

#geshi(ActionScript){{
package dat;

private typedef Init = haxe.macro.MacroType<[cdb.Module.build("dat/MyDB.cdb")]>;
}}

上記コードは、シート名や項目名をマクロで展開するものです。これによりCastleDBのデータにアクセスしやすくなります。

** Haxeで読み込む [#r29361bd]
Project.xmlに「MyDB.cdb」を読み込めるように assets path を登録します。

#geshi(xml){{
  <!-- MyDB.cdbを読み込めるようにする -->
  <assets path="source/dat/MyDB.cdb" />
}}

MenuState.hx に読み込み処理を記述します。


#geshi(ActionScript){{
package;

import flixel.FlxG;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.text.FlxText;
import flixel.ui.FlxButton;
import flixel.util.FlxMath;
import openfl.Assets;
import dat.Data;

/**
 * A FlxState which can be used for the game's menu.
 */
class MenuState extends FlxState
{
  
  /**
   * Function that is called up when to state is created to set it up. 
   */
  override public function create():Void
  {
    super.create();
    
    // CDBファイルの読み込み
    var content:String = openfl.Assets.getText("source/dat/MyDB.cdb");
    // ロード実行
    Data.load(content);
    // 値の取得
    trace("Slime: HP=" + Data.enemies.get(Slime).hp);
    trace("Dragon: HP=" + Data.enemies.get(Dragon).hp);
}}

実行すると、HPの値を取得することができます。

 Slime: HP=10
 Dragon: HP=9999

* カラムのマッピング [#v6901ffb]
カラムに指定したデータ型に対応する、Haxeにおける型は以下のようになります

,''カラム'',''型'',''説明 / 例''
,行データ,シート名の先頭を大文字にしたもの,"enemies"の場合は、"Enemies"という型になる
,Unique Identifier,シート名+Kind,"enemies"シートの場合、"EnemiesKind"という型になる
,Text,String,
,Boolean,Bool,
,Integer,Int,
,Float,Float,
,Color,Int,
,Enumeration,シート名_カラム名,"enemies"シートの"attr"カラムの場合は、"Enemies_attr"でアクセスできる
,Flags,cdb.Types.Flags<シート名_カラム名>,ビットが立っているかどうかを判定するには cdb.Types.Flags<T> のメソッド利用する
,Reference,指定したシートの型,"enemies" シートなら "Enemies" になる
,File,String,cdbファイルからの相対パス
,File,String,cdbファイルからの相対パス。指定がない(#MISSING)の場合は空文字「""」となります。
,Image,String,MD5のキーのみ。現時点では画像の読み込みはサポートしていない
,Tile,cdb.Types.TilePos,contains the tileset file and size、 the x/y position and optional width/height (by default it is 1)
,List,cdb.Types.ArrayRead<シート名_カラム名>,cdb.Types.ArrayRead<T>のメソッドで、イテレート、インデックスアクセスやサイズが取れる
,Custom,SheetName_ColumnName,values are converted on-the-fly to the enum created as it has been declared.
,Dynamic,Dynamic,data as-it.
,Data Layer,cbd.Types.Layer<SheetName>,you can decode the layer by passing the Data.sheetName.all array to the decode() function.
,Tile Layer,cbd.Types.TileLayer,you can decode the layer by using the t.data.decode() function. It will automatically decompress data and will return an Array of 16-bits values. If the tile layer is in tile/ground mode、 this gives you width x height values. If it is in object mode、 see the object layer encoding section.

** Unique Identifierの詳細 [#y02f0b64]
例えば、enemiesシートのUnique Identifierに「Slime」がある場合、以下の記述でアクセスできます。

#geshi(ActionScript3){{
    // スライムの情報を取得
    var e:Data.Enemies = Data.enemies.get(Data.EnemiesKind.Slime);
    trace(e);
}}

以下のように省略してアクセスすることも可能です。

#geshi(ActionScript3){{
    // スライムの情報を取得
    var e:Data.Enemies = Data.enemies.get(Slime);
    trace(e);
}}

*** Referenceとの連携 [#g5b85f38]
Unique Identifierをわざわざ定義する理由は、Referenceとの連携があるからです。
例えば、敵の出現グループ(RPGでスライムx3が現れるなど)のテーブルを定義したいときに、ドロップダウンで選択可能になります。
敵出現テーブルを作成して、カラムを「Reference」にすると参照するシートを選ぶことができます。
#ref(UniqueIdentifier002.png);
ここで敵定義テーブルの「enemies」を選ぶと、ドロップダウンで敵の種類を選ぶことができます。

#ref(UniqueIdentifier003.png);

なお、Referenceを指定したカラムにはUnique Identifierを指定しますが、実際にはそのデータの参照(行データ)が含まれることになります
** Enumerationの詳細 [#zc856d5c]
値は定義した順番で「0」から連番の数値となります。
例えば、enemiesシートのattrカラムに、「Phys,Gun,Fire」が定義されている場合は「0,1,2」となります

#geshi(ActionScript3){{
    trace(Data.Enemies_attr.Phys); // 0
    trace(Data.Enemies_attr.Gun);  // 1
    trace(Data.Enemies_attr.Fire); // 2
}}

また、COUNTで項目の最大数、NAMESで項目の文字列を取得することが可能です。

#geshi(ActionScript3){{
    trace(Data.Enemies_attr.COUNT); // 3
    trace(Data.Enemies_attr.NAMES); // [Phys,Gun,Fire]
}}

** Flagsの詳細 [#a7e7239f]
例えばFlagsのカラム名に"flag"、Possible Valuesに"[a,b,c,d]"を指定した場合は、以下の方法でビットが立っているかどうかをチェックできます。

#geshi(ActionScript3){{
    // cdb.Types.Flags<T>.has()で判定
    var e:Data.Enemies = Data.enemies.get(Data.EnemiesKind.Slime);
    if(e.flag.has(Data.Enemies_flag.a)) {
      trace("a is on");
    }
    if(e.flag.has(Data.Enemies_flag.b)) {
      trace("b is on");
    }
    if(e.flag.has(Data.Enemies_flag.c)) {
      trace("c is on");
    }
    if(e.flag.has(Data.Enemies_flag.d)) {
      trace("d is on");
    }
}}

また、COUNTで項目の最大数、NAMESで項目の文字列を取得することが可能です。

** Listの詳細 [#e4782688]
例えば、敵テーブルにドロップアイテムのカラム「dropitem」を追加し、50%で1番、30%で2番、20%で4番のアイテムをドロップするようにしました
#ref(List001.png);

CastleDBのList型は Haxeの Array とほぼ同等で、lengthでサイズを取得したり、インデックスアクセスができます。以下はイテレートする例です。

#geshi(ActionScript3){{
    var e:Data.Enemies = Data.enemies.get(Data.EnemiesKind.Slime);
    for(info in e.dropitem) {
      trace(info.item, info.ratio);
    }
}}
** カラムのマッピングをコードで確認する [#ta7ee4b3]
以下のコマンドで、マッピングがどうなっているのか確認できます
 haxe Data.hx -D dump=pretty -lib castle

* Tips [#ld31ff8a]
** シート内の全要素にアクセスしたい [#d65eb850]
シート名.all ですべての要素にアクセスできます

#geshi(ActionScript3){{
    // equipmentシートのすべての要素にアクセス
    for(info in MyDB.equipment.all) {
    }
}}

** データ数を取得する [#be646db3]
シート名.all.length でデータ数を取得できます

#geshi(ActionScript3){{
  trace(MyDB.equipment.all.length);
}}
* 参考 [#mb0880e4]
- [[CASTLEDB -- A GAME DATABASE? A LEVEL EDITOR? IT’S BOTH>http://www.gamefromscratch.com/post/2015/11/14/CastleDB-A-Game-Database-A-Level-Editor-Its-Both.aspx]]