2017-03-18 3 views
0

그래서 기본 스프라이트()와 샤프트 용 별도 스프라이트 (Turret Shaft)가있는 터렛 유형 건이 있습니다. 샤프트는베이스 뒤쪽으로 그려지고 마우스 위치를 향하여 회전합니다. 샤프트의 각도는 _turretAngle으로 저장됩니다.Monogame/XNA 건 총알 발사 마우스

글 머리 기호를 올바르게 배치하려고하면 내 문제가 발생합니다. 문제의 총알 (Bullet)은 샤프트의 끝에서 항상 올바르게 기울어 져야하며 물론 올바른 방향으로 발사해야합니다.

총알을 비스듬히하려면 간단히 _turretAngle을 사용하고 방향은 new Vector2(-Math.Cos(_turretAngle), -Math.Sin(_turretAngle));이지만 초기 위치를 올바르게 가져올 수 없습니다. (상기 터릿의 각도에 따라) 행 어딘가에 위치하는 탄 올바르게 위치되고 너무 가까운

int i = _bullets.Count - 1; 
Bullet b = _bullets[i]; 

b.SetAngle(_turretAngle); 

float cos = (float)Math.Cos(_turretAngle); 
float sin = (float)Math.Sin(_turretAngle); 

b.SetDirection(new Vector2(-cos, -sin)); 

var posX = (Position.X - (Shaft.Width * cos) - (b.Width * cos)) + (Width/2) - ((b.Width/2) * cos); 
var posY = Position.Y - (Shaft.Height * sin) - (b.Height * sin); 

b.SetPosition((int)posX, (int)posY); 

b.BulletState = Bullet.State.Active; 

하지만, 대신에, 상기 샤프트에 위치가 아닌 경우 다음과 같이

는 I 현재 그것을 가지고 포대보다 5-15 픽셀 앞.

Current

내가 그것을 표시 할 방법 :

는 현재 표시 방법

Ideal

내가 여기에 니트 - 까다롭게 될 수 알지만 ' d는 수학이 어떻게 잘못되었는지 알고 싶어합니다.

누락 된 정보가있을 수 있다는 것을 알고 있습니다. 아무 것도 추가해야하는지 알려주세요.

+0

내가 제안을 이 총알을 turet와 같은 위치에 산란시키고, 같은 회전 행렬을 적용한 다음, y 방향으로 포대의 높이 + 총알의 높이와 같은 대상을 움직여야하는 이동 행렬을 적용합니다. 먼저 회전 행렬을 적용한 다음 객체를 이동해야하는 이유입니다. 그것은 하나의 픽셀 간격과도 완벽하게 정렬되어야합니다. –

답변

2

일부 코드 샘플 및 더 자세한 설명으로 내 의견을 확장하십시오.
각도를도 또는 라디안으로 지정하지 않았으므로 변환해야 할 도수를 사용하고 있다고 가정합니다. 다음으로 회전 및 변환 행렬을 작성하여 총알 객체에 적용합니다.

나의 제안은 같은 확장 클래스를 만드는 것입니다 :

public static class TransformEx 
{ 
    // method to convert degree into radians 
    public static double ToRadians(this double degree) 
    { 
     return ((degree % 360.0D)/180.0D) * Math.PI; 
    } 

    // get the rotation matrix 
    public static Matrix GetRotationMatrix(this double angle, Vector2 rotationCenter) 
    { 
     double radians = angle.ToRadians(); 
     double cos = Math.Cos(radians); 
     double sin = Math.Sin(radians); 

     return new Matrix 
     { 
      M11 = cos, 
      M12 = sin, 
      M21 = -sin, 
      M22 = cos, 
      M41 = (rotationCenter.X * (1.0 - cos)) + (rotationCenter.Y * sin), 
      M42 = (rotationCenter.Y * (1.0 - cos)) - (rotationCenter.X * sin) 
     }; 
    } 

    // get translation matrix 
    public static Matrix GetTranslationMatrix(this Vector2 position) 
    { 
     return new Matrix 
     { 
      M41 = position.X, 
      M42 = position.Y, 
      M43 = 0 
     }; 
    } 
} 

이 지금 계산을 진행하고 총알을 설정할 수 있습니다 가졌어요. 글 머리 기호가 올바르게 표시 되려면 X 축에서의 번역을 계산해야합니다.

// spawn the bullet 
Bullet b = _bullets[i]; 

// get size of bullet and turret for further calculations 
Vector2 bulletSize = new Vector2(b.Width, b.Height); 
Vector2 turretSize = new Vector2(turret.Width, turret.Height); 

// move bullet to the same position as turret 
b.Position = turret.Position; 

// calculate new translation depending on the size difference 
double deltaX = (turretSize.X - bulletSize.X)/2; 
Vector2 bulletNewPos = new Vector2(b.Position.X + deltaX, b.Position.Y + turretSize.Height); 

// using extension methods get rotation matrix 
// this will rotate referencing the middle point of your bullet 
Matrix mtxRotation = _turretAngle.GetRotationMatrix(new Vector2(bulletSize.X/2, bulletSize.Y/2)); 

// now you have to create translation matrix 
// but remember to calculate position correctly 
Matrix mtxTranslation = bulletNewPos.GetTranslationMatrix(); 

// now all you have to do is to rotate and then translate your bullet 
Matrix transformMatrix = mtxTranslation * mtxRotation; 

이제 transformMatrix에는 필요한 모든 변환 세부 정보가 포함되어 있습니다. SpriteBatch.Begin에 대한 오버로드 방법을 사용하여이 변환 행렬을 사용할 수 있습니다.

그러나 여전히 SetPositionSetAngle 방법을 사용하려는 경우당신은 단순히 새로운 위치를 추출하는이 행렬을 사용하고이 사용하여 적용 할 수 있습니다

b.SetAngle(_turretAngle); 
// M41 >> position.X 
// M42 >> position.Y 
// M43 >> position.Z 
b.SetPosition((int)transformMatrix.M41, (int)transformMatrix.M42); 

편집이 :
이것은 당신의 축 값이 같은 정의되어 있다고 가정합니다

Y + 
^
    | 
    | 
    |   
-X +------------> X + 
    Y-