Проблема с движущейся и вращающейся картой? - PullRequest
3 голосов
/ 24 августа 2011

У меня есть изображение карты и меньший элемент управления PictureBox.

Я получаю информацию от моего приятеля. Моя картинка снимает изображение вверх и влево 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 ...

У кого-нибудь есть идеи по решению этой проблемы?


EDIT

Вот мой новый код:

    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 Ответ

3 голосов
/ 24 августа 2011

Возможно, лучшим подходом является использование методов Matrix.Rotate() и Matrix.Translate(), чтобы получить матрицу для установки Graphics.Transform в.

Затем вы можете просто нарисовать карту в начале координат (игнорируя ее перемещение и поворот), и графический объект сделает все остальное.

См. Примеры в ссылках на метод Matrix для получения дополнительной информации.В их примере они рисуют прямоугольник, но вместо этого вы можете легко нарисовать свое изображение.


В моем неотредактированном ответе я ошибся.Я исправил свой код ниже.

Ключевые моменты, на которые следует обратить внимание:

  1. Вы хотите, чтобы точка поворота карты изменялась в зависимости от того, где находится игрок, поэтому вам следуетсначала переведите карту (так как это повлияет на поворот).
  2. Я изменил код, чтобы использовать RotateAt, чтобы его было легче понять.Таким образом, нам не нужно беспокоиться о дополнительных переводах, чтобы получить точку поворота в исходной точке, а затем обратно.
  3. Поскольку вы хотите, чтобы клавиши со стрелками обозначали вверх относительно повернутого изображения, мы не можемсделать это так же просто, как обычно.Я добавил Cos и Sin терминов, выведенных с использованием базовой тригонометрии.
  4. Теперь у меня есть 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);
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...