XNA与多个类相交/碰撞?

时间:2012-04-29 10:20:52

标签: c# xna collision intersect

在过去的12个小时里,我一直在尝试“所有”我能想到的不同方法,以便在XNA(4.0)中正确地使两个矩形相交/测试碰撞。

我有三个类(只是示例名称):

  • Game1.cs
  • Player.cs
  • Man.cs

在Game1中,我加载了这样的内容:

//在Game1的开头:

    Player player;
    Man man;

// LoadContent:

    man = new Man(Content.Load<Texture2D>("ManImage"), new Rectangle(440, 310, 150, 98));
    player = new Player(Content.Load<Texture2D>("playerSheet"), new Vector2(40, 420), 50, 44);

但是,我想检查人与玩家之间的碰撞,但我不明白如何“加入”这两个类,以便能够在Game1中做一个if(相交)(如果这是做它的地方)。

播放器矩形如下所示:

playerRect = new Rectangle(currentFrame * frameWidth, 0, frameWidth, frameHeight);

我刚刚完全“代码盲”,或者什么?任何能够帮助我解决这个问题的人都会在经过12小时的碰撞测试后失去动力。

1 个答案:

答案 0 :(得分:1)

对于这两个类,您可以添加属性

public Rectangle PositionRectangle { get; private set; }

然后,在相关的构造函数中,您需要启动此属性

public Man(..., Rectangle rectangle)
{
    PositionRectangle = rectangle;
}

public Player(..., Vector2 position, int width, int height)
{
    PositionRectangle = new rectangle((int)position.X, (int)position.Y, width, height);
}

您无需担心要显示的帧,因为这与源矩形有关,而与目标矩形无关(这是什么)你需要测试碰撞。)

然后您可以轻松地测试这些碰撞

if(man.PositionRectangle.Intersects(player.PositionRectangle))
{
    //collision logic
}

当然,您需要在更改位置时更新这些矩形(如果位置更改,则需要更新宽度和高度)


轻微编辑(或更好的版本)

如果您想轻松定位Man and Player而不必担心矩形的更新方式,可以这样设置:

class Man
{
    Texture2D _texture;

    public Vector2 Position { get; set; }
    public int Width { get; set; } 
    public int Height { get; set; }

    public Rectangle PositionRectangle
    {
        get
        {
            return new Rectangle((int)Position.X, (int)Position.Y, Width, Height);
        }
    }

    public Man(Texture2D texture)
    {
        this._texture = texture;
        this.Width = texture.Width;
        this.Height = texture.Height;
    }

    ... //other man related logic!
}

class Player
{
    Texture2D _texture;
    int _frameCount;
    int _currentFrame;
    //other frame related logic...

    public Vector2 Position { get; set; }
    public int Width { get; set; } 
    public int Height { get; set; }

    public Rectangle PositionRectangle
    {
        get
        {
            return new Rectangle((int)Position.X, (int)Position.Y, Width, Height);
        }
    }

    public Rectangle SourceRectangle
    {
        get
        {
            return new Rectangle(Width * _currentFrame, 0, Width, Height);
        }
    }

    public Player(Texture2D texture, int frameWidth, int frameCount)
    {
        this._texture = texture;
        this.Width = frameWidth;
        this.Height = texture.Height;
        this._frameCount = frameCount;
        this._currentFrame = 0;
        //etc...
    }

    ... //other player related logic! such as updating _currentFrame

    public Draw(SpriteBatch spriteBatch)
    {
         spriteBatch.Draw(_texture, PositionRectangle, SourceRectangle, Color.White);
    }
}

这里我举例说明了如何利用属性访问器动态生成相关的矩形!

您使用PositionRectangle来确定您的玩家(或玩家)在屏幕上的位置,并使用SourceRectangle来确定您要绘制的纹理部分。

此外,如果您的人员和玩家的宽度和高度不会改变,那么您应该将他们的set访问者设置为private

当您需要更改位置时,只需设置其位置属性

即可
man.Position = new Vector2(100, 100); //i.e.

并且您的碰撞和绘制逻辑将自动使用新的矩形而无需任何进一步干预!

希望你喜欢它!

EDIT2

关于源矩形是公开的,只需要从外部绘制这些矩形(例如Game1调用spriteBatch.Draw(player.Texture, player.PositionRectangle, player.SourceRectangle, Color.White);)。

如果您像示例中那样(从内部)绘制它,您可以废弃整个public Recangle SourceRectangle{...}事物并直接在绘图中使用该矩形:

    public Draw(SpriteBatch spriteBatch)
    {
         spriteBatch.Draw(_texture, PositionRectangle, new Rectangle(Width * _currentFrame, 0, Width, Height), Color.White);
    }