0

私はC#とXNA 4.0、およびFarseer Physics Engine(Box2Dに非常に似ています)を使用しており、OBlock、LBlockなどを派生させるBlockクラスを持っています。

ブロックは次のとおりです。

class Block
{
    public Body m_body;
    public virtual void Draw(SpriteBatch spriteBatch) { }

    public virtual void RemoveBody(World world)
    {
        //world.RemoveBody(m_body);
    }
}

リスト内のオーバーライドされたバージョンにアクセスできるように、これらのメソッドやフィールドなどのみを入力しました

したがって、オーバーライドされたバージョンは次のようになります:OBlock.cs

class OBlock : Block
{

    private static Texture2D blockImg; //I load this in LoadContent so I don't have loads of Texture2Ds
    public new Body m_body; //Is this right?

    public OBlock(World world, Vector2 position)
    {
        m_body = BodyFactory.CreateBody(world, position); // Create the body, changing it from null
        FixtureFactory.AttachRectangle(Game1.blockSide *2, Game1.blockSide *2, 1.0f, new Vector2(0, 0), m_body); //This bit changes between classes
        m_body.BodyType = BodyType.Dynamic;

    }

    public override void RemoveBody(World world)
    {
        world.RemoveBody(m_body);
    }

    public static void LoadImage(Texture2D tex)
    {
        OBlock.blockImg = tex;
    }

    public override void Draw(SpriteBatch spriteBatch)
    {

        Vector2 position = m_body.Position * Game1.MetreInPixels;
        Vector2 origin = new Vector2(blockImg.Width / 2, blockImg.Height / 2);

        float rotation = m_body.Rotation;

        spriteBatch.Begin();

        spriteBatch.Draw(blockImg, position, null, Color.White, rotation, origin, Game1.BLOCK_SCALE, SpriteEffects.None, 1);

        spriteBatch.End();

        base.Draw(spriteBatch);
    }
}

LBlock、ZBlockなどもありますが、コメントした部分を除けば、どれも非常によく似ています。

それから私はそれらをすべて入れます

List<Block> blocks //As a field in Game1

blocks = new List<Block>(); // In LoadContent after loading images

私がやろうとしているのは、タイプに関係なく、リスト内の任意のブロックのm_bodyにアクセスすることです。

blocks[index].m_body.DOSTUFF();

どうやらm_bodyは常にnullです...

4

3 に答える 3

2

public new Body m_body; //これは正しいですか?

いいえ!これにより、ストレージの2番目のビットが宣言されます。つまり、Blockのm_bodyとOBlockのm_bodyがあり、一方だけをnull以外に初期化します。m_bodyへの特定の参照が何を解決するかについての正確な規則は、おそらく理解するには退屈すぎます。

おそらく、上記の行を完全に削除し、継承の基本に慣れるために時間を費やす必要があります(例: http: //msdn.microsoft.com/en-gb/library/ms173149.aspx )。

于 2013-02-03T09:29:12.593 に答える
0
public new Body m_body;

これは正しくないです。クラスからのm_bodyfrom Block(btwとマークする必要がありますabstract)は、それから派生するすべてのクラスに表示されます。あなたが今していることは隠蔽と呼ばれ(これは常にimoを避けるべきです)、それは様々な合併症を引き起こします。

これで、それぞれOBlockに2つのメンバーが含まれるようになりましm_bodyた。1つはに属しBlock、もう1つはに属しOBlockます。これにより、クラスで参照するときはいつでもthis.m_body、に属するフィールドOBlockを割り当て、宣言されたままにすることができます。これは、メンバーを非表示にすることに伴う奇妙な問題の1つです。m_bodyOBlockm_blockBlock

Block myBlock = new OBlock();
// myBlock.m_block is null, because myBlock is of type block, and remember,
// the m_block belonging to Block is never assigned to, only the one belonging
// to OBlock

これは期待どおりに機能しますが、次のようになります。

OBlock myOBlock = new OBlock();
// myOBlock.m_block isn't null, because it was assigned to in the constructor.

だから隠れることは避けてください!削除する

public new Body m_body;

コードファイルから、とにかくそれから派生するすべてのクラスによってm_block宣言されたで継承されるので、あなたは行ってもいいです。Block

于 2013-02-03T10:34:56.453 に答える
0
public new Body m_body; 

これにより、基本クラスのm_bodyが非表示になります。したがって、基本的には、派生クラス(基本クラスではない)でm_bodyの新しいインスタンスを定義しています。したがって、基本クラスのm_bodyは初期化されないため、nullになるのはそのためだと思います。

したがって、代わりにその特定の行を削除します。これは、すべての派生クラスについて、すべてがBlockクラスから派生しているため、m_bodyがすでに定義されているためです。詳細については、このMSDNの記事を参照してください。

于 2013-02-03T09:51:57.433 に答える