viernes, 15 de julio de 2011

GameEngine: Capitulo 20.Scroll

Hola a todos,

Bienvenidos a un nuevo capitulo de como crear nuestro propio game engine desde 0.

El capitulo de hoy trata sobre el scroll.

  • Que es el scroll? A grandes rasgos puede decirse que el scroll es el desplazamiento del fondo del escenario que nos permite tener la ilusión que el personaje se va moviendo. Es decir, que podemos dejar el personaje pintandose justo en el centro de la pantalla y que lo que se vaya moviendo sea el fondo.
  • Como lo hemos implementado? Basicamente se han introducido dos variables nuevas dentro del Graphics2DManager llamadas scroll_x y scroll_y que se utilizan como coordenadas de referencia para todos los gráficos en los que aplicamos el scroll. Estas variables las podemos setear desde el código del juego (por ejemplo, forzando que el personaje esté en el centro de la pantalla) . Estas variables se suman a las coordenadas de todos los gráficos y esto hace que se genere la sensación de movimiento. A fin de indicar que gráficos queremos que tengan scroll y que gráficos no, hemo usado el sistema de flags que ya se utilizó hace pocos capitulos para marcar la inversión en x.
  • Algo más a tener cuenta? Pues si, hemos creado una función nueva que se encarga de calcular el angulo entre un punto que definimos y el puntero del ratón. Esta función ya tiene en cuenta el scroll y tiene la gracia que en la mayoria de juegos 2D será necesaria.

A nivel de código, los cambios son ridiculos:

En el código de juego:
void draw ()
{
static bool right = true;
static int angle = 0;
static int xplayer=300, yplayer = 260;

//A todo lo que pintemos a partir de ahora se le aplicará scroll.
LPE.EnableFlag("SCROLL");

TileManager::singleton().DrawMap(); //Pintamos el mapa cargado

LPE.Scroll(xplayer,yplayer);

if ( LPE.KeyBoardRight() )
{
xplayer++;
right = true;
}

if ( LPE.KeyBoardLeft() )
{
xplayer--;
right = false;
}

if ( LPE.KeyBoardUp() )
{
yplayer++;
}

if ( LPE.KeyBoardDown() )
{
yplayer--;
}

if ( right )
LPE.DisableFlag("INVX");
else
LPE.EnableFlag("INVX");
angle = LPE.Angle2DToMouse(xplayer,yplayer);

if( angle < 0.1 ) angle = 0.1;

//Personaje
LPE.DrawAnim(xplayer,yplayer,"RUN");

if(right)
LPE.DrawCenterRotate(xplayer-10,yplayer-30,angle,"PLAYER",3);
else
LPE.DrawCenterRotate(xplayer-60,yplayer-30,angle,"PLAYER",3);

//Cuando hemos acabado de pintar lo que queremos tener girado, desactivamos los flips de x
LPE.DisableFlag("INVX");
//Cuando hemos acabado de pintar lo que queremos tener con el scroll activado, lo desactivamos.
LPE.DisableFlag("SCROLL");

//Pintado de textos
LPE.DrawText("SYSTEM",200,350,"ANIMACIONES 2D");
}


Si os fijais en el video que hay abajo el texto "ANIMACIONES 2D" se mantiene estatico en pantalla ya que se pinta despues de hacer el disable del SCROLL.

Este sistema de flag nos permite tener muchisimas menos funciones a las que acceder para dibujar nuestros juegos.Con el tiempo le iremos viendo más utilidades.

A nivel de código de motor solo pondré un par de ejemplos ya que el resto es copiar y pegar:
Dentro del Graphics2DManager:

//Calcula el angulo existente entre el punto dado y el ratón (bastante util en juegos de disparos 2D)
float Graphics2DManager::AngleToMouse(int xp, int yp)
{
int angle;
int x,y;
LPE.GetMousePosition(&x,&y);
angle = atan2( (double)( (yp+scroll_y) - y), (double)( x - (xp+scroll_x)) ) * 180/PI + 360;
angle %= 360;

return (float) angle;

}

//Pinta un gráfico partido con su tamaño original en las coordenadas x e y
void Graphics2DManager::InsertDrawPart(float x, float y, char cad[], int p)
{
int w,h;
float xi,yi,xf,yf;

if(flags_scroll)
{
x += scroll_x;
y += scroll_y;
}

w = TextureManager::singleton().GetWidth(cad,p);
h = TextureManager::singleton().GetHeight(cad,p);

TextureManager::singleton().GetBox(cad,p, &xi,&yi,&xf,&yf);
task2D[num_task2D].type = TYPE_DRAW ;
task2D[num_task2D].invx = flags_invx;
task2D[num_task2D].scroll = flags_scroll;
task2D[num_task2D].angle = 0;
task2D[num_task2D].Xi = xi;
task2D[num_task2D].Yi = yi;
task2D[num_task2D].Xf = xf;
task2D[num_task2D].Yf = yf;

task2D[num_task2D].xi = x;
task2D[num_task2D].yi = y;
task2D[num_task2D].xf = (x+w);
task2D[num_task2D].yf = (y+h);

sprintf(task2D[num_task2D].cad,"%s",cad);

num_task2D++; //Incrementamos el número de tarea
}

Fijaos que las funciones de pintado como tal no se han tenido que modificar , solo se ha tenido que tocar las funciones de inserción de tareas.

Ya visto todo este código solo nos queda mirar el video de como ha quedado el resultado. El sistema de físicas todavia no está implementado, pero si todo va bien en breve tendremos unas fisicas 2D sencillitas implementadas:


Os habeis dado cuenta que todo este video es el trabajo de solo 24 lineas de código dentro del juego?? :D

LordPakusBlog
Espero que hayais disfrutado y aprendido... nos vemos

0 comentarios :

Publicar un comentario

Entradas populares