移动和放大器的问题旋转地图?

时间:2011-08-24 13:17:00

标签: c# .net image

我有一张Map和一个较小的PictureBox控件的图像。

我从joysyick那里得到了输入。我的Y将图像向上并向左移动 并且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轴上移动地图后,旋转点会停留在中心点上。

enter image description here

照顾我只旋转地图:

enter image description here

你可以看到我没有移动Y轴但它确实改变了..因为旋转点位于图像的中心而不是红叉的位置。

我需要旋转点位于红十字的相同位置。

1 个答案:

答案 0 :(得分:3)

可能更好的方法是使用Matrix.Rotate()Matrix.Translate()方法获取矩阵以将Graphics.Transform设置为。

然后你可以简单地在原点绘制地图(忽略移动和旋转它),图形对象将完成其余的工作。

有关详细信息,请参阅Matrix方法链接中的示例。在他们的示例中,他们绘制了一个矩形,但您可以轻松地绘制图像。


在我未经编辑的回答中,我错了。我已在下面更正了我的代码。

需要注意的关键事项是:

  1. 您希望地图旋转的点根据玩家的位置而变化,因此您应首先翻译地图(因为这将影响旋转发生的位置)。
  2. 我已将代码更改为使用RotateAt,因此更容易理解。这样我们就不必担心额外的翻译,以便在原点再次获得旋转点。
  3. 正如您希望箭头键相对于旋转的图像而言,我们无法像平常一样进行操作。我添加了CosSin条款,使用基本三角函数推导出来。
  4. 我现在有2个图片盒,第一个只显示翻译,播放器的方向,第二个是雷达视图(这是你想要的)。所以,这个答案有2个主要的地图显示类型,在picturebox1中固定北,在picturebox2中向北旋转。
  5. 箭头键移动图像, 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);
                }
            }
        }
    }