Anuncios

Bienvenidos sean a este post, hoy hablaremos mas sobre el renderizado de las texturas.

Anuncios

En el post anterior hablamos sobre el rectangulo de origen (origenRectangulo) y el rectangulo de destino (destinoRectangulo) pero no explicamos para que se usan, hoy nos centraremos en ellos. Para trabajar con ellos, usaremos al codigo del post anterior pero si no lo tienen les dejo un link para descargarlo:

Proyecto Juego

Anuncios

Descarguen el archivo y extraigan el contenido pero no funcionara porque deben revincular a SDL. Para ello, les recomiendo este post donde explico como hacerlo. Una vez que este todo configurado y funcionando podemos pasar a trabajar con el codigo. En el post anterior cuando trabajamos con la foto definimos dos rectangulos, tanto sus ejes como su ancho y alto, una vez definidos los usamos para enviarlos al metodo encargado de copiarlo desde una textura a la ventana.. Si volvemos a nuestro proyecto Juego cuando agregamos a nuestra imagen utilizamos toda la imagen pero nosotros tambien tenemos la posibilidad de poder definir que parte de la imagen se vea o ubicarla en otra posicion pero para ello deberemos hacer algunas modificaciones. Lo primero que haremos es hacer una serie de modificaciones en Juego.cpp. En la funcion iniciar, vamos a agregar las siguientes dos lineas despues de la funcion SDL_GetTextureSize:

	m_origenRectangulo.w = 50;
	m_origenRectangulo.h = 50;
Anuncios

En este caso establecimos un valor de ancho y de alto de 50 (pixels), pero debemos hacer una modificacion mas. Tomemos estas dos liineas:

    m_destinoRectangulo.w = m_origenRectangulo.w = w;
    m_destinoRectangulo.h = m_origenRectangulo.h = h;
Anuncios

Y las modificaremos de la siguiente manera:

    m_destinoRectangulo.w = m_origenRectangulo.w;
    m_destinoRectangulo.h = m_origenRectangulo.h;
Anuncios

Esto hara que no tome el valor que obtuvimos de la funcion SDL_GetTextureSize sino con los establecidos anteriormente. Ahora si lo volvemos a probar se vera de la siguiente manera

Anuncios

Como pueden observar redujimos el area de nuestra imagen al variar el ancho y el alto del rectangulo de origen, esto ocasiona que se reduzca la porcion que mostraremos en pantalla. Ahora cambiaremos de posicion a nuestra imagen y para ello agregaremos las siguientes lineas despues de que establecemos los valores de X e Y de los rectangulos:

	m_destinoRectangulo.x = 100;
	m_destinoRectangulo.y = 100;
Anuncios

Si bien en las dos lineas anteriores a estas establecimos el valor de los ejes X e Y, al volver a definirlas seran distintas de las definidas en m_origenRectangulo. Si lo compilamos y probamos veremos la siguiente salida

Anuncios

Como pueden observar corrimos la imagen a las coordenadas informadas en X e Y pero nosotros tambien podemos cambiar la ubicacion del rectangulo que mostrara otra parte de la imagen, para ello primero tomaremos estas dos lineas:

	m_destinoRectangulo.x = m_origenRectangulo.x = 0;
	m_destinoRectangulo.y = m_origenRectangulo.y = 0;
Anuncios

Y las modificaremos de la siguiente manera:

	m_origenRectangulo.x = 50;
	m_origenRectangulo.y = 50;
Anuncios

Probemos de compilar y veamos que sucede con la siguiente imagen

Anuncios

Observen como se mantuvo la posicion de la imagen que modificamos anteriormente pero ahora tomo otras coordenadas para comenzar y desde ahi devolvio un rectangulo de 50 x 50 pero con los ejes internos de la imagen, resumiendo un poco lo visto hasta ahora nosotros tenemos las siguientes posibilidades:

  • Cambiar el tamaño del rectangulo que mostraremos de la imagen
  • Cambiar la posicion donde estara la imagen
  • Cambiar la posicion desde donde comenzara el rectangulo
Anuncios

Si bien esto no parece muy importante pronto descubriremos que esto es muy util, especialmente lo relacionado a los graficos. Con todo esto comentado, la sintaxis de la funcion va a ser:

SDL_RenderTexture(<objeto renderizador>, 
	<textura o imagen>, 
	&<define el rectangulo a mostrar>, 
        &<sera el encargado de ubicarlo en la ventana>);
Anuncios

Recuerden que los dos ultimos atributos son objetos por lo tanto internamente no solo almacenan un valor sino todos los que contenga la estructura o clase que los creo (SDL_FRect en este caso), pero nosotros tambien podemos pasar objetos nulos. Para ello, debemos modificar a SDL_RenderTexture de la funcion renderizar de la siguiente manera:

SDL_RenderTexture(m_pRenderer, m_pTextura, NULL, NULL);
Anuncios

Si lo compilamos y probamos veremos la siguiente salida

Anuncios

En este caso, al no enviar ninguno de los datos anteriores la funcion tomo los datos de la ventana y los utilizo para definir la renderizacion. Con esto ya cubrimos lo basico en lo referido a las areas de una imagen, pasemos al siguiente tema.

Anuncios

Animando una lamina de sprites

Cuando hablamos de animaciones en videojuegos, en general se hacen por medio de una serie de sprites en una sola lamina o linea, por ejemplo como esta

Anuncios

En este caso, podemos ver una secuencia de los distintos cuadros del tigre dientes de sable corriendo. Lo que haremos sera generar cada uno de los rectangulos para cada una de las imagenes y las mostraremos una detras de la otra dando la sensacion de una animacion, tal como si dibujaramos los mismos en un bloc de papeles y pasaramos uno atras del otro. Primero descarguen el siguiente archivo:

Anuncios

Descarguen el archivo y extraigan el contenido dentro de la carpeta assets que creamos en el post anterior. Una vez hecho esto procederemos a hacer una serie de modificaciones en nuestro codigo para poder ver esto en accion. La primera sera dentro de la funcion renderizar donde cambiaremos la siguiente llamada:

SDL_SetRenderDrawColor(m_pRenderer, 255, 255, 255, 255);
Anuncios

De la siguiente manera:

SDL_SetRenderDrawColor(m_pRenderer, 0, 0, 0, 255);
Anuncios

Esto se encargara de modificar el color de fondo de nuestro renderizador, nuestro siguiente paso sera modificar la linea encargada de cargar la imagen pero esta se encuentra en la funcion iniciar:

SDL_Surface* iSurfaceTemp = SDL_LoadBMP("assets/rider.bmp");
Anuncios

De la siguiente forma:

SDL_Surface* iSurfaceTemp = SDL_LoadBMP("assets/animate.bmp");
Anuncios

Con esto ya cambiamos la imagen que vamos a renderizar, el siguiente paso sera modificar todos los datos de los dos rectangulos para ello modificaremos el siguiente segmento de codigo:

    m_origenRectangulo.h = 50;
    m_origenRectangulo.w = 50;
    m_origenRectangulo.x = 50;
    m_origenRectangulo.y = 50;
    m_destinoRectangulo.x = 100;
    m_destinoRectangulo.y = 100;
    m_destinoRectangulo.w = m_origenRectangulo.w;
    m_destinoRectangulo.h = m_origenRectangulo.h;
Anuncios

Las cambiaremos de la siguiente manera:

    m_origenRectangulo.h = 82;
    m_origenRectangulo.w = 128;
    m_origenRectangulo.x = m_destinoRectangulo.x = 0;
    m_origenRectangulo.y = m_destinoRectangulo.y = 0;
    m_destinoRectangulo.w = m_origenRectangulo.w;
    m_destinoRectangulo.h = m_origenRectangulo.h;
Anuncios

En este caso volvemos a los ejes X e Y de m_destinoRectangulo y m_origenRectangulo con el valor 0, despues asignamos al ancho y alto de m_destinoRectangulo los valores de m_origenRectangulo. La unica diferencia es que asignamos el valor de ancho (w) y alto (h) de m_origenRectangulo con un valor, nuestro ultimo paso sera definir la funcion actualizar y para ello lle agregaremos el siguiente codigo:

void Juego::actualizar()
{
	m_origenRectangulo.x = 128 * int(((SDL_GetTicks() / 100) % 6));
}
Anuncios
Anuncios

Como lo unico que necesitamos es mover el rectangulo en el eje X u horizontal, el unico eje que actualizaremos sera el eje X del rectangulo de origen (es decir el de la imagen), donde 128 es el ancho de cada uno de los sprites y convertimos en entero el resultado de la division del valor devuelto por SDL_GetTicks por cien. A este resultado usamos el operador de modulo con seis, que es la cantidad de cuadros en la animacion. Esto hara que mantengamos la animacion cada 1 segundo, se desplace al siguiente cuadro y se mantenga dentro del rango. Si se preguntan sobre la funcion SDL_GetTicks, esta devuelve la cantidad de milisegundos desde que SDL fue iniciado. Con esto tenemos nuestro metodo finalizado solo nos resta modificar a la funcion renderizar de la siguiente manera:

void Juego::renderizar() {
    SDL_SetRenderDrawColor(m_pRenderer, 0, 0, 0, 255);
    SDL_RenderClear(m_pRenderer);
    SDL_RenderTexture(m_pRenderer, m_pTextura, &m_origenRectangulo, 
        &m_destinoRectangulo);
    SDL_RenderPresent(m_pRenderer);
    actualizar();
}
Anuncios

Principalmente volvimos a modificar SDL_RenderTexture para que utilice los rectangulos que definimos nuevamente en la funcion iniciar, y agregamos la funcion actualizar en esta. Si lo compilamos y probamos debera verse como el siguiente video

Anuncios

Con esto logramos una animacion basica en SDL, si bien no es muy complicado tiene su dificultad. Un dato particular que siempre deben tener en cuenta es saber el valor del ancho de cada frame o cuadro o sprite para el momento de pasar a cada uno de ellos. Pasemos a hablar sobre el ultimo tema.

Anuncios

Nuestro ultimo tema sera la capacidad de poder revertir una imagen. En determinadas situaciones necesitaremos de esta accion ya que nuestro jugador o los enemigos deben moverse hacia un lado u otro. Tenemos dos opciones para hacer esto, uno es creando una nueva linea de sprites con las imagenes invertidas y la segunda es utilizar la funcion SDL_RenderTextureRotated. Antes de que la ejecutemos veamos la tabla de los valores que disponemos para hacer el FLIP en dicha funcion:

Valor de SDL_FlipModeProposito
SDL_FLIP_NONENinguna inversion
SDL_FLIP_HORIZONTALInversion horizontal
SDL_FLIP_VERTICALInversion vertical
Anuncios

Nuestro siguiente paso sera la modificacion de la funcion renderizar de la siguiente manera:

void Juego::renderizar() {
    SDL_SetRenderDrawColor(m_pRenderer, 0, 0, 0, 255);
    SDL_RenderClear(m_pRenderer);
    SDL_RenderTextureRotated(m_pRenderer, m_pTextura, &m_origenRectangulo, 
        &m_destinoRectangulo,0,0, SDL_FLIP_HORIZONTAL);
    SDL_RenderPresent(m_pRenderer);
    actualizar();
}
Anuncios

Basicamente lo unico que reemplazamos en la funcion encargada de la renderizacion. Los cuatros atributos que pasamos son los mismos a la anterior pero los siguientes dos atributos son para indicar el angulo de rotacion y el punto de centro que usaremos para la rotacion respectivamente. El ultimo atributo sera para indicar el tipo de inversion que haremos. Podemos volver a compilar y probarlo tal como se ve en el siguiente video

Anuncios

En resumen, hoy hemos visto una version mas avanzada de dibujar, hemos visto como ver una parte de la imagen, como reubicarla en nuestra renderizacion, luego hemos hablado como hacer animaciones a partir de una lamina de sprites, esto gracias a lo visto en la primera parte, luego hicimos la animacion y por ultimo como invertir la animacion sin mucho esfuerzo. Espero les haya sido de utilidad y les dejo un link a GitHub donde estan los codigos creados hoy:

Dibujo mas avanzado / GitHub

Les dejo algunas de mis redes sociales para seguirme o recibir una notificacion cada vez que subo un nuevo post:

Anuncios
pp258

Donación

Es para mantenimento del sitio, gracias!

$1.50