1

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

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

  • 游戏1.cs
  • 播放器.cs
  • 人.cs

在 Game1 中,我加载如下内容:

// 在 Game1 开始时:

    Player player;
    Man man;

// 加载内容:

    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(intersects) (如果那是这样做的地方)。

播放器矩形如下所示:

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

我只是在这里完全“盲目地编码”,还是什么?任何能够帮助我解决这个问题的人,在 12 小时的碰撞测试后,动力都下降了。

4

1 回答 1

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 和 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.

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

希望你喜欢!

编辑2

关于源矩形是公开的,你只需要从外部绘制它们(即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);
    }
于 2012-04-29T10:29:46.413 回答