c# windows-phone-8 xna monogame

c# - Obteniendo el ángulo entre Vector2



windows-phone-8 xna (4)

Creo que deberías hacer:

public double AngleBetween(Vector2 a, Vector2 b) { return Math.Atan2(-(b.Y - a.Y), b.X - a.X); }

Teniendo en cuenta el eje Y invertido, debe negar los componentes Y.

Entonces, como escribió Zong Zheng Li , has cambiado a Sin y Cos:

collidedCoinVelocity = new Vector2((float)Math.Cos(angleBetween), -(float)Math.Sin(angleBetween));

pero aún necesita negar el componente Vector2.Y , debido al eje Y invertido.

Quiero mover la estrella (moneda en mi código) a la esquina superior derecha exacta de la pantalla cuando el auto golpea la estrella. Tanto la estrella como la carretera se mueven hacia abajo a una velocidad constante durante cada actualización. El automóvil no se mueve, pero parece moverse hacia arriba debido a que la carretera se mueve hacia abajo. Aunque se puede mover al carril izquierdo y derecho en el comando del usuario.

Así que calculé el ángulo entre la estrella y la esquina superior derecha de la pantalla usando el siguiente método

public double AngleBetween(Vector2 a, Vector2 b) { return Math.Atan2(b.Y - a.Y, b.X - a.X); }

En mi método de Update , los siguientes calculan la velocidad para mover y enviarla a la esquina superior derecha de la pantalla

double angleBetween = coin.AngleBetween(coin.Position, new Vector2(currentGame.GraphicsDevice.Viewport.Bounds.Right, 0)); collidedCoinVelocity = new Vector2((float)Math.Sin(angleBetween), -(float)Math.Cos(angleBetween));

En mi método Draw , actualicé la coin.Position usando

coin.Position += collidedCoinVelocity * 10 ;

El problema es que la estrella (moneda) no se envía a la esquina superior derecha como yo quería, sino que está en algún lugar en el medio de la pantalla de la derecha.

Cuando se golpea la estrella cuando está en el carril derecho, el ángulo entre esta y la esquina superior derecha es siempre

1.2196048576751 radians = 69.878211 degree

Cuando la estrella está en el carril izquierdo, el ángulo es

0.952588487628243 radians = 54.5793 degree

¿Estoy calculando el ángulo correctamente? ¿Qué me estoy perdiendo? Tal vez me estoy olvidando de considerar el movimiento descendente de la estrella?

EDITAR

He actualizado la imagen para mostrar el ángulo que estoy tratando de calcular y he editado mi pregunta para que quede más clara.

EDIT 2

Se agregó una segunda imagen para mostrar dónde va la estrella después de ser golpeada.


Parece que cambiaste el pecado y el cos por accidente, y parece que hay un negativo al azar allí. Por lo tanto, esta línea

collidedCoinVelocity = new Vector2((float)Math.Sin(angleBetween), -(float)Math.Cos(angleBetween));

debería ser probablemente

collidedCoinVelocity = new Vector2((float)Math.Cos(angleBetween), (float)Math.Sin(angleBetween));

Aunque ni siquiera necesitas calcular tantos ángulos. Para obtener un vector unitario sin ángulos solo use

double dx = b.X - a.X; double dy = b.Y - a.Y; double mag = Math.Sqrt(dx * dx + dy * dy); collidedCoinVelocity = new Vector2(dx, dy) / mag;


Erhm ... solo para tu información; la conversión de coordenadas cartesianas a usar ángulo, y luego volver a cartesiano no tiene sentido aquí.

Solo obtenga su velocidad final de esta manera:

Vector2 direction = new Vector2(currentGame.GraphicsDevice.Viewport.Bounds.Right, 0) - coin.Position; direction.Normalize(); Velocity = direction * 10; Position += Velocity;

También; NUNCA actualices la posición en Draw. Draw es para Drawing, no se actualiza. ¡Actualizando estadías en Actualización!

También 2; Debes generalizar tu código. todos los objetos en movimiento deben heredar la misma base que incluye elementos como Velocidad, Posición y Aceleración, y el código para manejarlos. De esta forma, solo tiene que cambiar su lógica para manipular Velocity y / o Aceleración para hacer que las cosas se muevan.

MovingObject.Update:

Velocity += Acceleration * deltaTime; Positioin += Velocity * deltaTime;

(deltaTime = tiempo en segundos desde el último fotograma, o (flotante) gameTime.ElapsedGameTime.TotalSeconds)

Luego solo usa base.Update () al final de su actualización de subClasses, y la posición y velocidad funcionarán :) siempre y cuando configure los valores correctos.


Vector2 proporciona una función estática para la interpolación entre puntos.

star_pos = Vector2.Lerp(position_when_hit, destinatin, percent); percent += 0.005f;

Usando este método, cuando se golpea la estrella, configure el Punto A y el Punto B.
Pásalo a la función Vector2.Lerp .
Incluya un valor de flotante Percentage_of_distance_moved .

Esta es la clase de estrella modificada:

class star { Texture2D starT; public Vector2 star_pos; Vector2 position_when_hit; Vector2 destinatin; float percent; bool star_moving_up; public star(Random rand,Texture2D star) { this.starT = star; star_moving_up = false; destinatin = new Vector2(800, 0); star_pos = new Vector2(rand.Next(500), rand.Next(500)); } //Try to call this only once public void on_hit(){ if (!star_moving_up) { position_when_hit = star_pos; star_moving_up = true; } } public void update(GameTime gameTime) { if (star_moving_up) { star_pos = Vector2.Lerp(position_when_hit, destinatin, percent); //a larger percent value will move the star faster. percent += 0.001f; } else { //Your Logic for moving it down } } public void draw(SpriteBatch sp) { sp.Draw(starT, star_pos, Color.White); } }

Y así es como lo usé:

public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Texture2D star; Random rand; star STAR; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } protected override void Initialize() { graphics.PreferredBackBufferWidth = 800; graphics.PreferredBackBufferHeight = 600; base.Initialize(); } protected override void LoadContent() { rand = new Random(); spriteBatch = new SpriteBatch(GraphicsDevice); star = Content.Load<Texture2D>("Bitmap1"); STAR = new star(rand, star); } protected override void UnloadContent() { } protected override void Update(GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); //calls on_hit every update call after 4 seconds. just for demo purpose. if (gameTime.TotalGameTime > TimeSpan.FromSeconds(4)) STAR.on_hit(); STAR.update(gameTime); base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); STAR.draw(spriteBatch); spriteBatch.End(); base.Draw(gameTime); } }