hugoruscitti/pilas

View on GitHub
data/manual/imagen/index.json

Summary

Maintainability
Test Coverage
{
    "content": "<h1 id=\"manejo-de-imagenes\">Manejo de im\u00e1genes</h1>\n<p>En los videojuegos 2D las im\u00e1genes suelen estar en formatos\ngr\u00e1ficos como <strong>png</strong> o <strong>jpg</strong> ya dise\u00f1ados con anterioridad.</p>\n<p>En <code>pilas</code> se pueden cargar estos recursos usando\nel m\u00f3dulo <code>imagenes</code>. Por ejemplo, si tenemos una\nimagen llamada <code>hola.png</code> podr\u00edamos incorporarla a\nnuestro juego as\u00ed:</p>\n<pre><code class=\"python\">hola = pilas.imagenes.cargar('hola.png')\n</code></pre>\n\n<p>Las im\u00e1genes no se imprimen directamente en pantalla, en\nsu lugar tienes que crear un Actor y asignarle la\nimagen.</p>\n<p>Por ejemplo, el siguiente c\u00f3digo muestra la imagen\nen pantalla:</p>\n<pre><code>imagen = pilas.imagenes.cargar(\"mi_personaje.png\")\nactor = pilas.actores.Actor(imagen)\n</code></pre>\n<p>otra opci\u00f3n similar es crear al actor, y luego\nasignarle la imagen:</p>\n<pre><code>imagen = pilas.imagenes.cargar(\"mi_personaje.png\")\nactor = pilas.actores.Actor()\n\nactor.imagen = imagen\n</code></pre>\n<p>Cualquiera de las dos opciones produce el mismo\nresultado, personaje \"cambiar\u00e1\" de apariencia\ncuando se le asigne una nueva imagen.</p>\n<h2 id=\"imagenes-de-fondo\">Im\u00e1genes de fondo</h2>\n<p>Muchas veces queremos que las im\u00e1genes cubran el fondo de pantalla\ncompletamente, como si se tratara de un fondo o papel tapiz.</p>\n<p>Si la imagen es suficientemente gr\u00e1nde para cubrir la pantalla, podemos\ncargarla como una imagen normal y luego crear un fondo que la represente:</p>\n<pre><code>fondo = pilas.fondos.Fondo()\nfondo.imagen = pilas.imagenes.cargar('mi_fondo.png')\n</code></pre>\n<p>Ahora, si en realidad queremos que el fondo se dibuje como si fuera un\nmozaico (o papel tapiz), tenemos que indicarle a la imagen que se re-dibuje\nmuchas veces hasta cubrir el fondo de pantalla. El c\u00f3digo es muy similar\nal anterior, solo que ahora usamos las propiedades <code>repetir_horizontal</code> y\n<code>repetir_vertical</code></p>\n<pre><code>fondo = pilas.fondos.Fondo()\nfondo.imagen = pilas.imagenes.cargar('mi_fondo.png')\n\nfondo.imagen.repetir_vertical = True\nfondo.imagen.repetir_horizontal = True\n</code></pre>\n<h2 id=\"grillas-de-imagenes\">Grillas de im\u00e1genes</h2>\n<p>Un forma conveniente de almacenar las im\u00e1genes de tus\npersonajes es usar una grilla.</p>\n<p>La siguiente imagen es una grilla de 10 columnas\nque utilizamos para crear al personaje \"pingu\":</p>\n<p><img alt=\"\" src=\"../imagenes/imagen/pingu.png\" /></p>\n<p>Internamente la imagen se almacena as\u00ed, pero a la\nhora de mostrarse en pantalla se puede seleccionar\nel cuadro.</p>\n<p>Este es un ejemplo que carga la grilla de mas arriba\ny genera un actor para mostrar el cuadro 1:</p>\n<pre><code>actor = pilas.actores.Actor()\ngrilla = pilas.imagenes.cargar_grilla(\"pingu.png\", 10)\nactor.imagen = grilla\n</code></pre>\n<p>Ten en cuenta que el \u00faltimo argumento de la funci\u00f3n <code>pilas.imagenes.cargar_grilla</code> es la cantidad de columnas que\ntiene la grilla. Tambi\u00e9n es posible usar funciones\nque tengan filas y columnas, solo tendr\u00edas que indicar un\nargumento mas con el n\u00famero de filas. Lo veremos mas adelante.</p>\n<p>Puedes ejecutar la siguiente sentencia para ver\nla documentaci\u00f3n completa de esta funci\u00f3n:</p>\n<pre><code>help(pilas.imagenes.cargar_grilla)\n</code></pre>\n<h2 id=\"reproduciendo-animaciones\">Reproduciendo animaciones</h2>\n<p>Tener una grilla de imagenes es una buena\nforma de comenzar a realizar animaciones.</p>\n<p>Si quieres tomar una grilla y mostrar una\ny otra vez sus cuadros podr\u00edas usar el actor Animaci\u00f3n.</p>\n<p>El siguiente c\u00f3digo genera un actor que mostrar\u00e1\nuno a uno los cuadros de la grilla:</p>\n<pre><code>grilla = pilas.imagenes.cargar_grilla(\"explosion.png\", 7)\np = pilas.actores.Animacion(grilla, True)\n</code></pre>\n<p>El actor <code>Animacion</code>, tambi\u00e9n puede recibir c\u00f3mo argumento\nla velocidad con la que tiene que reproducir la animaci\u00f3n (medida\nen cuadros por segundo).</p>\n<p>El segundo argumento indica que la animaci\u00f3n tiene que ser\nc\u00edclica (nunca termina).</p>\n<p>Observa este ejemplo, muestra la misma animaci\u00f3n de antes pero\nmostrando un cuadro por segundo y se elimina cuando termina:</p>\n<pre><code>grilla = pilas.imagenes.cargar_grilla(\"explosion.png\", 7)\np = pilas.actores.Animacion(grilla, False, velocidad=1)\n</code></pre>\n<h2 id=\"animaciones-controladas-a-mano-con-una-grilla\">Animaciones controladas a mano con una grilla</h2>\n<p>Otra forma de hacer animaciones, es asociar una grilla\ndirectamente a un actor y cambiar el cuadro a mostrar.</p>\n<p>Por ejemplo, la siguiente sentencia avanza al siguiente\ncuadro de animaci\u00f3n en la grilla. Recuerda que\ncomienza en 1:</p>\n<pre><code>grilla.avanzar()\nactor.imagen = grilla\n</code></pre>\n<p>Ten en cuenta que el m\u00e9todo <code>avanzar</code> va a retornar <code>True</code> o <code>False</code>.\n<code>True</code> significa que la grilla ha avanzado y ha mostrado un cuadro nuevo.\n<code>False</code> significa que la grilla volvi\u00f3 a mostrar el primer cuadro.</p>\n<p>Este valor de retorno es muy \u00fatil a la hora de\nsaber si una animaci\u00f3n termin\u00f3, y poder tomar\nalguna decisi\u00f3n al respecto.</p>\n<h2 id=\"grillas-con-filas-y-columnas\">Grillas con filas y columnas</h2>\n<p>En el ejemplo anterior mencion\u00e9 que las grillas pueden\ntener filas y columnas. Esto se logra gracias a que\npython permite tener funciones y m\u00e9todos con argumentos\nopcionales.</p>\n<p>En este caso, la funci\u00f3n <code>cargar_grilla</code> tambi\u00e9n\npuede recibir la cantidad de filas que tiene una grilla:</p>\n<pre><code>animacion = pilas.imagenes.cargar_grilla(\"grilla.png\", 2, 2)\n</code></pre>\n<p>el primer n\u00famero <code>2</code> indica que la grilla tiene dos\ncolumnas y el segudo <code>2</code> indica que la grilla tiene dos\nfilas.</p>\n<p>Cuando usas una grilla con pilas y columnas, la funci\u00f3n <code>avanzar</code>\nque vimos antes va a recorriendo los cuadros de la misma\nmanera en que se lee una historieta (de izquierda\na derecha y de arriba a abajo).</p>\n<p>Esta es la apariencia de la im\u00e1gen que usamos antes y\nlos n\u00fameros indican el \u00f3rden con que pilas leer\u00e1 los cuadros:</p>\n<p><img alt=\"\" src=\"../imagenes/imagen/grilla_con_columnas.png\" /></p>\n<h2 id=\"haciendo-animaciones-sencillas\">Haciendo animaciones sencillas</h2>\n<p>En muchas oportunidades nos interesa hacer animaciones simples\ny que se repitan todo el tiempo sin mucho esfuerzo.</p>\n<p>Con lo que vimos hasta ahora, hacer esas animaci\u00f3n\nes cuesti\u00f3n de cargar una grilla y llamar cada\nun determinado tiempo a la funci\u00f3n <code>avanzar</code>.</p>\n<p>Pero como esta es una tarea muy com\u00fan, en <strong>pilas</strong> hay una forma\nmas sencilla de hacer esto.</p>\n<p>Existe un actor llamado <code>Animaci\u00f3n</code> que tiene la\ncapacidad de mostrar una animaci\u00f3n c\u00edclica, es decir,\nque se repita todo el tiempo, comenzando desde el principio\ncuando llega al final.</p>\n<p>Veamos un ejemplo, esta imagen tiene <code>6</code> cuadros de animaci\u00f3n\nordenados en columnas:</p>\n<p><img alt=\"\" src=\"../imagenes/imagen/grilla_fuego.png\" /></p>\n<p>Una forma sencilla de convertir esta animaci\u00f3n en un actor\nsimple es crear la grilla, construir un actor <code>Animacion</code> e\nindicarle a pilas que ser\u00e1 una animaci\u00f3n c\u00edclica, es decir, que\nse tendr\u00e1 que repetir indefinidamente:</p>\n<pre><code>grilla = pilas.imagenes.cargar_grilla(\"fuego.png\", 6)\nactor = pilas.actores.Animacion(grilla, ciclica=True)\n</code></pre>\n<p>El resultado en la ventana ser\u00e1 una animaci\u00f3n de fuego que\nno terminar\u00e1 nunca. Cuando el actor termine de mostrar el\ncuadro 6 de la animaci\u00f3n regresar\u00e1 al primero para comenzar\nnuevamente.</p>\n<p>Otra posibilidad es especificar el argumento <code>ciclica=False</code>. En\nese caso el actor comenzar\u00e1 a mostrar la animaci\u00f3n desde el cuadro\n1 y cuanto termine eliminar\u00e1 al actor de la ventana. Esto es \u00fatil\npara hacer efectos especiales, como explosiones o destellos, cosas\nque quieres tener en la ventana un instante de tiempo y nada mas...</p>\n<h2 id=\"haciendo-actores-con-animacion\">Haciendo actores con animaci\u00f3n</h2>\n<p>Puede que quieras hacer un actor que tenga m\u00faltiples animaciones, y\nque las muestre en determinados momentos. Por ejemplo, si tienes\nuna nave con motores, es probable que quieras mostrar una animaci\u00f3n\nde motores en funcionamiento cuando la nave avanza y detener la\nanimaci\u00f3n de motores cuando finaliza el movimiento.</p>\n<p>Una forma de lograr esto de manera sencilla es crear tu propio\nactor, y que este tenga dos atributos, uno para cada animaci\u00f3n:</p>\n<pre><code class=\"python\">class MiNave(pilasengine.actores.Actor):\n\n    def iniciar(self, x=0, y=0):\n        self.animacion_detenida = pilas.imagenes.cargar_grilla(&quot;nave_detenida.png&quot;, 1)\n        self.animacion_movimiento = pilas.imagenes.cargar_grilla(&quot;nave_en_movimiento.png&quot;, 3)\n</code></pre>\n\n<p>Luego, en el m\u00e9todo <code>actualizar</code> del propio actor podr\u00edas\navanzar la animaci\u00f3n actual y permitirle al programador invocar\nm\u00e9todos para intercambiar animaciones:</p>\n<pre><code class=\"python\">class MiNave(pilasengine.actores.Actor):\n\n    # [...] codigo anterior\n\n    def poner_en_movimiento(self):\n        self.imagen = self.animacion_movimiento\n\n    def poner_en_reposo(self):\n        self.imagen = self.animacion_detenida\n\n    def actualizar(self):\n        self.imagen.avanzar()\n</code></pre>\n\n<p>Como puedes ver, el concepto inicial es el mismo, cuando\nqueremos cambiar de animaci\u00f3n tenemos que cambiar de grilla, y\ncuando queremos avanzar la animaci\u00f3n solamente tenemos que\nllamar al m\u00e9todo <code>avanzar</code>.</p>\n<h2 id=\"animaciones\">Animaciones</h2>\n<p>Adem\u00e1s de las im\u00e1genes y las grillas, pilas incluye un recurso llamado animaci\u00f3n, que nos permite declarar y utilizar animaciones almacenadas en una grilla.</p>\n<p>Por ejemplo, si tenemos una grilla con varios cuadros de animaci\u00f3n como aqu\u00ed:</p>\n<p><img alt=\"\" src=\"../imagenes/imagen/alien-simple.png\" /></p>\n<p>podemos cargar la grilla completa y definir las dos\nanimaciones por separado.</p>\n<p>Enumerando los cuadros de animaci\u00f3n nos quedar\u00eda as\u00ed:</p>\n<p><img alt=\"\" src=\"../imagenes/imagen/alien-simple-enumerado.png\" /></p>\n<p>y desde aqu\u00ed podemos extraer dos animaciones:</p>\n<ul>\n<li>La animaci\u00f3n que podemos armar con los cuadros <code>0, 1, 4</code>:</li>\n</ul>\n<p><img alt=\"\" src=\"../imagenes/imagen/anim2.gif\" /></p>\n<ul>\n<li>Y la animaci\u00f3n que se puede armar con los cuadros <code>3, 4, 5</code>:</li>\n</ul>\n<p><img alt=\"\" src=\"../imagenes/imagen/anim1.gif\" /></p>\n<p>Luego, para indicarle a <em>pilas</em> como interpretar las animaciones podemos\ncargar la animaci\u00f3n y especificar los cuadros:</p>\n<pre><code class=\"python\">animacion = pilas.imagenes.cargar_animacion('alien.png', 5, 1)\n\nanimacion.definir_animacion('baja_palanca', [0, 1, 4], 10)\nanimacion.definir_animacion('parado', [3, 3, 3, 3, 4, 5, 4], 10)\n</code></pre>\n\n<p>Al llamar al m\u00e9todo <code>definir_animacion</code> tenemos que especificar\nen nombre de la animaci\u00f3n, los cuadros a mostrar y luego la velocidad (medido\nen cuadros por segundo.)</p>\n<p>El siguiente paso es crear al actor e indicarle que animaci\u00f3n mostrar en\ncada momento:</p>\n<pre><code class=\"python\">\nclass MiActor(pilasengine.actores.Actor):\n\n    def iniciar(self):\n\n        # Las animaciones que cargamos antes:\n        animacion = pilas.imagenes.cargar_animacion('alien.png', 5, 1)\n\n        animacion.definir_animacion('baja_palanca', [0, 1, 4], 10)\n        animacion.definir_animacion('parado', [3, 3, 3, 3, 4, 5, 4], 10)\n\n        # Vinculamos la animaci\u00f3n al actor\n        self.imagen = animacion\n\n        # Le indicamos que muestre la animaci\u00f3n 'parado'\n        self.imagen.cargar_animacion('parado')\n\n    def actualizar(self):\n        self.imagen.avanzar()\n\n\npilas.actores.vincular(MiActor)\nmi_actor = pilas.actores.MiActor()\n</code></pre>\n\n<p>Es decir, con esta nueva clase, podremos representar\na nuestro actor y seleccionar cualquiera de las dos\nanimaciones que declaramos usando el m\u00e9todo <code>cargar_animacion</code>, que en este caso usamos para cargar\nla animaci\u00f3n <code>parado</code>.</p>\n", 
    "url": "/imagen/", 
    "language": "en", 
    "title": "Imagen"
}