DonerComponentsは、ビデオゲームを開発するためのC ++ 14コンポーネントベースのゲームオブジェクトモデルフレームワークです。
このコンセプトに慣れていない場合は、Exampleプロジェクトまたはチュートリアルをご覧になり、試してみることをお勧めします。
ここで安定したリリースを取得できます。
または、現在の開発バージョンを以下で確認できます。
git clone https://github.com/Donerkebap13/DonerComponents.git
git submodule update --init --recursive 。
また、メールで直接私に連絡することができます。提案がある場合、またはバグが見つかった場合は、新しい問題を作成することをheしないでください。
donercomponents_asteroids_exampleは、 donercomponentsの使用方法を示すために作成したプロジェクトの例です。それは本当にシンプルなアスタロイド系志望のクローンです。そのプロジェクトでの私の意図は、次のようなフレームワークが現在サポートしているすべての機能を示すことです。
ここでは、DonerComponentsのメインシステムの基本的な使用法を説明しようとします。これを読んだ後、物事がどのように整理され、どのように使用できるかについての基本的な知識が得られます。より深く理解するために、私はあなたが例プロジェクトを見ることをお勧めします。
CDonerComponentsSystems 、すべてのDonerComponentsに初期化してアクセスできるシングルトンです。初期化する必要があります。
# include < DonerComponents/CDonerComponentsSystems.h >
DonerComponents::CDonerComponentsSystems::CreateInstance ();
DonerComponents::CDonerComponentsSystems::Get ()->Init();更新:
float elapsed = ...;
DonerComponents::CDonerComponentsSystems::Get ()->Update(elapsed);そして破壊された:
DonerComponents::CDonerComponentsSystems::DestroyInstance (); DonerComponents::CGameObjectはDonerComponentsの主な俳優です。このクラスには、その動作を定義する異なるDonerComponents::CComponentを含めることができます。また、親と子供に関する情報もあります。また、ポッドメッセージを受け取り、コンポーネントと子供に転送することもできます。最後になりましたが、タグ付けすることもできます。
新しいGameObjectを作成することは、次のように簡単です。
# include < DonerComponents/gameObject/CGameObject.h >
DonerComponents::CGameObjectManager* gameObjectManager = DonerComponents::CDonerComponentsSystems::Get()-> GetGameObjectManager ();
DonerComponents::CGameObject *gameObject = gameObjectManager-> GetNewElement (); GetNewElement(); GameObjectsが生成されていない限り、有効なDonerComponents::CGameObjectを返します。デフォルトでは、DonerComponentsには4096のGameObjectsが同時に生きていることがあります。この値は、Compiler Flag -DMAX_GAME_OBJECTS=4096で最大8.192 GameObjectsを介して変更可能です。
DonerComponentsはプレハブの定義をサポートするため、ユーザーは必要な場所に再利用するための特定のGameObject階層を定義できます。
# include < DonerComponents/gameObject/CPrefabManager.h >
DonerComponents::CGameObjectManager* prefabManager = DonerComponents::CDonerComponentsSystems::Get()-> GetPrefabManager ();
prefabManager-> RegisterPrefab ( " prefabName " , anyGameObjectCreatedPreviously);プレハブは、JSONファイルからもロードできます。
DonerComponents::CComponent 、DonerComponentsの任意のコンポーネントの基本クラスです。コンポーネントは、集約によりGameObjectの動作を定義します。特定のメッセージを聞き、それに応じてアクションを実行できます。新しいコンポーネントはこのクラスから継承する必要があり、必要に応じていくつかの基本的な方法を実装できます。ユーザーは、最大512の異なるコンポーネントを登録できます。
新しいコンポーネント作成の例は次のとおりです。すべてのメソッドの実装はオプションです。
# include < DonerComponents/component/CComponent.h >
class CCompFoo : public DonerComponents ::CComponent
{
public:
void DoInit () override { m_foo = 0 . 0f ; }
void DoUpdate ( float dt) override { m_foo += dt; }
void DoDestroy () override { m_foo = 0 . 0f ; }
void DoActivate () override { }
void DoDeactivate () override { }
private:
float m_foo;
};このコンポーネントをシステムに登録するには、GameObjectを使用できるように、次のことを行う必要があります。
# include < DonerComponents/component/CComponentFactoryManager.h >
static constexpr int amountOfFooComponentsAvailable = 512 ;
ADD_COMPONENT_FACTORY ( " foo " , CCompFoo, amountOfFooComponentsAvailable); DonerComponents::CDonerComponentsSystemsを初期化した後、Macro ADD_COMPONENT_FACTORYを使用してコンポーネントをシステムに登録し始めることができます。受信する文字列は、JSONファイルからGameObjectを解析しながらコンポーネントを識別することです。最後のパラメーターは、使用可能なコンポーネントの数です。 GameObjectsと同様に、同じ種類の最大8.192コンポーネントが同時に生きています。
コンポネットがシステムに登録されると、2つの異なる方法でGameObjectに追加できます。
DonerComponents::CComponent* component = gameObject->AddComponent<CCompFoo>();
// same as
CCompFoo* component = gameObject->AddComponent<CCompFoo>();
// or
DonerComponents::CComponent* component = gameObject-> AddComponent ( " foo " );
// same as
CCompFoo* component = gameObject-> AddComponent ( " foo " );DonerComponentsでは、コンポーネントは、システムに登録された順序で、タイプごとに1つのタイプで更新されます。したがって、例では:
ADD_COMPONENT_FACTORY ( " foo " , CCompFoo, 128 );
ADD_COMPONENT_FACTORY ( " bar " , CCompBar, 128 );既存のすべてのCCompFoo 、既存のすべてのCCompBarコンポーネントを更新する前に、順次更新されます。
DonerSerializerを使用して、 JSONで変更されるデータが公開されるデータを定義できます。ここで使用する方法を確認できます。ここでは、例を示します。
class CCompFoo : public DonerComponents ::CComponent
{
DONER_DECLARE_COMPONENT_AS_SERIALIZABLE (CCompFoo)
public:
CCompFoo ();
private:
float m_dummy1;
std::vector<std::string> m_dummy2;
};
DONER_DEFINE_REFLECTION_DATA (CCompFoo,
DONER_ADD_NAMED_VAR_INFO (m_dummy1, " dummy1 " ),
DONER_ADD_NAMED_VAR_INFO(m_dummy2, " dummy2 " )
) m_dummy1とm_dummy2を公開した後、次のようなJSONでそれらの値を定義できます。
{
"root" : {
"name" : " test1 " ,
"components" : [
{
"name" : " foo " ,
"dummy1" : 1.0 ,
"dummy2" : [ " Test1 " , " Test2 " , " Test3 " ]
}
]
}
}JSONからの読み方についての詳細な見方については、これを確認してください。
DonerComponentsは、異なるGameObjectsとコンポーネント間で対話するメッセージシステムをサポートしています。メッセージは、ユーザーによって定義された任意の構造体/クラスである可能性があります。通常、それはデータのみ、ロジックは含まれませんが、これには制限はありません。これはDonerComponents::CComponent特定のメッセージを聞くことができる方法です。
// Somewhere in your code
struct SDummyMessage {
SDummyMessage ( int foo, int bar)
: m_foo(foo), m_bar(bar) {}
int m_foo = 0 ;
int m_bar = 0 ;
}
// Inside your component
CCompFoo::RegisterMessages () {
RegisterMessage (&CCompFoo::OnDummyMessage);
}
void CCompFoo::OnDummyMessage ( const SDummyMessage& message) {
// ...
}必要なメッセージを登録した後、次のようなメッセージの送信を開始できます。
SDummyMessage message ( 2 , 3 );
// This will propagate the message to all gameObject's components.
gameObject-> SendMessage (message);
// This will propagate the message to all gameObject's components and its children's components.
gameObject-> SendMessage (message, DonerComponents::ESendMessageType::Recursive);
// This won't send the message to the current gameObject but it's children.
gameObject-> SendMessageToChildren (message);
// Same as before but recursively through all gameObject's children and children's children.
gameObject-> SendMessageToChildren (message, DonerComponents::ESendMessageType::Recursive); SendMessage 、同じフレームですぐにメッセージを送信します。フレームの終了までメッセージの送信を遅らせる場合は、代わりにPostMessageを使用してください。
最後になりましたが、すべての生きているGameObjectsにメッセージを送信する場合は、 BroadcastMessageを使用できます。
SDummyMessage message ( 2 , 3 );
// This will propagate the message to all GameObjects alive.
gameObjectManager-> BroadcastMessage (message); DonerComponents::CHandle一種の単一スレッドスマートポインターです。彼らは、特定のDonerComponents::CGameObjectまたはDonerComponents::CComponentを指しています。それらがまだ有効であるかどうか、またはコード内のどこかで破壊されたかどうかを知っています。 DonerComponents::CHandleのサイズは32ビットです。 DonerComponentsでの作業方法は、 DonerComponents::CGameObjectまたはDonerComponents::CComponentの生のポインターを保存しないことです。常にDonerComponents::CHandle保存するため、指摘する要素がまだ有効かどうかを確認できます。 DonerComponents::CHandle DonerComponents::CGameObjectまたはDonerComponents::CComponentにキャストできます。キャストが有効であり、要素がまだ存在する場合、要素への有効なポインターを返します。それ以外の場合は、 nullptrを返します。これが例です:
# include < DonerComponents/handle/CHandle.h >
# include < DonerComponents/gameObject/CGameObjectManager.h >
using namespace DonerComponents ;
CHandle gameObjectHandle = m_gameObjectManager-> GetNewElement ();
if (gameObjectHandle) {
// CGameObjectManager has return a valid CGameObject
} else {
// CGameObjectManager has run out of CGameObjects
}
CGameObject* gameObject = gameObjectHandle;
// gameObject will be valid as gameObjectHandle points to an alive gameObject
m_gameObjectManager-> DestroyGameObject (&gameObject);
// gameObject is nullptr at this point
// gameObjectHandle == false as it points to a destroyed gameObject.また、ハンドルを介してメッセージを送信できます。ハンドルが有効な場合、メッセージは適切に伝播されます。それ以外の場合、メッセージは無視されます。
DonerComponents::CHandle handle = gameObject;
SDummyMessage message ( 2 , 3 );
handle.SendMessage(message);
タグは、GameObjectsに情報を追加する方法であるため、それらをフィルタリングして、特定のタグなどのGameObjectsのみにメッセージを送信できます。システムにタグを追加する方法は2つあります。後で使用できます。最初に、コードで直接宣言します。
# include < DonerComponents/tags/CTagsManager.h >
DonerComponents::CTagsManager* tagsManager = DonerComponents::CDonerComponentsSystems::Get()-> GetTagsManager ();
tagsManager-> RegisterTag ( " Tag1 " );
tagsManager-> RegisterTag ( " TagN " );2つ目は、JSONファイルからそれらを解析します。
tagsManager-> ParseTagsFromFile ( " path/to/your/tags.json " );tags.jsonファイルの形式は、これに似たものです。
{ "tags" : [ " Tag1 " , " tag2 " , " tagN " ] }DonerComponentsは、 DonerSerializerのおかげでJSONを使用してディスクからの読み込みをサポートしているため、アプリケーションを実行するたびにコードでゼロから構築する代わりに、アセットとして保存できるプレハブまたはシーンを作成する方法があります。基本的な使用法は次のとおりです。
# include < DonerComponents/GameObjects/CGameObjectParser.h >
DonerComponents::CGameObjectParser parser;
CGameObject* gameObject = parser.ParseSceneFromFile( " path/to/your/scene.json " );Scene.jsonファイルの形式は、これに似たものです。
{
"root" : {
"name" : " test1 " ,
"tags" : [ " tag1 " , " tag2 " , " tag3 " ],
"components" : [
{
"name" : " comp_location " ,
"x" : 1 ,
"y" : -3 ,
"z" : 9
},
{
"name" : " comp_rotation " ,
"radians" : 0.2
}
],
"children" : [
{
"name" : " test11 " ,
"tags" : [ " tag1 " , " tag3 " ]
},
{
"name" : " test12 " ,
"initiallyActive" : false
}
]
}
}シーンを解析する代わりに、プレハブを解析してDonerComponents::CPrefabManagerに自動的に登録する場合は、 ParsePrefabFromFileを呼び出す必要があります。
# include < DonerComponents/GameObjects/CGameObjectParser.h >
DonerComponents::CGameObjectParser parser;
CGameObject* gameObject = parser.ParsePrefabFromFile( " path/to/your/prefab.json " );これを行った後、プレハブは、新しい解析されたシーンが使用できるようになります。
DonerComponentsは、他のプレハブを含むプレハブをサポートし、コンポーネントの情報をオーバーライドできます。
Prefab1.json
{
"root" : {
"name" : " Prefab1 " ,
"components" : [
{
"name" : " comp_location " ,
"x" : 1 ,
"y" : -3 ,
"z" : 9
},
{
"name" : " comp_rotation " ,
"radians" : 0.2
},
{
"name" : " sprite " ,
"texture" : " res/common/textures/asteroid_med.png "
}
]
}
}Prefab2.json
{
"root" : {
"name" : " Prefab2 " ,
"prefab" : " Prefab1 " ,
"components" : [
{
"name" : " sprite " ,
"texture" : " res/common/textures/flower_big.png "
}
]
}
}Scene.json
{
"root" : {
"name" : " root " ,
"prefab" : " Prefab2 " ,
"components" : [
{
"name" : " comp_location " ,
"x" : 0 ,
"y" : 0 ,
"z" : 0
}
]
}
}