我有一个地图图像和一个较小的PictureBox控件。
我正在从Joysyick获取输入。我的Y将图像向上并向左移动
Adn X实际上会旋转图像。
我的问题是,当我旋转图像时,Y轴也随之旋转,因此当我再次向上移动时,它不会真正上升。.它也会沿Y轴指向的新方向移动。
如果您能理解我的问题,这是我的代码。
public void UpdateTurret()
{
while (js != null)
{
js.GetData();
Thread.Sleep(80);
MapY += js.State.Y;
MapRotation += js.State.X;
{
Image map = Properties.Resources.Map;
Bitmap bmp = (Bitmap)map.Clone();
Graphics g = Graphics.FromImage((Image)bmp);
g.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2 - (MapY / 2));
g.RotateTransform(MapRotation);
g.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2 + (MapY / 2));
g.DrawImage(bmp, 0, 0);
Graphics gfx = Graphics.FromImage((Image)bmp);
gfx.DrawPie(new Pen(Color.Blue, 5), bmp.Width/2 - 5, bmp.Height/2 - 5, 5, 5, 0, 360);
gfx.DrawImage(bmp, 0, MapY);
picBoxMap.Image = (Image)bmp;
float rot = MapRotation;
rot = (float)Math.Abs((rot - 360*Math.Ceiling(rot / 360)));
DrawString = (rot).ToString() + "° Y:" + MapY.ToString();
}
}
}
现在的问题是旋转点始终居中,我希望旋转点成为到达的新位置。
所以我想应该是这样的:
g.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2 - MapY);
g.RotateTransform(MapRotation);
g.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2 + MapY);
但这会导致另一个错误。现在,当我旋转图像时,Y轴随之旋转,因此当我再次向上移动时,它不会真正上升。.它也将沿Y轴指向的新方向移动。
有人有解决此问题的想法吗?
编辑:
这是我的新代码:
public void UpdateTurret()
{
while (js != null)
{
js.GetData();
Thread.Sleep(80);
MapY += js.State.Y;
MapRotation += js.State.X;
{
Image map = Properties.Resources.Map;
Size mapSize = map.Size;
Bitmap bmp = (Bitmap)map.Clone();
Graphics g = Graphics.FromImage((Image)bmp);
Matrix transformMatrix = new Matrix();
transformMatrix.Translate(-mapSize.Width / 2, -mapSize.Height / 2, MatrixOrder.Append);
transformMatrix.Rotate(MapRotation, MatrixOrder.Append);
transformMatrix.Translate(mapSize.Width / 2, mapSize.Height / 2, MatrixOrder.Append);
transformMatrix.Translate(0, MapY, MatrixOrder.Append);
g.Transform = transformMatrix;
g.DrawImage(bmp, 0,0);
picBoxMap.Image = (Image)bmp;
float rot = MapRotation;
rot = (float)Math.Abs((rot - 360*Math.Ceiling(rot / 360)));
DrawString = (rot).ToString() + "° Y:" + MapY.ToString();
}
}
//Draw Cross
Graphics gfx = picBoxMap.CreateGraphics();
Rectangle rc = picBoxMap.ClientRectangle;
gfx.DrawLine(Pens.Red, rc.Width / 2, rc.Height / 2 + 10, rc.Width / 2, rc.Height / 2 - 10);
gfx.DrawLine(Pens.Red, rc.Width / 2 + 10, rc.Height / 2, rc.Width / 2 - 10, rc.Height / 2);
}
我现在的问题是,在Y轴上移动地图后,旋转点停留在中心点上。
并照顾我只旋转地图:
您可以看到我没有移动Y轴,但是它确实发生了变化..因为旋转点位于图像的中心,而不是红叉所在的位置。
我需要旋转点位于红十字的相同位置。
最佳答案
可能更好的方法是使用Matrix.Rotate()
和Matrix.Translate()
方法来获取将Graphics.Transform
设置为的矩阵。
然后,您可以简单地在原点绘制地图(忽略移动和旋转地图),然后图形对象将完成其余工作。
有关更多信息,请参见Matrix方法链接中的示例。在他们的示例中,他们绘制了一个矩形,但是您可以轻松地绘制图像。
在我未编辑的答案中,我错了。我已经更正了下面的代码。
需要注意的关键事项是:
您希望地图旋转的点根据玩家所在的位置而变化,因此您应该首先平移地图(因为这将影响旋转发生的位置)。
我已经更改了代码以使用RotateAt
,因此更易于理解。这样,我们就不必担心多余的平移以使旋转点位于原点,然后再返回。
因为您希望箭头键相对于旋转的图像向上倾斜,所以我们不能像平常一样简单地进行操作。我添加了Cos
和Sin
术语,这是使用基本三角学推论得出的。
现在,我有2个图片框,第一个仅显示平移,以及播放器的方向,第二个是类似雷达的视图(这就是您所追求的)。因此,此答案具有2种主要地图显示类型,即在picturebox1中向北固定,在picturebox2中向北旋转。
箭头键移动图像,Q和E旋转图像。
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private PictureBox pictureBox1;
private PictureBox pictureBox2;
private Image imageToDraw = null;
private float imageRotation = 0.0f;
private PointF imageTranslation = new PointF();
public Form1()
{
InitializeComponent();
pictureBox1 = new PictureBox() { Top = 20, Left = 10, Width = 280, Height = 310, BorderStyle = BorderStyle.FixedSingle };
pictureBox2 = new PictureBox() { Top = 20, Left = pictureBox1.Right + 10, Width = 280, Height = 310, BorderStyle = BorderStyle.FixedSingle };
pictureBox1.Paint += new PaintEventHandler(pictureBox1_Paint);
pictureBox2.Paint += new PaintEventHandler(pictureBox2_Paint);
this.Controls.Add(pictureBox1);
this.Controls.Add(pictureBox2);
this.Controls.Add(new Label() { Text = "Left = translation only, Right = translation and rotation", Width = Width / 2 });
this.ClientSize = new Size(pictureBox2.Right + 10, pictureBox2.Bottom + 10);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
}
private void Form1_Activated(object sender, EventArgs e)
{
try
{
imageToDraw = Image.FromFile("C:\\Map.jpg");
}
catch (Exception)
{
MessageBox.Show("Ensure C:\\Map.jpg exists!");
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if (imageToDraw != null)
imageToDraw.Dispose();
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
const float MoveSpeed = 5.0f;
switch (e.KeyCode)
{
case Keys.Q:
imageRotation -= 1.0f;
break;
case Keys.E:
imageRotation += 1.0f;
break;
case Keys.Up:
imageTranslation = new PointF(imageTranslation.X - (float)Math.Sin(imageRotation / 180 * Math.PI) * MoveSpeed, imageTranslation.Y - (float)Math.Cos(imageRotation / 180 * Math.PI) * MoveSpeed);
break;
case Keys.Down:
imageTranslation = new PointF(imageTranslation.X + (float)Math.Sin(imageRotation / 180 * Math.PI) * MoveSpeed, imageTranslation.Y + (float)Math.Cos(imageRotation / 180 * Math.PI) * MoveSpeed);
break;
case Keys.Left:
imageTranslation = new PointF(imageTranslation.X - (float)Math.Cos(imageRotation / 180 * Math.PI) * MoveSpeed, imageTranslation.Y + (float)Math.Sin(imageRotation / 180 * Math.PI) * MoveSpeed);
break;
case Keys.Right:
imageTranslation = new PointF(imageTranslation.X + (float)Math.Cos(imageRotation / 180 * Math.PI) * MoveSpeed, imageTranslation.Y - (float)Math.Sin(imageRotation / 180 * Math.PI) * MoveSpeed);
break;
}
pictureBox1.Invalidate();
pictureBox2.Invalidate();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (imageToDraw != null)
{
e.Graphics.ResetTransform();
Matrix transformMatrix = new Matrix();
transformMatrix.Translate(-imageTranslation.X, -imageTranslation.Y);
e.Graphics.Transform = transformMatrix;
e.Graphics.DrawImage(imageToDraw, Point.Empty);
transformMatrix = new Matrix();
transformMatrix.Translate(50, 50);
transformMatrix.RotateAt(-imageRotation, new PointF(20, 20));
e.Graphics.Transform = transformMatrix;
e.Graphics.DrawString("^", new Font(DefaultFont.FontFamily, 40), Brushes.Black, 0, 0);
}
}
private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
if (imageToDraw != null)
{
e.Graphics.ResetTransform();
Matrix transformMatrix = new Matrix();
transformMatrix.Translate(-imageTranslation.X, -imageTranslation.Y);
transformMatrix.RotateAt(imageRotation, new PointF(pictureBox1.Width / 2 + imageTranslation.X, pictureBox1.Height / 2 + imageTranslation.Y));
e.Graphics.Transform = transformMatrix;
e.Graphics.DrawImage(imageToDraw, Point.Empty);
}
}
}
}