Как мне переместить спрайт в направлении, в котором он находится после вращения? - PullRequest
0 голосов
/ 23 мая 2018

Я могу перемещаться на лодке по спрайту вверх, вниз, влево и вправо, а также вращать его.Однако вместо того, чтобы лодка всегда двигалась вверх, когда нажата клавиша «вверх», я бы хотел, чтобы лодка двигалась в направлении ее носа.Я думал, что мог бы вставить переменную vector2 где-нибудь в методе обновления, который всегда указывает на кончик спрайта, но я не могу обернуться, как «жестко закодировать» координату спрайта.

Я опубликую свой класс корабля ниже, я думаю, что все немного запутанно, любые предложения по очистке кода также приветствуются.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;


//width = 62 pixels
//height = 179 pixels

namespace my_first_game
{
class Ship
{

    private Vector2 position = new Vector2(300, 300);
    private int radius = 50;
    private bool ismoving = false;
    private Dir direction = Dir.down;
    private int health = 3;
    private float speed = 100;
    public float angle = 0;
    public double turntime = .5d;

    private float velocity = 10f;
    private float drifttime = 0f;

   // Constructor for the ship class
   public Ship(int shiphealth)
    {
        shiphealth = health;
    }

    //getter/setter for angle
     public float Get_angle
     {
         get { return angle; }
        set { value = angle; }

     }         

    //get and set health
    public int Health
    {
        get { return health; }
        set { value = health; }
    }

    // get and set the ship's position
    public Vector2 Position
    {
        get{ return position; }
        set { value = position; }
    }

    public void SetAngle (float f)
    {
        angle = MathHelper.ToDegrees(f);
    }

    //update loop for the ship's state
    public void update_ship(GameTime gameTime)
    {
        KeyboardState kstate = Keyboard.GetState();
        float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;

        float rotation = 0.02f;

        //Vector2 Direction = new Vector2((float)Math.Cos(angle + 45), (float)Math.Sin(angle));
        //Direction.Normalize();           

        //if keys are pressed, the ship moves until the keys are unpressed

        if (kstate.IsKeyDown(Keys.W))
        {
            direction = Dir.up;
            ismoving = true;
        }
        if (kstate.IsKeyDown(Keys.A))
        {
            direction = Dir.left;
            ismoving = true;
        }
        if (kstate.IsKeyDown(Keys.D))
        {
            direction = Dir.right;
            ismoving = true;
        }
        if (kstate.IsKeyDown(Keys.S))
        {
            direction = Dir.down;
            ismoving = true;
        }
        if(kstate.IsKeyDown(Keys.W) && kstate.IsKeyDown(Keys.D))
        { direction = Dir.up_right;
            ismoving = true;
        }
        if(kstate.IsKeyDown(Keys.W) && kstate.IsKeyDown(Keys.A))
        {
            direction = Dir.up_left;
            ismoving = true;
        }
        if (kstate.IsKeyDown(Keys.S) && kstate.IsKeyDown(Keys.D))
        { direction = Dir.down_right;
            ismoving = true;
        }
        if (kstate.IsKeyDown(Keys.S) && kstate.IsKeyDown(Keys.A))
        {
            direction = Dir.down_left;
            ismoving = true;
        }

            //"ismoving" is used as a flag to move the ship if keys are held
            //angle also rotates the boat when "A" and "D" are pressed
            if (ismoving) {

            switch (direction)
            {
                case Dir.up:
                    position.Y -= speed * dt;
                    ismoving = false;
                    break;

                case Dir.down:

                    position.Y += speed * dt;
                    ismoving = false;
                    break;

                case Dir.left:

                    angle -= rotation;
                    ismoving = false;
                    break;

                case Dir.right:
                    angle += rotation;
                    ismoving = false;
                    break;

                case Dir.up_right:
                    position.Y -= speed * dt;
                    position.X += speed * (float)turntime * dt;
                    angle += rotation;
                    ismoving = false;
                    break;

                case Dir.up_left:
                    position.Y -= speed * dt;
                    position.X -= speed * (float)turntime * dt;
                    angle -= rotation;
                    ismoving = false;
                    break;
                case Dir.down_right:
                    position.Y += speed * dt;
                    position.X += speed * (float)turntime * dt;
                    angle += rotation;
                    ismoving = false;
                    break;
                case Dir.down_left:
                    position.Y += speed * dt;
                    position.X -= speed * (float)turntime * dt;
                    angle -= rotation;
                    ismoving = false;
                    break;

                default: break;
            }
            }   
        }
    }
}

Вот соответствующий метод рисования для моего корабля:

//create a new rectangle around the ship_sprite
        Rectangle ship_rectangle = new Rectangle(0, 0, ship_sprite.Width, 
ship_sprite.Height);

        Vector2 origin = new Vector2(31, 160);


        spriteBatch.Draw(ship_sprite, ship.Position, ship_rectangle, 
Color.White, ship.angle, origin, 1.0f, SpriteEffects.None, 1);

Ответы [ 2 ]

0 голосов
/ 25 мая 2018

После небольшого количества попыток я нашел решение, которое сработало для меня.

Vector2 direction = new Vector2((float)Math.Cos(angle + 30), 
(float)Math.Sin(angle + 30));

Затем, когда нажата кнопка «вверх», вы можете просто установить положение лодки в ее текущее положение плюс уголлодки.Сумма этих двух может быть умножена на время дельты и скорость лодки.

if(kstate.IsKeyDown(Keys.W))
{
  position = position + direction * dt * speed;   
}
0 голосов
/ 23 мая 2018

Я сомневаюсь, что есть один «правильный» ответ на этот вопрос, но я бы использовал ваше свойство «angle» для определения движения при нажатии кнопки «Вверх».

Я думаю олинии тригонометрии - ваш радиус будет скорость лодки.Затем вы должны сделать что-то вроде (псевдокод!):

x += (cos(angle) * speed);
y += (sin(angle) * speed);

Это предполагает, что Angle = 0 соответствует стандартной интерпретации 0 градусов на нормальном плане (так, если смотреть направо).Если это не так, вам нужно соответствующим образом скорректировать.

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

...