2012-03-02 5 views
1

회전 반경을 사용하여 회전을 증가 및 감소시켜 스프라이트를 회전 시키려고합니다. 마우스가 왼쪽 상단에 있고 오른쪽 상단으로 움직일 때까지 잘 작동합니다. 각도 차이가 현재 회전 값보다 크면 스프라이트의 회전이 증가하고 그렇지 않으면 감소합니다. 그래서 6.5 라디안에서 0으로 갈 때 시계 방향으로 15도 정도가 아닌 약간의 각도로 350도 반 시계 방향으로 회전합니다. 나와 나와 다른 사람들은 하루 종일이 문제를 해결하는 방법을 모르고 있습니다. 내 코드는 다음과 같습니다 :스프라이트 회전 XNA

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using Microsoft.Xna.Framework.Graphics; 
using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Input; 
using System.IO; 

namespace Physics 
{ 
public class Ship 
{ 
    public Texture2D Texture { get; set; } 
    public Vector2 Position { get; set; } 
    public double Rotation { get; set; } 
    MouseState prevState, currState; 

    Vector2 A, B; 

    public const double NINETY_DEGREES = 1.57079633; 

    double turningRadius = 2 * (Math.PI/180); 
    double targetRotation, rotationDifferential; 

    public Ship(Texture2D texture, Vector2 position) 
    { 
     Texture = texture; 
     Position = position; 
     A = new Vector2(Position.X, Position.Y); 
     B = new Vector2(Mouse.GetState().X, Mouse.GetState().Y); 
     Rotation = 0; 
    } 

    public void Update() 
    { 
     currState = Mouse.GetState(); 
     A.X = Position.X; 
     A.Y = Position.Y; 
     B.X = currState.X; 
     B.Y = currState.Y; 

     if (B.Y > A.Y) 
      if (B.X > A.X) //Bottom-right 
       targetRotation = Math.Atan((B.Y - A.Y)/(B.X - A.X)) + NINETY_DEGREES; 
      else //Bottom-left 
       targetRotation = (Math.Atan((A.X - B.X)/(B.Y - A.Y))) + (NINETY_DEGREES * 2); 
     else 
      if (B.X > A.X) //Top-right 
       targetRotation = Math.Atan((B.X - A.X)/(A.Y - B.Y)); 
      else //Top-Left 
       targetRotation = Math.Atan((A.Y - B.Y)/(A.X - B.X)) + (NINETY_DEGREES * 3); 

     if (Rotation > targetRotation) 
      Rotation -= turningRadius; 
     else 
      Rotation += turningRadius; 

     prevState = currState; 
    } 

    public void Draw(SpriteBatch spriteBatch) 
    { 
     spriteBatch.Draw(Texture, Position, null, Color.White, (float)Rotation, new Vector2(Texture.Width/2, Texture.Height/2), 0.5f, 
      SpriteEffects.None, 0.0f); 
    } 
} 

}

답변

3

은 제가 이해하도록하자 Math.PI로 180을 변경. 객체의 방향을 나타내는 벡터 (Cos(Rotation), Sin(Rotation)이 있습니다. 다른 벡터 (B.X-A.X, B.Y-A.Y) 방향을 나타내는 원하는 귀하의 개체를 얼굴에; 그리고 두 번째 벡터의 방향으로 객체 (첫 번째 벡터)를 시계 방향 또는 반 시계 방향으로 회전시킬 것인지 여부를 알고 싶습니까?

단순, 단지 (Z = 0을 설정)과 cross product을 3D 벡터로 모두 취급합니다. 생성 된 벡터는 양 Z 성분이 있으면

  • , 반 시계 방향이 양의 Z 성분이 있으면
  • 회전 방향으로 회전
  • Z 성분이 0 인 경우, 두 벡터 그래서, 평행 그들이 반대 방향을 마주보고 있는지 확인하십시오. (어느 방향 으로든 회전) 또는 같은 방향 (아무 것도 할 수 없습니다!)

이것은 교차 제품을 정의하는 right-hand rule 때문에 작동합니다.

+0

라디안으로 두 개의 float 각도를 간단히 가졌다면 어떻게하는지 생각해보십시오. – Jack

+0

@ 잭 : 그게 이미 대답입니까? 각도를 방향 벡터로 바꾸려면 그냥 (Cos (Rotation), Sin (Rotation)) –

+0

플로트를 Vector3으로 변형하지 않고이 작업을 수행 할 수 있는지 궁금합니다. 그 변환을 거쳐 다시 부유물로 돌아 가기 위해 조금 외적인 것 같군요? – Jack

0

편집 내 사과는 내 후방에서 내 머리를 제거하고 실제로 질문이 시간을 읽으십시오. 그래서 여기에 오늘 밤 쓰는 데 3 시간 쓴 멋진 작은 방법이 있습니다.

private float AngleLerp(float nowrap, float wraps, float lerp) { 

    float c, d; 

    if (wraps < nowrap) { 
     c = wraps + MathHelper.TwoPi; 
     //c > nowrap > wraps 
     d = c - nowrap > nowrap - wraps 
      ? MathHelper.Lerp(nowrap, wraps, lerp) 
      : MathHelper.Lerp(nowrap, c, lerp); 

    } else if (wraps > nowrap) { 
     c = wraps - MathHelper.TwoPi; 
     //wraps > nowrap > c 
     d = wraps - nowrap > nowrap - c 
      ? MathHelper.Lerp(nowrap, c, lerp) 
      : MathHelper.Lerp(nowrap, wraps, lerp); 

    } else { return nowrap; } //Same angle already 

    return MathHelper.WrapAngle(d); 
} 

IT는 wraps 값을 향해 nowrap lerps. wraps 각도는 0에서 TwoPi로 점프하고 다시이 각도로 마우스의 각도가 될 수 있습니다. nowrap는 당신의 목표 각이어야한다.

희망이 시간은 실제로 도움이되었습니다.

+0

내가 이해하는 것처럼 x에서 Pi와 -Pi 사이의 각도로 축소됩니다. 문서가 조금 부족합니다. 그것은 유망한 것처럼 보이지만 각도가 변화하는 속도에 대한 어떠한 제어도주지 못합니다. 이것은 게임의 기본입니다. 정확히 무엇을하는지에 대한 약간의 도움이됩니다. 사용법은 좋을 것입니다 :-). 또한 구현할 때 Rotation을 MathHelper.WrapAngle (targetRotation)으로 설정하고 단순히 회전 각도를 설정합니다. 부드럽고 천천히 전환해야합니다 ... – Jack

0

다음을 시도해보십시오 (이것은 내가 작성한 탱크 게임의 코드입니다.이 시나리오에도 여전히 적용되는지는 확실하지 않습니다). 나는 필수로 내려 손질 :

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

namespace Physics 
{ 
    public class Ship 
    { 
     public Texture2D Texture { get; set; } 
     public Vector2 Position { get; set; } 
     public double Rotation { get; set; } 
     private MouseState currState; 

     public Ship(Texture2D texture, Vector2 position) 
     { 
      Texture = texture; 
      Position = position; 
      Rotation = 0; 
     } 

     public void Update() 
     { 
      currState = Mouse.GetState(); 

      var mouseloc = new Vector2(currState.X, currState.Y); 
      Vector2 direction = Position - mouseloc; 
      Rotation = Math.Atan2(direction.Y, direction.X) + MathHelper.PiOver2; 
     } 

     public void Draw(SpriteBatch spriteBatch) 
     { 
      spriteBatch.Draw(Texture, Position, null, Color.White, (float) Rotation, 
          new Vector2(Texture.Width/2, Texture.Height/2), 0.5f, 
          SpriteEffects.None, 0.0f); 
     } 
    } 
} 

난 당신이 그냥 내가 다시 내가 해결책을 마련하면 올 것이다 회전 속도를 수정하는 데 좀 더 수학을 필요가 있다고 생각합니다. 또한이 코드는 스프라이트의 기본 회전에 따라 달라집니다. 내 예에서는 스프라이트가 아래를 향하고 있다고 가정합니다 (6시 방향). 희망이 올바른 방향으로 당신을 가리 킵니다!

1

빠른 방향으로 반대 방향으로 진행해야합니다.

spin = targetRotation - Rotation; 
if (abs(spin) > Math.PI) 
    spin *= -1; 
if (spin > 0 
    Rotation += turningRadius; 
else 
    Rotation -= turningRadius; 

편집 :

+0

그게 효과가 있다면. –