Razón Artificial

La ciencia y el arte de crear videojuegos

Introducción a la programación gráfica 2D (II)

Escrito por adrigm el 19 de agosto de 2010 en Desarrollo Videojuegos, Noticias, Programación | 5 Comentarios.

Ahora que sabemos lo básico vamos a entrar en materia diferenciando los gráficos 2D y 3D y explicando los conceptos básicos de como trabajan las bibliotecas 2D.

Diferencias entre 3D y 2D

Una biblioteca 3D se basa en polígonos. Estos polígonos están formados por vértices que tiene una serie de coordenadas para definirlos. Lo que hace nuestra biblioteca 3D es proyectar estos polígonos sobre un plano, en nuestro caso ese plano es la pantalla.

Cuando dibujamos esos polígonos en pantalla tenemos la opción de ponerles una imagen que se llama textura. A este proceso se le llama rasterización.

Se podría crear aplicaciones 2D utilizando una biblioteca 3D, bastaría con usar una proyección ortogonal.

Sin embargo, no todas las bibliotecas son así, existen otras que son exclusivas de 2D (SDL, Pygame…) en la que no existen los polígonos.

Estas bibliotecas se remontan a los ordenadores antiguos donde las gráficas no eran nada potentes y hacer calculos en como flotante que requieren los Bibliotecas 3D era inviable. Todo se hacía mediante procesador y les era más fácil hacer cálculos con operaciones enteras (esto ha cambiado ahora).

Conceptos básicos de programación 2D

Las bibliotecas 2D se basan en el concepto de superficies y de operaciones con superficies. Una superfice no es más que un espacio en la memoria donde guardar unos datos que se corresponden a una imagen. Las operaciones consisten en copiar trozos de una superficie origen a otra de destino.

Tomemos como ejemplo el Paint. Tenemos un lienzo en blanco en el que podemos dibujar, cargar una imagen desde el ordenador, etc.

Ahora ejecutamos otro Paint, tendríamos otro lienzo en blanco independiente del primero. Estos dos lienzos serían dos superficies en las que podriamos dibujar o copiar parte de otra superficie.

Por ejemplo, cogemos un trozo de la imagen de uno de los Paints y la copiamos en el otro Dlienzo. Esta operación se llamo Blit y es la mas importante de una biblioteca 2D.

Al igual que en Paint, al hacer un Blit, lo que había en la superficie destino en la región que sobreescribimos se pierde para siempre. Al copiar sobre esa posición machacamos los datos anteriores. Esto es importante si tenemos, por ejemplo, un personaje moviéndose sobre un escenario. Al dibujar el personaje destruimos esa región del escenario, así que si el personaje se mueve, tendremos que volver a dibujar de nuevo el escenario por cada fotograma.

También de esto sacamos que el orden en que hagamos los blits importa, y mucho. Si algo tiene que quedar por encima, tiene que ser lo último que bliteemos.

Vale, con esto ya sabemos como montar imagenes entre varias superficies, pero ¿Cómo mostramos todo esto en la pantalla? Pues fácil, la pantalla no es más que otra superficie, una superficie especial que se muestra. Por tanto para mostrar algo en pantalla solo debemos hacer blits a esta superficie especial que se suele llamar screen.

La superficie de la pantalla (screen) suele tener un tamaño único durante todo el juego que es la resolución, como por ejemplo 640×480, este es el tamaño de nuestro lienzo y sobre él podemos hacer todos los blits que queramos.

Flipping

Vale, ahora tenemos una imagen que hemos compuesto sobre el Buffer Primario. Ya tenemos todo listo para que se muestre en el monitor. ¿Como hacemos para “actualizar” el monitor?

Depende, hay dos maneras de hacerlo, la fácil, y la difícil.

La fácil es llamar a la función de nuestra biblioteca que se encargue de  dibujar y actualizar directamente todo a la superficie de nuestra screen. El problema de esto es que el monitor tiene un refresco de actualización, y si llamamos a esta función en el momento en que el monitor está dibujando algo, lo que veremos será un parpadeo bastante molesto.

Lo que queremos es que esa actualización se produzca justo en el momento en que el monitor ha terminado de dibujar un fotograma, y esta preparándose para el siguiente. A esto se le llama “sincronizarlo con el refresco vertical”, o en inglés, “VSYNC”.

Para hacer eso, lo que se usa es una técnica llamada “Double Buffer”. Consiste en que tendremos un buffer Secundario (o “BackBuffer”), además del primario. Nuestra imagen la compondremos en el secundario, y llegado el momento, intercambiaremos ambos buffers para que el secundario pase a ser el primario y viceversa, actualizando la imagen en el monitor. Este intercambio estará sincronizado con el refresco del monitor.

La mayoría de las bibliotecas gráficas modernas tienen funciones o clases que se encargan ellas solas de hacer todo este del doblebuffer y nosotros simplemente tenemos que decir que actualice la pantalla y ella se encarga de crearlo, pero es importante conocer como funciona.

Resumiendo:

  • Programación 3D != Programación 2D.
  • Programación 3D == Punto Flotante, matrices, proyecciones + rasterizaciones.
  • Programación 2D == Operaciones enteras, ints, copias de trozos de memoria de un lado a otro.
  • Superficie: Espacio en memoria donde tenemos una imagen.
  • Blit: Copy-paste de una región de una superficie sobre otra.
  • Buffer Primario: Superficie que contiene lo que se dibuja en pantalla.
  • Double Buffer: Algo raro que evita los parpadeos.

Autor: Autor: Sergio Hidalgo. serhid@wired-weasel.com
Fuente: http://www.wired-weasel.com/users/serhid/tutos/tut1.html

5 Comentarios en "Introducción a la programación gráfica 2D (II)"

  1. ratnu dice:

    No estoy del todo de acuerdo con tu diferenciación de conceptos de 2D y 3D.

    Se pueden, y se suelen, hacer animaciones 2D vectoriales para las que es necesario pensar con polígonos y toda la cacharrería.

    Es más, se puede usar OpenGL y la tarjeta gráfica para manipular y mostrar esas imágenes y no sobrecargar la CPU. O al menos eso es lo que he entendido después de leer varios tutoriales sobre pyglet ( parecido a pygame ) y OpenGL.

    Presentación muy recomendable: http://tartley.com/files/stretching_pyglets_wings/presentation/

  2. adrigm dice:

    hay bibliotecas como pyglet o SFML basadas en OpenGL que ciertamente usan polígonos y demás para representar 2D, pero para propósito general y aprender lo básico no creo que tenga cabida aquí.

    De todas maneras no se realmente si estas bibliotecas tratas objetos 2D como 3D o como lo hacen, intentaré documentarme.

  3. ratnu dice:

    Más que nada lo decía porque igual con un poco de esfuerzo se puede aligerar mucho el trabajo de la CPU enviandolo a la GPU y así dar un poco más de rienda suelta a Python.

    Pero bueno, para gustos colores y sí, siendo un tutorial, esas cosas no se suelen tener muy en cuenta.

    De todos modos, gracias por la información sobre el flipping.

  4. […] los conceptos básicos de la programación de juegos 2D. Parte 1, Parte 2 y Parte […]

  5. […] Introducción a la programación gráfica 2D (II) […]

Deja un comentario