2

Java ライブラリArtemisの移植を検討しています。エンティティ システム フレームワーク。まだ始めていません。代わりに、Java コードがどのようにまとめられているかという内部作業を分析してきました。CPP ポートが半分しか機能していないことはわかっています。

私は両方のコードを見て、Java コードが特定のものをよりエレガントに配置していることに気付きました。そして、主に次のこと。

package com.artemis;

import java.util.HashMap;

public class ComponentTypeManager {
    private static HashMap<Class<? extends Component>, ComponentType> componentTypes = new HashMap<Class<? extends Component>, ComponentType>();

    public static final ComponentType getTypeFor(Class<? extends Component> c){
        ComponentType type = componentTypes.get(c);

        if(type == null){
            type = new ComponentType();
            componentTypes.put(c, type);
        }

        return type;
    }

    public static long getBit(Class<? extends Component> c){
        return getTypeFor(c).getBit();
    }

    public static int getId(Class<? extends Component> c){
        return getTypeFor(c).getId();
    }
}

そして、componentType「オブジェクト」

package com.artemis;

public class ComponentType {
    private static long nextBit = 1;
    private static int nextId = 0;

    private long bit;
    private int id;

    public ComponentType() {
        init();
    }

    private void init() {
        bit = nextBit;
        nextBit = nextBit << 1;
        id = nextId++;
    }

    public long getBit() {
        return bit;
    }

    public int getId() {
        return id;
    }
}

基本的に、componentTypeManager が行うことは、componentType をクラス タイプにマップすることです。これにより、新しいコンポーネントを追加するときに動的になります。

C++ ポート ソリューションは次のとおりです。

#ifndef __COMPONENT_TYPE_H__
#define __COMPONENT_TYPE_H__

namespace SGF
{
    enum ComponentType 
    {
        CT_TRANSFORM = 0,
        CT_HEALTH,
        CT_RENDERABLE,
        CT_RIGID_BODY,
        CT_JOINT,

        CT_LAST
    };

    // Component type bits. Used by the entity systems to determine if an entity is compatible.
    const unsigned int CT_TRANSFORM_BIT  = 1 << CT_TRANSFORM;
    const unsigned int CT_HEALTH_BIT     = 1 << CT_HEALTH;
    const unsigned int CT_RENDERABLE_BIT = 1 << CT_RENDERABLE;
    const unsigned int CT_RIGID_BODY_BIT = 1 << CT_RIGID_BODY;
    const unsigned int CT_JOINT_BIT      = 1 << CT_JOINT;
};

#endif

ここでは、ComponentManager は完全に省略されています。代わりに列挙型が使用されます。これに関する私の問題は、新しいコンポーネントタイプを列挙子に追加し、定数を「タイプ」識別子として追加する必要があるという事実です。Java フレームワークでは、コンポーネント クラス タイプを渡してその ID を識別することができます。

私の質問は、新しいコンポーネントごとに列挙子の型をハードコーディングせずに、型を渡して Java コードのような id をマップするという同様の効果を得るにはどうすればよいでしょうか? C++ がクラス型を引数としてサポートしていないことは知っています。だから、これは私にとってかなり気が遠くなるようなものです。

4

1 に答える 1

2

コンポーネント タイプを指定してコンポーネントをインスタンス化する予定がなく、コンポーネントComponentに 1 つ以上のvirtual機能があると想定している限り、目的にはRTTIを使用するだけで十分です。unordered_mapの代わりに を使用し、 を に置き換えることができHashMapます。Class<C>type_info

私が確信していないことの 1 つは、返される正確なビットをどのように知るかということです。マップ内にパラメーターが見つからない場合ComponentType、コードはパラメーターなしでインスタンス化されますが、異なるインスタンスは異なるパターンの設定ビットと未設定ビットを返すと想定されています。ComponentTypeただし、これは、ハッシュ マップが既知のコンポーネント タイプ用に事前設定されているためだと思います。

于 2012-06-23T17:36:56.140 に答える