英文:
Moving an object from A to B by angle - object goes the wrong way
问题
我明白这个主题有很多问题。我对几何学或数学不够熟悉,无法理解这些解决方案(已经很长时间没有学数学了),所以我真的很感谢有人能帮助我解决这个问题。
我试图在C#中移动一个PictureBox对象,需要三个值:起始位置作为一个Point坐标,它应该移动的角度,以及速度(移动多少像素)。
我尝试了从不同答案中拼凑出来的这个方法:
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);
}
然而,只有当角度为0时才有效。这个图片是一辆坦克 - 当图片处于默认方向时,坦克炮塔朝右 - 角度为0。我知道我可能没有将角度0放在北方,但我不确定如何根据这个旋转来纠正公式。
为了说明我所说的设置,下面的截图中角度为0 - 你可以从记录角度的标签中看到。子弹从坦克正确地射向左边到右边。
但是,当我把坦克旋转一点,使其朝右上方,角度就是315(想象它顺时针移动了315度,或者逆时针移动了45度)。我期望子弹朝右上方飞去,但它们飞向右下方。看起来它可能偏了大约90度?
我犯了什么错误,如何修正运动公式,使子弹以预期的角度飞行?
英文:
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.
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?
答案1
得分: 1
根据您的文本,您正在使用度数(0-360)来处理角度,但Math.Sin/Cos期望角度以弧度表示(0-2π)。
您应该使用
Math.Sin(angle * Math.PI / 180)
Math.Cos(angle * Math.PI / 180)
英文:
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)
答案2
得分: 1
我强烈建议创建一个角度类型,负责处理弧度/角度的转换。使用浮点/双精度数表示角度容易引发混淆和错误。我还强烈建议尽量使用向量,因为描述角度可能会变得复杂。可以使用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);
}
这样可以让你像这样编写代码:
var newPosition = currentPosition + angle.ToDirection() * bulletSpeed;
请注意,坐标系统很复杂,如果你有一个方便的系统来显示位置、角度、方向等,而不是试图猜测它们或在调试器中阅读变量并尝试理解它们的含义,会让你的生活变得更轻松。这在3D中尤为重要,因为一切都变得更加复杂。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论