【问题标题】:Problem with a Moving & Rotating Map?移动和旋转地图有问题吗?
【发布时间】:2011-08-24 13:16:59
【问题描述】:

我有一张地图的图像和一个较小的 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 轴上移动地图后,旋转点停留在中心点上。

并且照顾我只旋转了地图:

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

我需要旋转点在红十字的同一位置。

【问题讨论】:

  • 看看Graphics.TransformMatrix.Rotate / Matrix.Translate 方法。它比做你正在做的事情(在每次变换后绘制图像)要简单得多。
  • @George 嘿,你能给我举个例子吗?我以前从未使用过 Tranfrom / Matrix ...

标签: c# .net image


【解决方案1】:

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

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

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


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

需要注意的关键点是:

  1. 您希望地图旋转的点根据玩家所在的位置而有所不同,因此您应该先平移地图(因为这会影响旋转发生的位置)。
  2. 我已将代码更改为使用RotateAt,这样更容易理解。这样我们就不需要担心额外的平移来获取原点的旋转点然后再返回。
  3. 由于您希望箭头键相对于旋转的图像向上,我们不能像往常一样简单地做到这一点。我添加了 CosSin 术语,使用基本三角学推导出来。
  4. 我现在有 2 个图片框,第一个只显示翻译和玩家的方向,第二个是类似雷达的视图(这是您所追求的)。所以,这个答案有两种主要的地图显示类型,在picturebox1中固定北向,在picturebox2中旋转北向。

方向键移动图片,QE旋转图片。

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);
            }
        }
    }
}

【讨论】:

  • Arrrrr... 我真的很难接受这个!大声笑我讨厌矩阵翻译和所有这一切..你能给我看一段代码..我敢肯定它不会超过 5 行..
  • 嘿,谢谢,这正是我所做的......但问题是它在左上角而不是从中心旋转......所以它全部聚集起来哈哈......我以为我做了什么错误的。我怎样才能让它从中心旋转?
  • 仅供参考,你不应该编辑你的问题,它会改变它,只需在底部添加编辑。我不明白你的问题,或者你想要什么。也许描述你想要的图片会有所帮助?
  • 我在帖子底部添加了我认为您想要实现的完整示例。
  • 我不明白你的意思,如果你想从图像中心的播放器开始,只需将开始的imageTranslation改成(0, 0)以外的东西跨度>
猜你喜欢
  • 1970-01-01
  • 2017-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多