Dividir pantalla (Split Screen) – XNA 2D


Cuando se usan opciones Multiplayer, o cuando se hace un juego al estilo un Nintendo Ds, se divide la pantalla, para dar la sensación de tener dos vistas y en cada división se verá algo diferente.

En XNA es fácil, para este caso se usa la clase ViewPort, el ViewPort es útil para dibujar solo en una parte de la pantalla, se define el tamaño y en método Draw se asigna el Viewport a la clase GraphicsDevice, así solo dibujara en pantalla en el pedazo que hayamos indicado.

Para ver el ejemplo en acción, voy a seguir usando el último código del algoritmo de búsqueda o pathfinding, y voy a modificarle algunas cosas.


En la clase Game1 del proyecto ColisionMapa, creamos una lista de Viewports:

List<Viewport> viewports;

Ahora en el método Initialize, inicialiamos la lista y agregamos 2 Viewports, ambos con el mismo tamaño, pero diferente posición:

protected override void Initialize()
{
// TODO: Add your initialization logic here
IsMouseVisible = true;
viewports = new List<Viewport>();
Viewport vp = new Viewport();
vp.X = 0;
vp.Y = 0;
vp.Width = this.graphics.PreferredBackBufferWidth;
vp.Height = this.graphics.PreferredBackBufferHeight / 2;
viewports.Add(vp);

vp.X = 0;
vp.Y = this.graphics.PreferredBackBufferHeight / 2;
vp.Width = this.graphics.PreferredBackBufferWidth;
vp.Height = this.graphics.PreferredBackBufferHeight / 2;
viewports.Add(vp);

base.Initialize();
}

Ahora en el método Draw, vamos a dibujar la misma escena en cada Viewport:

foreach (Viewport vp in viewports)
{
spriteBatch.Begin();
GraphicsDevice.Viewport = vp;
mapa.Draw(gameTime);
tanque.Draw(gameTime);
String heuristica = "";
switch (GestorBusqueda.Heuristica)
{
case 0:
heuristica = "Manhattan";
break;
case 1:
heuristica = "Euclidiana";
break;
case 2:
heuristica = "Custom";
break;
default:
break;
}
spriteBatch.DrawString(fuente, "Heuristica: ", new Vector2(580, 200), Color.White);
spriteBatch.DrawString(fuente, heuristica, new Vector2(580, 220), Color.White);
spriteBatch.DrawString(fuente, "Nod abiertos: " + GestorBusqueda.listaAbierta.Count.ToString(), new Vector2(580, 240), Color.White);
spriteBatch.DrawString(fuente, "Nod cerrados: " + GestorBusqueda.listaCerrada.Count.ToString(), new Vector2(580, 260), Color.White);
spriteBatch.DrawString(fuente, "Tiempo gastado: " + tiempoGastado.ToString(), new Vector2(580, 280), Color.White);
spriteBatch.End();
}
base.Draw(gameTime);
}

Si movemos el tanque por toda la pantalla, podemos ver que cuando se pasa la mitad de la pantalla, se desaparace, para corregir esto podemos modificar la clase Camara2D para que cuando el tanque se mueva, también se mueva la pantalla:

En la clase Camara2D creamos un objeto Matrix que nos va a ser útil para rotar y mover la pantalla de una forma mejor que teníamos anteriormente, también crearemos un método que nos devolverá la matriz de transformación:

//Declaraciones
private static Viewport viewport;
private static Matrix transform;
private static float rotation;
public static float Rotacion
{
get { return rotation; }
set { rotation = value; }
}

public static Matrix obtenerTransformacion(GraphicsDevice graphicsDevice)
{
transform =       Matrix.CreateTranslation(new Vector3(Posicion.X, -Posicion.Y, 0)) *
Matrix.CreateRotationZ(Rotacion) *
Matrix.CreateScale(new Vector3(Zoom, Zoom, 1)) *
Matrix.CreateTranslation(new Vector3(viewport.X * 0.5f, viewport.Y * 0.5f, 0));
return transform;
}

Se debe añadir la refencia Microsoft.Xna.Framework.Graphics;

También es necesario cambiar el tamaño de la Cámara, una forma es en el método cargarMapa de la clase TileEngine:

Camara2D.TamanoPantalla = new Vector2(Mapa.tamanoPantalla.X, Mapa.tamanoPantalla.Y/2  - tamanoTile);
Camara2D.altoTile = tamanoTile;
Camara2D.anchoTile = tamanoTile;
Camara2D.numXTiles = anchoTile;
Camara2D.numYTiles = altoTile+2;

Y en el método reiniciarTodo:

private void reiniciarTodo()
{
Camara2D.TamanoPantalla = new Vector2(Mapa.tamanoPantalla.X, Mapa.tamanoPantalla.Y / 2);//Mapa.tamanoPantalla;
Camara2D.Posicion = Vector2.Zero;//centroPantalla;
Camara2D.Zoom = 1f;
camaraCambiada();
}

En el método camaraCambiada, comentamos el código que hace la asignación de la posición de la cámara, vamos a usar otro método y por eso lo comentamos:

public void camaraCambiada()
{
//ajustar posicion
//Mapa.PosicionCamara = Camara2D.Posicion;
//Mapa.ZoomCamara = Camara2D.Zoom;
Camara2D.reiniciarCambios();
}

En el método Update, comentamos el código para que no reinicie los cambios y no se llame el método para administrar el teclado:


public override void Update(GameTime gameTime)
{
//Camara2D.reiniciarCambios();
//administrarEntradaTeclado((float)gameTime.ElapsedGameTime.TotalSeconds);
if (Camara2D.aCambiado)
{
camaraCambiada();
}
base.Update(gameTime);
}

Creamos un método público que servirá para mover la cámara:

public void moverCamara(float dX, float dY)
{
Vector2 distancia = new Vector2(dX, dY);
Camara2D.Mover(ref distancia);
}

En la clase Game1 del proyecto ColisionMapa, modificamos el método Update para adicionar la captura del teclado y mover la cámara:

//Update
mapa.moverCamara(dX * 2, dY * 2);
mapa.Update(gameTime);
base.Update(gameTime);

Listo, ahora podemos ejecutar el código y ver como se mueve la pantalla con el movimiento del tanque, y la pantalla está dividida en dos partes iguales.

Lo que queda por hacer es:

–          Centrar siempre el tanque en la cámara

–          Poder manejar dos cámaras diferentes y asignarle a una cámara un objeto como referencia

–          Adicionar la opción de Multiplayer y ver en cada Viewport el movimiento de cada jugador

Un pensamiento en “Dividir pantalla (Split Screen) – XNA 2D

  1. Hola que tal, muchas gracias por los tutoriales los eh seguido y de verdad que me han servido muchas gracias, pero tengo un problema, no puedo hacer que la camara se mueva podrias ayudarme? si sale un aumento de la posicion de la camara mas sin embargo no hay un desplazamiento en el dibujar de los tile se queda como esta todo, estare omitiendo algun punto importante? lo utilice con los dos proyectos el mio y el que tienes en el de busqueda, agregando el codigo de este tutorial pero el resultado es el mismo podrias por favor ayudarme… Gracias

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