2013-02-03 55 views
0

我使用C#和XNA 4.0以及Farseer Physics Engine(非常类似于Box2D),并且有一个Block类,我从中派生出OBlock,LBlock,等从基类列表中访问派生类的字段

块如下:

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总是空。 ...

+0

什么,当你通过一行代码一步一个线,看的对象m_body发生什么呢? – SecurityMatt

回答

0
public new Body m_body; 

这是不对的。从Block类(您应该标记abstract btw)的m_body在从它派生的所有类中都可见。你现在正在做的是被称为隐藏(这应该总是避免imo),这会导致各种复杂化。

您现在已经制作了每个OBlock有两个成员m_body,一个属于Block,一个属于OBlock。它使得您在任何时候在OBlock类中参考this.m_body时,都可以指定字段属于OBlock,而Block仅在Block中声明m_block。这是一个带有隐藏成员怪异的并发症之一:

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; 

,你是好去,因为在Block宣布m_block由反正从中获取的所有类继承。

+0

的事情是,我想有我所有的不同的块,我可以一步虽然一个列表,并访问我想任何块的尸体。我是对的,这需要一个基类的列表来逐步通过,然后我把派生类放入? –

+0

@WilliamOsborne你循环遍历列表并用派生类yes来实例化它们中的每一个。如果你从你的代码中删除了'public new Body m_body''行,那么一切都会好起来的,并且可以像你所描述的那样工作。 – antonijn

+0

啊,是的,它现在有效。谢谢! –

2

public new Body m_body; //这是正确的吗?

不!这声明了第二个存储位 - 所以你有Block的m_body和OBlock的m_body,你只能初始化一个非空。关于m_body的特定引用将要解决的确切规则可能太无聊而不想理解。

您应该完全删除上面的行,并花一些时间来熟悉继承的基础知识,例如, http://msdn.microsoft.com/en-gb/library/ms173149.aspx

0
public new Body m_body; 

这隐藏了基类的m_body。所以基本上你是在派生类(而不是基类)中定义一个新的m_body实例。所以我认为这就是你的基类m_body将为空的原因,因为它从不初始化。

所以相反,删除该特定行,因为对于每个派生类,m_body已定义为所有派生自Block类。请通过this MSDN article了解更多详情。