3
\$\begingroup\$

I'm developing a 2D game. In the game, all entities can rotate 360 degrees. Each entity holds an angle value, and every frame it is drawn rotated around it's center by it's current angle value. For example:

enter image description here

An entity can 'shoot' another entity, a projectile. The Projectile is instantiated with a position and an angle. The position is calculated like so:

radius = entity.width / 2
angle = entity.angle
projectileX = entity.centerX + cos(angle) * radius
projectileY = entity.centerY + sin(angle) * radius

Example positions this calculation gives:

enter image description here

The angle the Projectile is instantiated with is the angle of the entity creating it. So if the entity's current angle value was 45, the angle of the new Projectile is going to be 45.

All of this creates a problem. I will demonstrate the steps leading to this problem:

1- An entity decides to shoot a Projectile. It's position is calculated like shown above.

enter image description here

2- A new Projectile is added to the game. It is instantiated with the position calculated in the previous step and with the angle of the entity instantiating it, for this example 45.

3- Every frame, each entity is drawn rotated around it's center by it's current angle value.

The angle of the new Projectile is 45, so it is drawn rotated around it's center by 45 degrees.

enter image description here

As you can see: after the rotation, the Projectile is no longer aligned correctly with the entity that created it. They are both rotated by the same angle, but the Projectile isn't 'pointing from the center' of the entity. It seems like it 'moved' a little to the side.

To clarify:

enter image description here

My question: how can I make the Projectile align correctly with the entity that created it? How can I make it still 'point from the middle' of the entity that created it, and not mess this up when rotating it around it's center?

\$\endgroup\$
1
  • 2
    \$\begingroup\$ In step 2, you add an entity at the calculated position... so why isn't the center of the projectile equal to the calculated position? In your illustration the entity is placed somewhere outside of the firing entity which is a step you didn't explain and that's probably also the root of your problem. To clarify: The projectile center (small red dot) should be identical to your calculated position (large red dot)... at least that's what your code snipped does. What your real code does is probably another issue. \$\endgroup\$
    – bummzack
    Jun 27, 2014 at 12:15

2 Answers 2

5
\$\begingroup\$

Rather than rotating the projectile about its own centre, then translating it to the end of the cannon, you could translate it first and then rotate the projectile using the origin of the tank (the tank's centre, in this case) by the tank's rotation.

Diagram

Here is how to rotate a point around another point in c++. (C# version)

Following that:

projectile.position = tank.position + cannonOffset;
projectile.position = rotatePoint(origin: tank.position,
                                  point: projectile.position,
                                  angle: tank.rotation);
projectile.rotation = tank.rotation;

Part of the reason for doing it this way is that you can make cannonOffset any relative position to the source entity. So if there is a gun on the front side (1,-1 instead of 2,0), this will still work.

\$\endgroup\$
5
  • \$\begingroup\$ You mean 'rotate the projectile around the center of the tank using the tank's rotation`? \$\endgroup\$
    – Aviv Cohn
    Jun 26, 2014 at 23:03
  • 1
    \$\begingroup\$ Yes. Maybe some code would help? \$\endgroup\$
    – jzx
    Jun 26, 2014 at 23:06
  • \$\begingroup\$ Thing is I want the Projectile to be completely independent of whatever instantiated it. Once it's created and added to the list in GameWorld, I want it to be independent. If I understand correctly, your solution means that every frame when drawing the projectiles, the GameDrawer would need to get the angle of the tank that originally created the projectile. Also the tank can obviously change it's angle, which shouldn't affect the projectile that was already fired. Can you think of a way to solve this problem with the projectile independent of whoever created it after creation? \$\endgroup\$
    – Aviv Cohn
    Jun 26, 2014 at 23:12
  • \$\begingroup\$ Or maybe I don't understand correctly? \$\endgroup\$
    – Aviv Cohn
    Jun 26, 2014 at 23:15
  • 1
    \$\begingroup\$ You would rotate the starting coordinates of the projectile about the tank's origin, only when it's created. \$\endgroup\$
    – jzx
    Jun 27, 2014 at 5:54
4
\$\begingroup\$

I would instantiate the Projectile at the (x,y) location of the Entity and then move it in the direction of the Entity by radius distance. In code, that would go:

projectileX = entity.x + cos(entity.angle) * radius;
projectileY = entity.y + sin(entity.angle) * radius;

Then add your projectile to the game world and send it off!

\$\endgroup\$
2
  • \$\begingroup\$ This is exactly what I'm doing (except entity.x is entityCenter.x). I forgot to add the entity.x + part in the original question, now it's there. Thanks for answering but this doesn't really address the problem I'm talking about. \$\endgroup\$
    – Aviv Cohn
    Jun 27, 2014 at 11:53
  • \$\begingroup\$ I don't really understand your question, then. You 'fire' your missile (instantiate it), then your entity turns. Why do you want your projectile to match the entity's angle after it's fired? \$\endgroup\$
    – user9513
    Jun 27, 2014 at 12:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .