<?xml version="1.0" encoding="UTF-8" ?><rdf:RDF 
  xmlns="http://purl.org/rss/1.0/"
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xml:lang="ja">
  <channel rdf:about="http://w.atwiki.jp/mofnotony/">
    <title>W/B Child@ ウィキ</title>
    <link>http://w.atwiki.jp/mofnotony/</link>
    <atom:link href="https://w.atwiki.jp/mofnotony/rss10.xml" rel="self" type="application/rss+xml" />
    <atom:link rel="hub" href="https://pubsubhubbub.appspot.com" />
    <description>W/B Child@ ウィキ</description>

    <dc:language>ja</dc:language>
    <dc:date>2006-11-18T17:01:59+09:00</dc:date>
    <utime>1163836919</utime>

    <items>
      <rdf:Seq>
                <rdf:li rdf:resource="https://w.atwiki.jp/mofnotony/pages/7.html" />
                <rdf:li rdf:resource="https://w.atwiki.jp/mofnotony/pages/9.html" />
                <rdf:li rdf:resource="https://w.atwiki.jp/mofnotony/pages/1.html" />
                <rdf:li rdf:resource="https://w.atwiki.jp/mofnotony/pages/2.html" />
                <rdf:li rdf:resource="https://w.atwiki.jp/mofnotony/pages/8.html" />
                <rdf:li rdf:resource="https://w.atwiki.jp/mofnotony/pages/6.html" />
                <rdf:li rdf:resource="https://w.atwiki.jp/mofnotony/pages/5.html" />
                <rdf:li rdf:resource="https://w.atwiki.jp/mofnotony/pages/4.html" />
              </rdf:Seq>
    </items>
	
		
    
  </channel>
    <item rdf:about="https://w.atwiki.jp/mofnotony/pages/7.html">
    <title>クライアント</title>
    <link>https://w.atwiki.jp/mofnotony/pages/7.html</link>
    <description>
      *エンティティシステム

■ プレイヤーがミサイルを発射する例

// par1: 作成する発射物の型
// par2: 発射物の射手/所有者
// par3: シーングラフの親
ENTITY* FireProjectile ( char* className, ENTITY* entshooter, ENTITIY* parent )
{
    ENTITY* entProj;                                            // 発射物エンティティ
    VECTOR3 pos;                                                // 射手/発射物の位置
    VECTOR3 dir;                                                // 射手の方向ベクトル
    VECTOR3 velocity;                                           // 射手の速度ベクトル
    
    
    // 『parent』のシーングラフの子として発射物を作成
    entProj = EntCreate(className, parent, 0, 0);
    if ( entProj)
    {
        // 射手から位置・方向・速度を取得
        EntSendMessage( entShooter, EM_GETPOS, (int)&amp;pos, 0 );
        EntSendMessage( entShooter, EM_GETDIR, (int)&amp;dir, 0 );
        EntSendMessage( entShooter, EM_GETVELOCITY, (int)&amp;vel, 0 );
        
        // 新しい発射物の設定
        EntSendMessage( entProj, EM_SETPOS,      (int)&amp;pos, 0 );
        EntSendMessage( entProj, EM_SETDIR,      (int)&amp;dir, 0 );
        EntSendMessage( entProj, EM_SETVELOCITY, (int)&amp;vel, 0 );
        EntSendMessage( entProj, EM_SETOWNER,    (int)&amp;entShooter, 0 );
        EntSendMessage( entProj, EM_START,       0, 0);
        
        return (entProj);
    }
}

※ C++の実装では、(int)のキャストは正しい型付きパラメータを引数とする仮想関数により消える。


■ 全てがエンティティ

全てをメッセージで制御可能なエンティティとして考えること！
発射物も、地形も、ゲームスクリプト(アルゴリズム)といったもの全てを統一して考える。

弾丸、地形、スクリプトエンティティの様々なメッセージへの応答の仕方


                         弾丸       地形       スクリプト
-----------------------------------------------------------------------------
更新                     処理       無視          処理
-----------------------------------------------------------------------------
描画                     処理       処理          無視
-----------------------------------------------------------------------------
衝突チェック             処理       無視          無視
-----------------------------------------------------------------------------
衝突テストへの応答       無視       処理          無視
-----------------------------------------------------------------------------


■ システムの要素

・エンティティメッセージ: エンティティの通信の仕方を定義する
・エンティティコード    : エンティティクラスを実装するコードとデータ
・クラスリスト          : 登録されたエンティティクラスのリストの保守
・エンティティマネージャ: エンティティの作成、エンティティツリーの管理、
                          1つあるいは複数のエンティティへのメッセージ送信のサポート


■ エンティティメッセージ

エンティティは必要でなかったり、理解できないメッセージを安全に無視できなければならない。

// メッセージ処理関数型
//
// par1: _thisエンティティへのポインタ
// par2: EM_...エンティティ メッセージ
// par3: 汎用パラメータ1
// par4: 汎用パラメータ2
// ret : 関数の戻り値によって、エンティティツリーを通って再帰を続けるべきかどうかを通知する
typedef int (ENT_PROC) ( ENTITY* ent, EM message, int var1, int var2 );


メッセージリストの例

この列挙型に1つ値を加えるだけで、新しいメッセージを追加できる。

enum EEntMessageTag
{
    // クラス処理
    EM_CLSINIT,                         // クラスの初期化 var1=char* データパス
    EM_CLSFREE,                         // クラスの解放
    EM_CLSNAME,                         // クラス名をvar1にコピー
    
    // 作成と破棄
    EM_CREAT,                           // エンティティの作成
    EM_START,                           // エンティティを『ON』にする
    EM_SHUTDOWN,                        // エンティティを上品に破棄
    EM_DESTOROY,                        // エンティティを即座に破棄
    
    // 標準アクション
    EM_UPDATE,                          // var1 = int 経過秒数
    EM_DRAW,                            // _normal_ レンダリング
    
    // データアクセス
    EM_SETPOS,                          // var1 = VECTOR3* 位置
    EM_GETPOS,                          // VECTOR3 位置をvar1にコピー
    
    ...
};


■ エンティティコード(Cベース)


// ミサイルクラス
struct missileTag
{
    char        name[ENT_NAME_LEN]; // 名前
    VECTOR3     velocity;           // 速度
    VECTOR3     position;           // ワールド空間位置
    VECTOR3     forceAccum;         // 力の累算器
    MATRIX4x4     matModel;         // 姿勢行列
    int         engineRunning;      // TRUE: エンジンON
    
    // 他に必要なメンバがあれば以下に追加する
};


// CLSINITYでロードされ、CLSFREEで開放されるリソースとクラス全体の変数
static MODLE mdlMissile;
static SOUND launchSount;
static float thrust = 10000.0f;

// メッセージ処理部
// par1: システムの任意の型のエンティティの参照に使う汎用エンティティコンテナ
// par2: 処理するメッセージ
// par3: 汎用パラメータ1
// par4: 汎用パラメータ2
int MissileProc( ENTITY* entity, EM message, int var1, int var2)
{
    
    // コンテナからエンティティのクラス データを取得
    MISSILE* e = ( (MISSILE*)entity-&gt;data );
    
    
    // ミサイルエンティティに関連する全てのメッセージを処理
    switch(message)
    {
        // クラス操作
        case EM_CLSNAME : strcpy((char*)var1, className); return(TRUE);
        case EM_CLSINIT : return( ClsInit((char*)var1) );
        case EM_CLSFREE : return( ClsFree() );

        // 作成と破棄
        case EM_CREATE  : return( Create(entity) );
        case EM_SHUTDOWN: return( Shutdown(THISENT) );
        case EM_DESTROY : return( Destroy(entity, THISENT) );
        case EM_START   : return( Start(THISENT) );

        // 標準アクション
        case EM_UPDATE  : return( Update(THISENT, INT2FLOAT(var1)) );
        case EM_DRAW    : return( Draw(THISENT) );

        // データアクセス
        case EM_SETNAME : strncpy(THISENT-&gt;name, (char*)var1, ENT_NAME_LEN); return(TRUE);
        case EM_GETNAME : strcpy((char*)var1, THISENT-&gt;name); return(TRUE);
        case EM_SETPOS  : V3Copy(&amp;THISENT-&gt;position, (VECTOR3*)var1); return(TRUE);
        case EM_SETVEL  : V3Copy(&amp;THISENT-&gt;velocity, (VECTOR3*)var1); return(TRUE);
        case EM_SETDIR  : return( SetDirection(THISENT, (VECTOR3*)var1) );
        
        // Win32のDefWindowProcと同様の粗野な形の継承をサポートする。
        default         : return( DefEntityProc(entity, message, var1, var2) );
    }
    return(TRUE);
}

■ クラスリスト

 外側の世界に対してはWin32のウィンドウクラスと同様にエンティティクラスはメッセージ処理関数だけを公開する。
 テキスト名でクラスを作成して参照できるように、クラスリストはこれらのメッセージハンドラのリンクリストや
 ベクトルを保持する。
 
 
 struct entityClass
 {
    char name[64];              // 一意なクラス名
    ENT_PROC* clsProc           // クラスのメッセージ ハンドラ
    struct entityClass* next    // リスト内の次のクラス
 };


 登録はEntCreateClass関数で行う。
 
 1) エントリをクラスリストに追加し、EM_CLSNAMEメッセージをclsProcに送り、クラスに付随するテキスト名を取り出す。
 
 2) EM_CLSINITメッセージをclsProcに送り、リソースのロードのような、1回限りの初期化を行う機会をクラスに与える。
 
 
 ゲームで使う様々なクラスの初期化は、次のようなコードで起動時に行えば良い。
 
 // par1: エンティティがデータを見つけるパス
 void GameInitClasses( char* dataPath )
 {
    EntCreateClass( playerProc, dataPath, 0 );                  // プレイヤーを登録
    EntCreateClass( missileProc, dataPath, 0 );                 // ミサイルを登録
    
    // ... 以下初期化が続く
 }
 
 void EntDestoryAllClasses()
 {
    // EM_CLS_FREEメッセージを1つ又は全ての登録クラスに送って後始末を楽にする。
 }

■ エンティティマネージャ

 エンティティマネージャは個々のエンティティの作成と削除を行い、それらを含むリストやツリーを管理する。
 エンティティのメッセージ処理関数とプライベートなデータへのポインタを、単純な汎用コンテナ構造で
 エンティティを参照する。
 
 
 struct entityTag
 {
    ENT_PRPC*           Proc;                   // メッセージ処理関数
    void*               data;                   // エンティティのカスタムデータ
    int                 guid;                   // ネット同期用の一意なID
    struct entityTag*   parent;                 // 親またはNULL
    struct entityTag*   prevSibling;            // 前の兄弟またはNULL
    struct entityTag*   nextSibling;            // 次の兄弟又はNULL
    struct entityTag*   child;                  // 最初の子
 };
 
 
 &lt;エンティティマネージャの鍵となる操作&gt;
 
--------------------------------------------------------------------------------

 ENTITY* EntCreateEntity( char* className, ENTITY* parent, int var1, int var2 );
 
 
 1)この関数はclassNameをクラスリストで参照し、見つかったら新しいENTITY構造体を
   作成し、parentの子としてエンティティツリーに付加する。
 
 2)クラスのメッセージ処理関数Procへのポインタを保存し、直ちにvar1,var2パラメータ
   でProcにEM_CREATEメッセージを送る。CREATEハンドラで、エンティティはクラスデータ
   用の領域を確保し、dataでそれを指す。
 
--------------------------------------------------------------------------------
 
 int EntDestoryEntity( ENTITY* ent );
 
 DESTOROYメッセージに応じて内部で呼び出され、ENTITYコンテナ構造体を開放して、
 ツリーから取り出す。実際にエンティティを破棄するには、EM_DESTOYメッセージを
 送るだけだ。
 
--------------------------------------------------------------------------------
 
 int ENtSendMessage( ENTITY* ent, EM message, int var1, int var2 );
 
 与えられたパラメーターでメッセージを個々のエンティティに送る
 
--------------------------------------------------------------------------------

 int EntSendMessageGuid( int guid, EM message, int var1, int var2 );

 メッセージをエンティティポインタではなく、guid経由で個々のエンティティに送る。
 これはポインタが意味をなさない[[ネットワーク]]同期に役立つ。

--------------------------------------------------------------------------------
 
 void EntSendMessagePre( ENTITY* ent, EM message, int var1, int var2 );
 
 メッセージをエンティティとその全ての子に前順序で送る。メッセージの処理後にFALSE
 を返すエンティティがあれば、再帰を中断する。
 
 エンティティツリーがシーングラフや衝突ツリーとしても使えるように、これらは階層
 カリングをサポートする。これに似た、中断しない関数も役に立つかもしれない。
 
--------------------------------------------------------------------------------
 
 拡張案
 
 ・エンティティを名前で探したり、エンティティツリーを並び替えたり、節点ごとに
   コールバックを発行するエンティティを反復する機能をサポート。
 
 
■ メッセージによるゲームループ

 ほとんど全ての『ゲームコード』は、結局エンティティ自身の内部に存在するので、ループは
 主としてメッセージ配送者になる。
 
 
static void GameProcessInput()
{
   // map input events, then send appropriate events to the entity(ies)
   // currently under human control
   GetInputEvents(&amp;inputEvent);                                 // イベントデータの入力
   MapInputEventsToGameEvents(&amp;inputEvent, &amp;gameEvent);         // マップの衆力
   EntSendMessage(entPlayer, EM_USERINPUT, (int)&amp;gameEvent, 0); // プレイヤー
} 



static void GameUpdateWorld()
{
    EntSendMessagePre(entWorld, EM_UPDATE, GetElapsedMs(), 0);
    EntSendMessagePre(entWorld, EM_POSTUPDATE, 0, 0);
    EntCleanup(entWorld);
}


static void GameDraw()
{
    // 全てのエンティティに自分をレンダリングさせ、オーバーレイを行う
    EntSendMessagePre(entWorld, EM_DRAW,        0, 0);
    EntSendMessagePre(entWorld, EM_DRAWSHADOW,  0, 0);
    EntSendMessagePre(entWorld, EM_DRAWOVERLAY, 0, 0);    

    // デバッグモードなら、エンティティの追加情報を描画する
    if (debugMode)
        EntSendMessagePre(entWorld, EM_DRAWDEBUG, 0, 0);

    // 現在選択中のエンティティの編集状態を表示
    if (editMode)
        EntSendMessage(entBeingEdited, EM_DRAWEDIT, 0, 0);        
}    </description>
    <dc:date>2006-11-18T17:01:59+09:00</dc:date>
    <utime>1163836919</utime>
  </item>
    <item rdf:about="https://w.atwiki.jp/mofnotony/pages/9.html">
    <title>グラフィック</title>
    <link>https://w.atwiki.jp/mofnotony/pages/9.html</link>
    <description>
      *グラフィック
コンデレ
#ref(st063.jpg)    </description>
    <dc:date>2006-11-02T13:11:33+09:00</dc:date>
    <utime>1162440693</utime>
  </item>
    <item rdf:about="https://w.atwiki.jp/mofnotony/pages/1.html">
    <title>トップページ</title>
    <link>https://w.atwiki.jp/mofnotony/pages/1.html</link>
    <description>
          </description>
    <dc:date>2006-11-01T16:42:29+09:00</dc:date>
    <utime>1162366949</utime>
  </item>
    <item rdf:about="https://w.atwiki.jp/mofnotony/pages/2.html">
    <title>メニュー</title>
    <link>https://w.atwiki.jp/mofnotony/pages/2.html</link>
    <description>
          </description>
    <dc:date>2006-11-01T16:38:13+09:00</dc:date>
    <utime>1162366693</utime>
  </item>
    <item rdf:about="https://w.atwiki.jp/mofnotony/pages/8.html">
    <title>ネットワーク</title>
    <link>https://w.atwiki.jp/mofnotony/pages/8.html</link>
    <description>
      *ネットワーク    </description>
    <dc:date>2006-11-01T16:33:55+09:00</dc:date>
    <utime>1162366435</utime>
  </item>
    <item rdf:about="https://w.atwiki.jp/mofnotony/pages/6.html">
    <title>仕様</title>
    <link>https://w.atwiki.jp/mofnotony/pages/6.html</link>
    <description>
      *仕様
**プログラム
-[[クライアント]]
-[[ネットワーク]]
**グラフィック
-[[グラフィック]]    </description>
    <dc:date>2006-11-01T16:32:52+09:00</dc:date>
    <utime>1162366372</utime>
  </item>
    <item rdf:about="https://w.atwiki.jp/mofnotony/pages/5.html">
    <title>テスト用</title>
    <link>https://w.atwiki.jp/mofnotony/pages/5.html</link>
    <description>
      *好きにテストしてみれ    </description>
    <dc:date>2006-11-01T16:28:10+09:00</dc:date>
    <utime>1162366090</utime>
  </item>
    <item rdf:about="https://w.atwiki.jp/mofnotony/pages/4.html">
    <title>企画書</title>
    <link>https://w.atwiki.jp/mofnotony/pages/4.html</link>
    <description>
          </description>
    <dc:date>2006-11-01T16:23:18+09:00</dc:date>
    <utime>1162365798</utime>
  </item>
  </rdf:RDF>
