Plano cartesiano y Rotación de Objetos – XNA


Para desarrollar juegos en 2D, tenemos que conocer cómo funciona XNA en cuanto a las coordenadas, si retrocedemos algunos años en la Universidad, o en el colegio o en la escuela, nos enseñaron el plano cartesiano, que era un plano formado por dos rectas cruzadas, una horizontal (eje de la X) y otra vertical (eje de la Y), la cual se cruzaban o tenían su punto de origen en el punto (0,0), en XNA se maneja el mismo plano, con la diferencia de que el origen en el plano cartesiano se encuentra en la mitad del plano, en XNA se encuentra en la parte superior izquierda:

 

Plano 2D en XNA (Esta imagen la encontré en internet :P)

 

Plano Cartesiano (Esta imagen la encontré en internet :P)


Muchos ya se habrán acostumbrado al plano que maneja XNA, pero pues hoy les voy a mostrar cómo convertir el plano de XNA en un plano Cartesiano.

Antes de eso voy a dibujar unas líneas en la pantalla para dibujar el los ejes, este es el código:

protected VertexPositionColor[] vertices;
BasicEffect basicEffect;

Initialize()

basicEffect = new BasicEffect(graphics.GraphicsDevice, null);
basicEffect.DiffuseColor = new Vector3(1.0f, 1.0f, 1.0f);

LoadContent():

spriteBatch = new SpriteBatch(GraphicsDevice);
vertices = new VertexPositionColor[4];
vertices[0] = new VertexPositionColor(-Vector3.UnitX, Color.Red);
vertices[1] = new VertexPositionColor(Vector3.UnitX, Color.Red);
vertices[2] = new VertexPositionColor(-Vector3.UnitY, Color.Red);
vertices[3] = new VertexPositionColor(Vector3.UnitY, Color.Red);

Draw():

GraphicsDevice.Clear(Color.Black);
basicEffect.Begin();
foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
{
      pass.Begin();
      graphics.GraphicsDevice.VertexDeclaration = new
      VertexDeclaration(graphics.GraphicsDevice,
      VertexPositionColor.VertexElements);
      graphics.GraphicsDevice.DrawUserPrimitives(
            PrimitiveType.LineList, vertices, 0, 2);
            pass.End();
}
basicEffect.End();

Al ejecutar la aplicación vemos:

 

No voy a enfocarme en el dibujo de las líneas o de otras formas primitivas, por lo tanto les debo esa explicación.

Para ver la diferencia de los planos, voy a cargar y mostrar una imagen en el punto (10,20):

 

Nuestro dibujo quedo dibujado en la posición (10,20), como dije anteriormente el punto (0,0) es la esquina de la izquierda en la parte superior.

Van a ver que es muy fácil convertir las coordenadas, vamos a usar dos funciones, uno que convierta los valores del eje X y otro que convierta los valores de eje Y:

public double cartesianoX(double x)
{
      Int32 punto0 = ventanaX / 2;
      return x + (punto0);
}
public double cartesianoY(double y)
{
      Int32 punto0 = ventanaY / 2;
      Int32 signo = 0;
      if (y > 0)
            signo = -1;
      else
            signo = 1;
      return signo * Math.Abs(y) + punto0;
}

En la función del eje de la X lo que hago es sumarle al valor de la x el  origen (?), para que me entiendan mejor, imaginemos que la pantalla tiene una dimensión de (100,100) el punto de origen en la pantalla será (50,50), por lo tanto si queremos que ubicarnos en el punto (0,0) del plano cartesiano, le sumamos 50 al valor de la x, si queremos ubicar el punto (10,10) en el plano cartesiano, se le suma 50 a la x, dando como resultado la posición 60 en la x, si el valor es negativo se va a restar. Una imagen donde las coordenadas de XNA están en rojo y las del plano cartesiano en azul:

 

En la función de la Y, tiene un detalle de más, no solo es sumar el valor como en la x, ya que por ejemplo su queremos ubicar el valor de la y en el punto 0, se le suma 50 nos va a dar correcto, pero su queremos ubicar el punto 10, al sumarle los 50 nos va a dar 60, y al ubicarlo no nos dará bien, lo estamos ubicando es en la posición -10 del plano cartesiano, ver imagen anterior.

Para corregir esto, si el valor de la y es mayor a 0, o sea es positiva, vamos a restar el valor del origen a la y, para que quede bien posicionado, al contrario se es negativo lo sumamos.

Antes de iniciar, declaramos las variables que son las que van a guardar el tamaño de la ventana:

Int32 ventanaX = 800;
Int32 ventanaY = 600;

Al inicio del Initialize:

graphics.PreferredBackBufferHeight = ventanaY;
graphics.PreferredBackBufferWidth = ventanaX;
graphics.ApplyChanges();

Modificar el Draw para aplicar la conversión:

float x = (float)cartesianoX(0);
float y = (float)cartesianoY(0);
spriteBatch.Begin();
spriteBatch.Draw(textura, new Vector2(x, y), Color.White);
spriteBatch.End();

Al ejecutar veremos:

 

El sprite se encuentra en la posición (0,0) del plano cartesiano, lo que equivale a la posición (50,50), los sprites tiene también su origen en la parte superior izquierda, para que quede centrado simplemente le restamos la mitad del ancho del sprite a la x, y la mitad de la altura del sprite a la y:

spriteBatch.Begin();
spriteBatch.Draw(textura, new Vector2(x - (textura.Width / 2), y - (textura.Height/2)), Color.White);
spriteBatch.End();

Otra cosa que podemos hacer, es limitar el plano, en este momento el limite es el tamaño de la pantalla, pero por código podemos dejar que el plano tenga un tamaño de (100,100) o de lo que queramos, Declaramos las variables:

Int32 limiteX = 100;
Int32 limiteY = 100;

Modificamos las funciones.

public double cartesianoX(double x)
{
      Int32 punto0 = ventanaX / 2;
      return (punto0 / limiteX) * x + (punto0);
}
public double cartesianoY(double y)
{
      Int32 punto0 = ventanaY / 2;
      Int32 signo = 0;
      if (y > 0)
            signo = -1;
      else
            signo = 1;
      return (punto0 / limiteY) * signo * Math.Abs(y) + punto0;
}

Ahora por ejemplo ubiquemos la pelota en la posición (-50, -20):

 

Rotación de Objetos:

Para rotar un objeto en XNA es algo muy sencillo, en el método Draw del SpriteBatch existe un constructor donde le enviamos como parámetro el ángulo (en radianes) y XNA se encargara de rotar nuestro objeto, hay que tener muy en cuenta que para rotar el objeto debemos decir el origen, el origen es el punto sobre  el cual se va a hacer la rotación.

Por ejemplo, vamos a dibujar una “manecilla”  o “palo” como quieran llamarle, lo dibujamos desde el centro del plano cartesiano e implementamos el constructor:

spriteBatch.Draw(textura, new Vector2(x,y), null, Color.White, angulo, new Vector2(textura.Width/2 , textura.Height), 1, SpriteEffects.None, 1);

El primer parámetro es la textura, el Segundo es la posición y vamos a dibujarlo en el punto (0,0), el tercer parámetro es usada para cortar la imagen o dibujar una parte especifica de la imagen, el cuarto parámetro es el color, el quinto es el ángulo de rotación, el sexto es el punto de origen de la textura donde se va a aplicar la rotación, el séptimo parámetro la escala, el octavo los efectos y el último parámetro es la profundidad de dibujo.

El punto de origen, es un punto de la textura, nosotros vamos a usar la parte de abajo, justo en la mitad, como el ángulo va en radianes, podemos aplicar la formula que transforma un ángulo en grados sexagesimales a radianes, y para vamos a girar la manecilla al estilo de un reloj, para ello creamos una función que va a ir aumentando los grados en sexagesimales infinitamente y vamos a su vez convirtiendo el ángulo en radianes para que cada vez que se dibuje, se cambie de ángulo:

float angulo;
float rotacion;
public void girar(GameTime gameTime)
{
      angulo = (float) Math.PI * rotacion / 180;
      if (rotacion <= 360)
      {
            rotacion++;
      }
      else
      {
            rotacion = 0;
      }
}

Esta función será llamada en el método Update.

 

Si queremos formar una Hélice, lo único que debemos hacer es cambiar el origen de la rotación:

spriteBatch.Draw(textura, new Vector2(x,y), null, Color.White, angulo, new Vector2(textura.Width/2 , textura.Height /2), 1, SpriteEffects.None, 1);

El código Aquí.

About these ads

18 pensamientos en “Plano cartesiano y Rotación de Objetos – XNA

  1. Pingback: Tweets that mention Plano cartesiano y Rotación de Objetos – XNA « Escarbando Código -- Topsy.com

  2. Pingback: El Blog en números del 2010 « Escarbando Código

    • Lo del plano cartesiano es una buena idea, mas no la implementaría.
      Sin embargo, hay una forma de hacer animación, en la que no dibujas al personaje completo varias veces, sino una sola pero el personaje está dividido en partes, y cada parte se anima por sí sola. Entonces si yo hago que el brazo de un personaje se anime, tengo que buscar el punto de rotación y hacerlo girar desde ahí. Esta explicación es la base de ese tipo de animaciones. No es tonto, solo que no te has puesto a pensar para qué te puede servir.

  3. Ayuda mucho para entender como están planteados los ejes en XNA muchas gracias, y gracias por todos los tutoriales son fantásticos, gracias a esto, aprenderé ^-^

Deseas comentar o sugerir algo?

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s