开发者

Problem with a Moving & Rotating Map?

I have a image of a Map and a smaller PictureBox control.

I'm getting input from my joysyick. My the Y takes the image up and left Adn the X actually rotates the image..

My problem is when i rotate the Image, the Y axis rotates with it, so when i move up again it wont really go up.. it will go the the new direction the Y axis points too..

Here is my code if you could understand my problam..

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

My problem now is that the rotation point is always centered, i want my rotation point to be the new position i reached.

So i figured out it should be like this:

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

But this cause another bug. Now when i rotate the I开发者_Go百科mage, the Y axis rotates with it, so when i move up again it wont really go up.. it will go the the new direction the Y axis points too..

Anyone has an idea on solving this issue?


EDIT:

Here is my new code:

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

My problem now is that after i move the map on the Y axis, the rotation point stays on the center point.

Problem with a Moving & Rotating Map?

And look after i only rotated the map:

Problem with a Moving & Rotating Map?

You can see i didn't move the Y axis but it did changed.. because the Rotation point is at the center of the image and not where to red cross is.

I need the rotation point to be at the same position of the red cross.


Possibly a better approach is to use the Matrix.Rotate() and Matrix.Translate() methods to get a matrix to set the Graphics.Transform to.

Then you can simply draw your map at the origin (ignoring moving and rotating it), and the graphics object will do the rest.

See the examples in the Matrix method links for more info. In their example they draw a rectangle, but you could easily draw your image instead.


In my unedited answer i was wrong. I've corrected my code below.

The key things to note are:

  1. You want the point the map rotates at to vary according to where the player is, so you should translate the map first (since this will then effect where the rotation happens).
  2. I've changed the code to use the RotateAt so it's easier to understand. This way we don't need to worry about the extra translations to get the rotation point at the origin then back again.
  3. As you want the arrow keys to mean up with respect to the rotated image we can't do it as simply as normal. I've added Cos and Sin terms in, deduced using basic trigonometry.
  4. I've now got 2 pictureboxes, the first shows only the translation, and the direction of the player, the second is a radar like view (which is what you're after). So, this answer has the 2 main map display types, fixed north in picturebox1, rotating north in picturebox2.

Arrow keys move the image, Q and E rotate it.

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜