How to "swing" bounding box and update collision for sprite swinging a weapon?

I have a simple question about sprite swinging weapons. I am making an RPG and would like something other than stabby-swords, so why not swinging swords?

I have a bounding rectangle for them, and the player equips them. Great, but I cannot grasp around my head how to swing both the sprite AND the bounding box (in XNA).

The sprite is easy, I specify it's origin and rotate by a specified amount over a certain amount of time (the swing time), but the bounding rectangle poses another issue for me.

Edit: A bit of clarity on my swinging animation. It's basically the player holding out their arm and the weapon swings in a curve from about +45 degree angle to a -45 degree angle.

Top-down Zelda style? One way to approach and simplify the problem is to instead of using an entire bounding box for the sword, reduce it to just one or two points of contact (lying inside the sword) and rotate them instead. In fact, the tip of the sword should be more than enough to detect most hits!

I've seen this used before in a few games. For instance this Muramasa-like sidescroller game made in XNA used points to handle player-enemy collisions. If I remember correctly from one of his YouTube comments, he placed collision points manually in each frame of the animations, and then uses them to detect hits with enemies.

In your case there's not much variation between frames. Just assign a single point to the sword's tip. When performing a stab, move that point back and forth along the player's Forward vector. When performing a slash, rotate it around the player. That's the only tricky part, which I'll describe below - rotating the point around the player no matter what transformations he has.

Implementation - How to rotate a point around the player

The easiest way to rotate a point around the player is to start with its definition in local space, i.e. in relation to the player, and then apply a series of transformations to get it into world space. This is not too hard to achieve. Here's a possible implementation:

(Step 1)

Calculate the player's world matrix. This is just a regular SRT matrix (scale-rotation-transform). Here's an example:

private Matrix GetPlayerWorldMatrix()
{
return Matrix.CreateScale(_playerScale, _playerScale, 1f) *
Matrix.CreateRotationZ(_playerRotation) *
Matrix.CreateTranslation(new Vector3(_playerPosition, 0f));
}


If your player can't rotate and/or scale just remove the corresponding lines.

(Step 2)

Start with the sword's position in local space, rotate it, and then apply the player's transform to it in order to get the final, world space position. It's simpler than it looks! Here's the code:

Vector2 localSword = new Vector2(0, _swordDistance);
Matrix swordMatrix = Matrix.CreateRotationZ(_swordRotation) * GetPlayerWorldMatrix();
Vector2 swordPosition = Vector2.Transform(localSword, swordMatrix);


All you need to do is interpolate the _swordRotation value when doing the swing.

(Step 3)

In my case I used the swordPosition for rendering so that you could see where it's placed, but in your case you should use that position for collision detection and hitting your mobs. Check the video and source code below for more details.

• Manual placement? Sounds interesting; I'll take a look.
– Ross
Commented Jan 7, 2012 at 22:27
• Manual placement makes sense for his game since every frame is extremely different from the previous ones. For a Zelda type game it's not really practical. I'll update my post within a few minutes with a possible implementation. Let me think this through a bit. Commented Jan 7, 2012 at 22:30
• Hmm, your method seems sound. I haven't been using matrices enough in my 2D game. Right now I'm researching more into collision points onto my weaponry to see how that works. I've been looking at Terraria and trying to research how they did their weapon swinging.
– Ross
Commented Jan 7, 2012 at 22:35
• Updated, what do you think? Commented Jan 7, 2012 at 23:32
• I like it, it suits my needs readily, thank you very much. It is quite awesome.
– Ross
Commented Jan 7, 2012 at 23:42