0

I realise there are many questions on this subject. I'm not familiar enough with the geometry or maths to understand the solutions (haven't done maths in a long time), so I'd really appreciate someone helping me to work this out.

I'm trying to move a PictureBox object in C#, with three values: it's start position as a Point coordinate, the angle it is supposed to travel in, and the speed (how many pixels to move).

I tried this method from piecing together different answers:

    private Point MoveBullet(Point startPos, float angle, int bulletSpeed)
    {
        int X = Convert.ToInt32(startPos.X + (bulletSpeed * Math.Cos(angle)));
        int Y = Convert.ToInt32(startPos.Y + (bulletSpeed * Math.Sin(angle)));
        return new Point(X, Y);
    }

However, it only works when the angle is 0. The picture is a tank - when the picture is at the default orientation, with the tank turret facing to the right - the angle is 0. I know that I've probably messed this up by not placing angle 0 at the north, but I'm not sure how to correct the formula according to this rotation.

To illustrate what I mean about the setup, in the screenshot below the angle is 0 - you can see from the label recording the angle. The bullets shoot from the tank correctly - from left to right.

enter image description here

However, when I rotate the tank a bit so that it is facing towards the top-right, the angle is 315 (imagine it's moved 315 degrees clockwise, or 45 degrees anti-clockwise.) I would expect the bullets to fly towards the top-right, but they fly towards the bottom-right. It looks like it's off by about 90 degrees perhaps?

What mistake have I made, and how can I correct the movement formula so that the bullets fly at the expected angle?

enter image description here

Lou
  • 2,200
  • 2
  • 33
  • 66
  • 1
    The problem might be an inverted y axis. In WinForms, y values increase as you move down, whereas in mathematics, y values increase as you move up. Perhaps the simplest fix is to negate the result of `Math.Sin`: `int Y = Convert.ToInt32(startPos.Y - (bulletSpeed * Math.Sin(angle)))` – Michael Liu Jun 18 '23 at 23:21
  • 2
    [Rotate Point around pivot Point repeatedly](https://stackoverflow.com/a/50478311/7444103) -- Notes in [How to visually connect 2 circles?](https://stackoverflow.com/a/52921415/7444103) -- Show the code that calculates / generates the angles -- I suggest you test the `Matrix.RotateAt()` method, considering the center of your figure as the starting point – Jimi Jun 18 '23 at 23:36
  • @Jimi thanks for the link, I think that question may go towards explaining why my image rotation is also not correct! – Lou Jun 19 '23 at 09:30

2 Answers2

1

According to your text you're working with angles in degrees (0-360) but Math.Sin/Cos is expecting the angle to be in radians (0-2π).

You should use

Math.Sin(angle * Math.PI / 180)
Math.Cos(angle * Math.PI / 180)
Dan Byström
  • 9,067
  • 5
  • 38
  • 68
1

I would highly recommend creating an angle-type that takes care of any radians/degree conversions. Using a float/double for an angle is an invitation for confusion and mistakes. I would also highly recommend using vectors as much as possible, since it can get complicated to describe angles. Using System.Numerics.Vectors:

public class Angle{
    public double Radians {get;}
    public double Degrees => Radians * 180d / Math.PI;
    private Angle(double radians) => Radians = radians;
    public Angle FromDegrees(double degrees) => new Angle(degrees * Math.PI/180d);
    public Angle FromRadians(double radians) => new Angle(radians);
    public double Sin => Sin(radians);
    public double Cos => Cos(radians);
    public Vector2 ToDirection() => new Vector2( (float)Cos, (float)Sin);
}

This should let you write your code like:

var newPosition = currentPosition  + angle.ToDirection() * bulletSpeed;

Note that coordinate systems are complicated, and you will make life easier for yourself if you have a convenient system to display positions, angles, directions etc instead of trying to guess what they are, or to try to read variables in the debugger and try to understand what they mean. This is especially important in 3D where everything just becomes even more complex.

JonasH
  • 28,608
  • 2
  • 10
  • 23