hugoruscitti/pilas

View on GitHub
data/manual/mkdocs/search_index.json

Summary

Maintainability
Test Coverage
{
    "docs": [
        {
            "location": "/", 
            "text": "\u00a1 Bienvenido !\n\n\n\n\npilas-engine\n es una herramienta que te permite\ncrear tus propios videojuegos y aprender a programar. Est\u00e1 dise\u00f1ada por\ndesarrolladores de habla hispana y cuenta con el respaldo de docentes\ny profesionales especialistas en desarrollo de Software.\n\n\nEl objetivo de este documento es presentar las caracter\u00edsticas del motor, y dar un recorrido general por todos los componentes que se pueden utilizar.", 
            "title": "Principal"
        }, 
        {
            "location": "/#bienvenido", 
            "text": "pilas-engine  es una herramienta que te permite\ncrear tus propios videojuegos y aprender a programar. Est\u00e1 dise\u00f1ada por\ndesarrolladores de habla hispana y cuenta con el respaldo de docentes\ny profesionales especialistas en desarrollo de Software.  El objetivo de este documento es presentar las caracter\u00edsticas del motor, y dar un recorrido general por todos los componentes que se pueden utilizar.", 
            "title": "\u00a1 Bienvenido !"
        }, 
        {
            "location": "/que_juegos/", 
            "text": "\u00bfQu\u00e9 tipos de juegos se pueden realizar?\n\n\nMediante pilas-engine se pueden hacer juegos en dos\ndimensiones, utilizando colisiones, gr\u00e1ficos, efectos\nde part\u00edculas y animaci\u00f3n.\n\n\nPor ejemplo, un juego sencillo de pilas podr\u00eda verse as\u00ed:\n\n\n\n\nIncluso podemos usar las dos dimensiones para simular\nuna vista a\u00e9rea.\n\n\n\n\ny editar los niveles usando bloques para simular plataformas.\n\n\n\n\nPor \u00faltimo un ejemplo m\u00e1s complejo de videojuego podr\u00eda\nincluir un suelo en perspectiva, para simular profundidad, como\nen el juego \nshaolin's blind fury\n:", 
            "title": "Tipos de juegos"
        }, 
        {
            "location": "/que_juegos/#que-tipos-de-juegos-se-pueden-realizar", 
            "text": "Mediante pilas-engine se pueden hacer juegos en dos\ndimensiones, utilizando colisiones, gr\u00e1ficos, efectos\nde part\u00edculas y animaci\u00f3n.  Por ejemplo, un juego sencillo de pilas podr\u00eda verse as\u00ed:   Incluso podemos usar las dos dimensiones para simular\nuna vista a\u00e9rea.   y editar los niveles usando bloques para simular plataformas.   Por \u00faltimo un ejemplo m\u00e1s complejo de videojuego podr\u00eda\nincluir un suelo en perspectiva, para simular profundidad, como\nen el juego  shaolin's blind fury :", 
            "title": "\u00bfQu\u00e9 tipos de juegos se pueden realizar?"
        }, 
        {
            "location": "/instalacion/", 
            "text": "Instalaci\u00f3n\n\n\nExisten 2 formas de instalar la biblioteca, as\u00ed que veremos cada una por separado.\n\n\nOpci\u00f3n 1 - Instalaci\u00f3n f\u00e1cil, para cada sistema operativo\n\n\nLa forma mas sencilla de instalar pilas es descargando alguna de las versiones empaquetadas desde nuestro sitio web:\n\n\n\n\nhttp://www.pilas-engine.com.ar\n\n\n\n\nOpci\u00f3n 2 - Avanzada, desde repositorios\n\n\nOtra opci\u00f3n es descargar pilas e instalarlo directamente desde nuestro respositio git.\n\n\nHay mas informaci\u00f3n sobre esta forma de instalaci\u00f3n en nuestra secci\u00f3n \nGu\u00eda para desarrolladores\n.", 
            "title": "Instalaci\u00f3n"
        }, 
        {
            "location": "/instalacion/#instalacion", 
            "text": "Existen 2 formas de instalar la biblioteca, as\u00ed que veremos cada una por separado.", 
            "title": "Instalaci\u00f3n"
        }, 
        {
            "location": "/instalacion/#opcion-1-instalacion-facil-para-cada-sistema-operativo", 
            "text": "La forma mas sencilla de instalar pilas es descargando alguna de las versiones empaquetadas desde nuestro sitio web:   http://www.pilas-engine.com.ar", 
            "title": "Opci\u00f3n 1 - Instalaci\u00f3n f\u00e1cil, para cada sistema operativo"
        }, 
        {
            "location": "/instalacion/#opcion-2-avanzada-desde-repositorios", 
            "text": "Otra opci\u00f3n es descargar pilas e instalarlo directamente desde nuestro respositio git.  Hay mas informaci\u00f3n sobre esta forma de instalaci\u00f3n en nuestra secci\u00f3n  Gu\u00eda para desarrolladores .", 
            "title": "Opci\u00f3n 2 - Avanzada, desde repositorios"
        }, 
        {
            "location": "/about/", 
            "text": "Acerca de pilas-engine\n\n\n\u00bfQue es pilas-engine?\n\n\nPilas es una herramienta para construir videojuegos de manera sencilla y divertida.\n\n\nIdeamos esta herramienta para que los j\u00f3venes puedan descubrir y\naprender a programar computadoras. Creemos que aprender a programar es\nespectacular, porque les permite tener el control de las computadora, inventar\ny desarrollar cualquier tipo de software.\n\n\nEl equipo\n\n\nEn el desarrollo de pilas participamos varias personas, somos una comunidad\nabierta y colaborativa de programadores, docentes y estudiantes de distintas\npartes del mundo:\n\n\nEquipo principal:\n\n\n\n\n\n  \n\n    \n\n    \n\n    Hugo Ruscitti\n  \n\n\n  \n\n    \n\n    \n\n    Walter Velazquez\n  \n\n\n  \n\n    \n\n    \n\n    Quique Porta\n  \n\n\n  \n\n    \n\n    \n\n    Fernando Salamero\n  \n\n\n\n  \n\n    \n\n    \n\n    Irving Rodr\u00edguez\n  \n\n\n\n\n\n\n\n\nColaboradores:\n\n\n\n\n\n  \n\n    \n\n    \n\n    Marcos Vanetta\n  \n\n\n  \n\n    \n\n    \n\n    Luciano Baraglia\n  \n\n\n  \n\n    \n\n    \n\n    hernantz\n  \n\n\n  \n\n    \n\n    \n\n    Pablo Mouzo\n  \n\n\n  \n\n    \n\n    \n\n    Diego Accorinti\n  \n\n\n\n\n\n\n\n\n  \n\n    \n\n    \n\n    JuanBC\n\n  \n\n\n\n  \n\n    \n\n    \n\n    binary-sequence\n\n  \n\n\n  \n\n    \n\n    \n\n    Jos\u00e9 Luis Di Biase\n\n  \n\n\n  \n\n    \n\n    \n\n    Felipe Gonz\u00e1lez\n\n  \n\n\n  \n\n    \n\n    \n\n    Ivan Pedrazas\n\n  \n\n\n\n\n\n\n\n  \n\n    \n\n    \n\n    Jairo Trad\n  \n\n\n  \n\n    \n\n    \n\n    Mat\u00edas Iturburu\n  \n\n\n  \n\n    \n\n    \n\n    Diego Riquelme\n  \n\n\n\n\n\n\n\n\n\u00bfC\u00f3mo participar?\n\n\nSi queres participar en el equipo, visit\u00e1 nuestro \nforo\n y nuestro proyecto en \ngithub\n para obtener m\u00e1s informaci\u00f3n.\n\n\n\u00bfPor qu\u00e9 pilas?\n\n\nPilas est\u00e1 focalizado en ofrecer ayuda a los desarrolladores de juegos casuales y novatos que quieran hacer sus primeros videojuegos, ofreciendo una colecci\u00f3n importante de actores, escenas predise\u00f1adas y rutinas para facilitar las tareas m\u00e1s comunes del desarrollo.\n\n\nPensamos que pilas es una gran oportunidad de acercar el desarrollo de videojuegos a todas las personas, principalmente j\u00f3venes con inter\u00e9s en aprender a programar computadoras y darle vida a sus ideas.\n\n\nPilas est\u00e1 profundamente inspirada en las ideas de Seymour Papert, logo\ny bibliotecas de videjuegos modernas como cocos2d, pygame, rabbyt y squeak.\n\n\nCaracter\u00edsticas\n\n\nEstas son algunas de las caracter\u00edsticas t\u00e9cnicas que podemos resumir de pilas.\n\n\n\n\nEs multiplataforma (Funciona sobre GNU/Linux y Windows)\n\n\nCuenta con objetos predise\u00f1ados para agilizar el desarrollo.\n\n\nTiene documentaci\u00f3n completamente en espa\u00f1ol.\n\n\nSe utiliza desde python, lo que permite usarla desde sesiones interactivas.\n\n\nIncluye interacci\u00f3n con el motor de f\u00edsica pybox2d.\n\n\nEs software libre.\n\n\nCuenta con varios ejemplos y tutoriales para ir paso a paso.\n\n\n\n\nA lo largo del documento se dar\u00e1 un repaso mas completo de cada una de estas caracter\u00edsticas y mas.\n\n\n\u00bfCuando comenz\u00f3?\n\n\nEl proyecto comenz\u00f3 el 1 de Agosto del 2010, a cargo de Hugo Ruscitti, puedes\nver el primer \ncommit\n\ndel proyecto y c\u00f3mo \navanz\u00f3 en el tiempo\n usando el historial de cambios que tenemos\nen github.\n\n\nSitio web\n\n\nPara mas informaci\u00f3n sobre el motor puedes visitar el sitio web:\n\n\n\n\nhttp://www.pilas-engine.com.ar", 
            "title": "Acerca de ..."
        }, 
        {
            "location": "/about/#acerca-de-pilas-engine", 
            "text": "", 
            "title": "Acerca de pilas-engine"
        }, 
        {
            "location": "/about/#que-es-pilas-engine", 
            "text": "Pilas es una herramienta para construir videojuegos de manera sencilla y divertida.  Ideamos esta herramienta para que los j\u00f3venes puedan descubrir y\naprender a programar computadoras. Creemos que aprender a programar es\nespectacular, porque les permite tener el control de las computadora, inventar\ny desarrollar cualquier tipo de software.", 
            "title": "\u00bfQue es pilas-engine?"
        }, 
        {
            "location": "/about/#el-equipo", 
            "text": "En el desarrollo de pilas participamos varias personas, somos una comunidad\nabierta y colaborativa de programadores, docentes y estudiantes de distintas\npartes del mundo:", 
            "title": "El equipo"
        }, 
        {
            "location": "/about/#equipo-principal", 
            "text": "Hugo Ruscitti\n   \n\n   \n     \n     \n    Walter Velazquez\n   \n\n   \n     \n     \n    Quique Porta\n   \n\n   \n     \n     \n    Fernando Salamero\n   \n\n\n   \n     \n     \n    Irving Rodr\u00edguez", 
            "title": "Equipo principal:"
        }, 
        {
            "location": "/about/#colaboradores", 
            "text": "Marcos Vanetta\n   \n\n   \n     \n     \n    Luciano Baraglia\n   \n\n   \n     \n     \n    hernantz\n   \n\n   \n     \n     \n    Pablo Mouzo\n   \n\n   \n     \n     \n    Diego Accorinti\n     \n\n   \n     \n     \n    JuanBC\n\n   \n\n\n   \n     \n     \n    binary-sequence\n\n   \n\n   \n     \n     \n    Jos\u00e9 Luis Di Biase\n\n   \n\n   \n     \n     \n    Felipe Gonz\u00e1lez\n\n   \n\n   \n     \n     \n    Ivan Pedrazas\n\n     \n   \n     \n     \n    Jairo Trad\n   \n\n   \n     \n     \n    Mat\u00edas Iturburu\n   \n\n   \n     \n     \n    Diego Riquelme", 
            "title": "Colaboradores:"
        }, 
        {
            "location": "/about/#como-participar", 
            "text": "Si queres participar en el equipo, visit\u00e1 nuestro  foro  y nuestro proyecto en  github  para obtener m\u00e1s informaci\u00f3n.", 
            "title": "\u00bfC\u00f3mo participar?"
        }, 
        {
            "location": "/about/#por-que-pilas", 
            "text": "Pilas est\u00e1 focalizado en ofrecer ayuda a los desarrolladores de juegos casuales y novatos que quieran hacer sus primeros videojuegos, ofreciendo una colecci\u00f3n importante de actores, escenas predise\u00f1adas y rutinas para facilitar las tareas m\u00e1s comunes del desarrollo.  Pensamos que pilas es una gran oportunidad de acercar el desarrollo de videojuegos a todas las personas, principalmente j\u00f3venes con inter\u00e9s en aprender a programar computadoras y darle vida a sus ideas.  Pilas est\u00e1 profundamente inspirada en las ideas de Seymour Papert, logo\ny bibliotecas de videjuegos modernas como cocos2d, pygame, rabbyt y squeak.", 
            "title": "\u00bfPor qu\u00e9 pilas?"
        }, 
        {
            "location": "/about/#caracteristicas", 
            "text": "Estas son algunas de las caracter\u00edsticas t\u00e9cnicas que podemos resumir de pilas.   Es multiplataforma (Funciona sobre GNU/Linux y Windows)  Cuenta con objetos predise\u00f1ados para agilizar el desarrollo.  Tiene documentaci\u00f3n completamente en espa\u00f1ol.  Se utiliza desde python, lo que permite usarla desde sesiones interactivas.  Incluye interacci\u00f3n con el motor de f\u00edsica pybox2d.  Es software libre.  Cuenta con varios ejemplos y tutoriales para ir paso a paso.   A lo largo del documento se dar\u00e1 un repaso mas completo de cada una de estas caracter\u00edsticas y mas.", 
            "title": "Caracter\u00edsticas"
        }, 
        {
            "location": "/about/#cuando-comenzo", 
            "text": "El proyecto comenz\u00f3 el 1 de Agosto del 2010, a cargo de Hugo Ruscitti, puedes\nver el primer  commit \ndel proyecto y c\u00f3mo  avanz\u00f3 en el tiempo  usando el historial de cambios que tenemos\nen github.", 
            "title": "\u00bfCuando comenz\u00f3?"
        }, 
        {
            "location": "/about/#sitio-web", 
            "text": "Para mas informaci\u00f3n sobre el motor puedes visitar el sitio web:   http://www.pilas-engine.com.ar", 
            "title": "Sitio web"
        }, 
        {
            "location": "/empezando/", 
            "text": "Empezando, los primeros pasos con pilas\n\n\nSi ya tienes instalada la biblioteca podemos comenzar a realizar nuestros primeros pasos con la biblioteca.\n\n\npilas incluye un int\u00e9rprete interactivo que te permite escribir c\u00f3digo de python y autocompletar el nombre de las funciones. Aunque si quieres, puedes usar el int\u00e9rprete est\u00e1ndar de python, abriendo un terminal de texto y ejecutando el comando python.\n\n\nIniciando pilas\n\n\nPara ejecutar el asistente de pilas, abre un terminal y ejecuta el comando \npilasengine\n.\n\n\nEn tu pantalla tiene que aparecer una ventana como esta.\n\n\n\n\nInt\u00e9rprete de pilas\n\n\nHaz click en Abrir int\u00e9rprete y aparecer\u00e1 esta ventana.\n\n\n\n\nLa ventana se divide en dos partes. La parte de abajo muestra el editor. Todo lo que escribas en el editor se ejecutar\u00e1 autom\u00e1ticamente. El resultado se muestra en la parte de arriba.\n\n\nIniciando la biblioteca\n\n\nLa parte de arriba es la que utilizaremos para interactuar con el motor. Y mas adelante ser\u00e1 la \u00fanica pantalla que ver\u00e1n los usuarios de nuestros juegos.\n\n\nPuedes ver que el int\u00e9rprete viene con algunas l\u00edneas de ejemplo.\n\n\nimport pilasengine\n\npilas = pilasengine.iniciar()\nmono = pilas.actores.Mono()\n\n\n\n\nLa l\u00ednea \nimport pilasengine\n le dice a Python que use la librer\u00eda pilas. La\nfunci\u00f3n \npilas = pilasengine.iniciar()\n prepara la ventana (entre otras cosas) para empezar\na usar pilas. Luego la l\u00ednea \nmono = pilas.actores.Mono()\n, construye al personaje\ncon cara de mono que aparecer\u00e1 en la pantalla y tambi\u00e9n le dar\u00e1 un nombre.\n\n\nLa funci\u00f3n \npilasengine.iniciar()\n tiene mas par\u00e1metros, pero los veremos mas\nadelante. Por ahora, continuaremos con lo b\u00e1sico.\n\n\nCreando personajes\n\n\nUn concepto importante en pilas es del de \nactores\n. Un actor en pilas es un\nobjeto que aparece en pantalla, tiene una posici\u00f3n determinada y se puede manipular.\n\n\nPor ejemplo, una nave, un enemigo, una medalla... etc.\n\n\nPara agilizar el desarrollo de juegos se incluyen varios actores dentro del\nmotor, uno de ellos es \nMono\n, un simp\u00e1tico chimpanc\u00e9.\n\n\nNota:\n\n\n\n\nPuedes ver todos los en la escena actual ejecutando\n\npilas.actores.listar_actores()\n o abriendo el panel lateral de actores.\n\n\n\n\nTenemos al actor \nmono\n. Para indicarle acciones solo tenemos que utilizar su nombre y sentencias simples.\n\n\nPor ejemplo, para que el personaje cambie su expresi\u00f3n, podemos usar sentencias c\u00f3mo:\n\n\nmono.sonreir()\n\n\n\n\no:\n\n\nmono.gritar()\n\n\n\n\nEn cualquiera de los dos casos, el personaje cambiar\u00e1 su aspecto y emitir\u00e1 un sonido.\n\n\n\n\nIncluso podr\u00edamos decirle al personaje que tiene que hablar algo, por ejemplo:\n\n\nmono.decir(\nHey, bienvenido a pilas!!!\n)\n\n\n\n\ny el personaje mostrar\u00e1 exactamente lo que le indicamos que tiene que decir,\nc\u00f3mo si fuera un personaje de comic:\n\n\n\n\nA partir de ahora, comenzaremos a escribir algunos ejemplos. Ten en cuenta que no es necesario que escribas todo el c\u00f3digo de los ejemplos, el int\u00e9rprete de pilas te permite autocompletar sentencias mientras escribes.\n\n\nCosas en com\u00fan para los actores\n\n\nInternamente, Mono es un actor, as\u00ed que encontraremos mucha funcionalidad en \u00e9l que la tendr\u00e1n el resto de los actores.\n\n\nVeamos algunas de estas caracter\u00edsticas:\n\n\nPosici\u00f3n\n\n\nPodemos cambiar la posici\u00f3n de un actor mediante las propiedades \nx\n e \ny\n:\n\n\nmono.x = 100\nmono.y = 100\n\n\n\n\nTen en cuenta que\nx\n e \ny\n son las coordenadas de posici\u00f3n en el escenario. Por lo tanto el punto (0, 0) es el centro de la ventana. Y x aumenta hacia la derecha e y hacia arriba.\n\n\n\n\nEste espacio de referencia se puede observar en detalle si pulsas la tecla F12, ah\u00ed observar\u00e1s que el movimiento del mouse est\u00e1 asociado a una coordenada y cada actor tambi\u00e9n.\n\n\nNota\n:\n\n\n\n\nPara que tenga efecto, debes tener seleccionada la ventana de resultado (parte de arriba). Haz click sobre ella antes de pulsar F12.\n\n\n\n\nEscala\n\n\nTodo actor tiene un atributo para indicar su tama\u00f1o en pantalla, el atributo escala (que originalmente vale 1):\n\n\nmono.escala = 2\n\n\n\n\nRotaci\u00f3n\n\n\nTambi\u00e9n contamos con un atributo que indica la rotaci\u00f3n en grados que debe tener el actor en pantalla. El atributo rotacion:\n\n\nmono.rotacion = 40\n\n\n\n\n\n\no bien:\n\n\nmono.rotacion = 80\n\n\n\n\n\n\n\nLa rotaci\u00f3n siempre se indica en grados, e indica el grado de inclinaci\u00f3n hacia la izquierda.\n\n\nAnimaciones\n\n\nCualquiera de todas las propiedes que vimos anteriormente se pueden usar para hacer animaciones, por ejemplo, con el siguiente c\u00f3digo podr\u00edamos indicarle al actor que d\u00e9 una vuelta completa:\n\n\nmono.rotacion = [360]\n\n\n\n\n\u00bfpor qu\u00e9?, porque los caracteres [ y ] representan una lista de valores, y cuando pilas ve esta lista asignada a un atributo de un \nactor\n, intenta hacer una animaci\u00f3n.\n\n\nVeamos otro ejemplo, si queremos que un personaje como el mono se mueva horizontalmente con una animaci\u00f3n podemos escribir esto:\n\n\nmono.x = [-200, 200]\n\n\n\n\nEstas animaciones las veremos mas adelante, pero de todas formas es interesante observar que son listas comunes y corrientes.\n\n\nPython permite multiplicar listas, as\u00ed que podr\u00edamos multiplicarlas para repetir la animaci\u00f3n.\n\n\n# S\u00f3lo en python.\nmono.x = [-200, 200] * 5 # ir de un lado a otro 5 veces.\n\n\n\n\no incluso podr\u00edamos alterarles la velocidad, digamos que el ir y regresar se tiene que hacer muy lento, en unos 10 segundos:\n\n\nmono.x = [-200, 200], 10\n\n\n\n\nPidiendo ayuda\n\n\nRecuerda que cada componente de pilas est\u00e1 documentado y codificado como un m\u00f3dulo o clase del lenguaje de programaci\u00f3n python. Por lo tanto, puedes ejecutar una sentencia c\u00f3mo:\n\n\nhelp(mono)\n\n\n\n\ny aparecer\u00e1n en pantalla todos los instructivos de la funcionalidad del actor.\n\n\nIncluso puedes usar la funci\u00f3n \npilas.ver\n para conocer el c\u00f3digo fuente de\ncualquier cosa de pilas. Por ejemplo podemos el c\u00f3digo completo del mono\nejecutando la sentencia:\n\n\npilas.ver(mono)\n\n\n\n\nY claro, ten en cuenta que si escribes \nmono.\n el int\u00e9rprete comenzar\u00e1 a autocompletar todos los m\u00e9todos y propiedades.\n\n\nEliminando a un actor\n\n\nPara eliminar un actor de la escena tienes que llamar al m\u00e9todo eliminar:\n\n\nmono.eliminar()\n\n\n\n\nConclusi\u00f3n\n\n\nHemos visto los pasos principales para gestionar actores. Ten en cuenta que el m\u00f3dulo \npilas.actores\n es donde se guardar\u00e1n todos los actores.\n\n\nUn buen ejercicio es ponerse a investigar el m\u00f3dulo actores. Hay muchos actores, estos son algunos ejemplos de c\u00f3digo para probar:\n\n\nb = pilas.actores.Bomba()\nb.explotar()\n\np = pilas.actores.Pingu()    # se mueve con el teclado.\n\n\n\n\n\n\nEs todo por ahora, segu\u00ed leyendo o comenz\u00e1 a explorar por tu cuenta. A divertirse!", 
            "title": "Empezando y los primeros pasos con pilas"
        }, 
        {
            "location": "/empezando/#empezando-los-primeros-pasos-con-pilas", 
            "text": "Si ya tienes instalada la biblioteca podemos comenzar a realizar nuestros primeros pasos con la biblioteca.  pilas incluye un int\u00e9rprete interactivo que te permite escribir c\u00f3digo de python y autocompletar el nombre de las funciones. Aunque si quieres, puedes usar el int\u00e9rprete est\u00e1ndar de python, abriendo un terminal de texto y ejecutando el comando python.", 
            "title": "Empezando, los primeros pasos con pilas"
        }, 
        {
            "location": "/empezando/#iniciando-pilas", 
            "text": "Para ejecutar el asistente de pilas, abre un terminal y ejecuta el comando  pilasengine .  En tu pantalla tiene que aparecer una ventana como esta.", 
            "title": "Iniciando pilas"
        }, 
        {
            "location": "/empezando/#interprete-de-pilas", 
            "text": "Haz click en Abrir int\u00e9rprete y aparecer\u00e1 esta ventana.   La ventana se divide en dos partes. La parte de abajo muestra el editor. Todo lo que escribas en el editor se ejecutar\u00e1 autom\u00e1ticamente. El resultado se muestra en la parte de arriba.", 
            "title": "Int\u00e9rprete de pilas"
        }, 
        {
            "location": "/empezando/#iniciando-la-biblioteca", 
            "text": "La parte de arriba es la que utilizaremos para interactuar con el motor. Y mas adelante ser\u00e1 la \u00fanica pantalla que ver\u00e1n los usuarios de nuestros juegos.  Puedes ver que el int\u00e9rprete viene con algunas l\u00edneas de ejemplo.  import pilasengine\n\npilas = pilasengine.iniciar()\nmono = pilas.actores.Mono()  La l\u00ednea  import pilasengine  le dice a Python que use la librer\u00eda pilas. La\nfunci\u00f3n  pilas = pilasengine.iniciar()  prepara la ventana (entre otras cosas) para empezar\na usar pilas. Luego la l\u00ednea  mono = pilas.actores.Mono() , construye al personaje\ncon cara de mono que aparecer\u00e1 en la pantalla y tambi\u00e9n le dar\u00e1 un nombre.  La funci\u00f3n  pilasengine.iniciar()  tiene mas par\u00e1metros, pero los veremos mas\nadelante. Por ahora, continuaremos con lo b\u00e1sico.", 
            "title": "Iniciando la biblioteca"
        }, 
        {
            "location": "/empezando/#creando-personajes", 
            "text": "Un concepto importante en pilas es del de  actores . Un actor en pilas es un\nobjeto que aparece en pantalla, tiene una posici\u00f3n determinada y se puede manipular.  Por ejemplo, una nave, un enemigo, una medalla... etc.  Para agilizar el desarrollo de juegos se incluyen varios actores dentro del\nmotor, uno de ellos es  Mono , un simp\u00e1tico chimpanc\u00e9.  Nota:   Puedes ver todos los en la escena actual ejecutando pilas.actores.listar_actores()  o abriendo el panel lateral de actores.   Tenemos al actor  mono . Para indicarle acciones solo tenemos que utilizar su nombre y sentencias simples.  Por ejemplo, para que el personaje cambie su expresi\u00f3n, podemos usar sentencias c\u00f3mo:  mono.sonreir()  o:  mono.gritar()  En cualquiera de los dos casos, el personaje cambiar\u00e1 su aspecto y emitir\u00e1 un sonido.   Incluso podr\u00edamos decirle al personaje que tiene que hablar algo, por ejemplo:  mono.decir( Hey, bienvenido a pilas!!! )  y el personaje mostrar\u00e1 exactamente lo que le indicamos que tiene que decir,\nc\u00f3mo si fuera un personaje de comic:   A partir de ahora, comenzaremos a escribir algunos ejemplos. Ten en cuenta que no es necesario que escribas todo el c\u00f3digo de los ejemplos, el int\u00e9rprete de pilas te permite autocompletar sentencias mientras escribes.", 
            "title": "Creando personajes"
        }, 
        {
            "location": "/empezando/#cosas-en-comun-para-los-actores", 
            "text": "Internamente, Mono es un actor, as\u00ed que encontraremos mucha funcionalidad en \u00e9l que la tendr\u00e1n el resto de los actores.  Veamos algunas de estas caracter\u00edsticas:", 
            "title": "Cosas en com\u00fan para los actores"
        }, 
        {
            "location": "/empezando/#posicion", 
            "text": "Podemos cambiar la posici\u00f3n de un actor mediante las propiedades  x  e  y :  mono.x = 100\nmono.y = 100  Ten en cuenta que x  e  y  son las coordenadas de posici\u00f3n en el escenario. Por lo tanto el punto (0, 0) es el centro de la ventana. Y x aumenta hacia la derecha e y hacia arriba.   Este espacio de referencia se puede observar en detalle si pulsas la tecla F12, ah\u00ed observar\u00e1s que el movimiento del mouse est\u00e1 asociado a una coordenada y cada actor tambi\u00e9n.  Nota :   Para que tenga efecto, debes tener seleccionada la ventana de resultado (parte de arriba). Haz click sobre ella antes de pulsar F12.", 
            "title": "Posici\u00f3n"
        }, 
        {
            "location": "/empezando/#escala", 
            "text": "Todo actor tiene un atributo para indicar su tama\u00f1o en pantalla, el atributo escala (que originalmente vale 1):  mono.escala = 2", 
            "title": "Escala"
        }, 
        {
            "location": "/empezando/#rotacion", 
            "text": "Tambi\u00e9n contamos con un atributo que indica la rotaci\u00f3n en grados que debe tener el actor en pantalla. El atributo rotacion:  mono.rotacion = 40   o bien:  mono.rotacion = 80   La rotaci\u00f3n siempre se indica en grados, e indica el grado de inclinaci\u00f3n hacia la izquierda.", 
            "title": "Rotaci\u00f3n"
        }, 
        {
            "location": "/empezando/#animaciones", 
            "text": "Cualquiera de todas las propiedes que vimos anteriormente se pueden usar para hacer animaciones, por ejemplo, con el siguiente c\u00f3digo podr\u00edamos indicarle al actor que d\u00e9 una vuelta completa:  mono.rotacion = [360]  \u00bfpor qu\u00e9?, porque los caracteres [ y ] representan una lista de valores, y cuando pilas ve esta lista asignada a un atributo de un  actor , intenta hacer una animaci\u00f3n.  Veamos otro ejemplo, si queremos que un personaje como el mono se mueva horizontalmente con una animaci\u00f3n podemos escribir esto:  mono.x = [-200, 200]  Estas animaciones las veremos mas adelante, pero de todas formas es interesante observar que son listas comunes y corrientes.  Python permite multiplicar listas, as\u00ed que podr\u00edamos multiplicarlas para repetir la animaci\u00f3n.  # S\u00f3lo en python.\nmono.x = [-200, 200] * 5 # ir de un lado a otro 5 veces.  o incluso podr\u00edamos alterarles la velocidad, digamos que el ir y regresar se tiene que hacer muy lento, en unos 10 segundos:  mono.x = [-200, 200], 10", 
            "title": "Animaciones"
        }, 
        {
            "location": "/empezando/#pidiendo-ayuda", 
            "text": "Recuerda que cada componente de pilas est\u00e1 documentado y codificado como un m\u00f3dulo o clase del lenguaje de programaci\u00f3n python. Por lo tanto, puedes ejecutar una sentencia c\u00f3mo:  help(mono)  y aparecer\u00e1n en pantalla todos los instructivos de la funcionalidad del actor.  Incluso puedes usar la funci\u00f3n  pilas.ver  para conocer el c\u00f3digo fuente de\ncualquier cosa de pilas. Por ejemplo podemos el c\u00f3digo completo del mono\nejecutando la sentencia:  pilas.ver(mono)  Y claro, ten en cuenta que si escribes  mono.  el int\u00e9rprete comenzar\u00e1 a autocompletar todos los m\u00e9todos y propiedades.", 
            "title": "Pidiendo ayuda"
        }, 
        {
            "location": "/empezando/#eliminando-a-un-actor", 
            "text": "Para eliminar un actor de la escena tienes que llamar al m\u00e9todo eliminar:  mono.eliminar()", 
            "title": "Eliminando a un actor"
        }, 
        {
            "location": "/empezando/#conclusion", 
            "text": "Hemos visto los pasos principales para gestionar actores. Ten en cuenta que el m\u00f3dulo  pilas.actores  es donde se guardar\u00e1n todos los actores.  Un buen ejercicio es ponerse a investigar el m\u00f3dulo actores. Hay muchos actores, estos son algunos ejemplos de c\u00f3digo para probar:  b = pilas.actores.Bomba()\nb.explotar()\n\np = pilas.actores.Pingu()    # se mueve con el teclado.   Es todo por ahora, segu\u00ed leyendo o comenz\u00e1 a explorar por tu cuenta. A divertirse!", 
            "title": "Conclusi\u00f3n"
        }, 
        {
            "location": "/actores/", 
            "text": "Actores\n\n\nLos actores son una pieza clave de pilas, nos sirven para representar\na los personajes dentro de videojuego, con sus propios atributos, apariencia\ny comportamiento.\n\n\nPuedes utilizar los actores predise\u00f1ados de pilas, o crear tus propios\nactores. Existe una p\u00e1gina separada del manual que explica \ncomo crear tus\npropios actores\n, en lugar de utilizar los incluidos en pilas.\n\n\nGaler\u00eda de actores inclu\u00eddos\n\n\nHay varios actores pre-dise\u00f1ados incluidos en pilas, pod\u00e9s usarlos\nsiguiendo los ejemplos de esta p\u00e1gina o adaptarlos para crear los\ntuyos propios:\n\n\n\n\nActor\n\n\nAceituna\n\n\nAnimacion\n\n\nAnimado\n\n\nBala\n\n\nBanana\n\n\nActorEliminadoException\n\n\nActorEliminado\n\n\nBanana\n\n\nBomba\n\n\nBoton\n\n\nCaja\n\n\nCalvo\n\n\nControlador\n\n\nCooperativista\n\n\nDeslizadorHorizontal\n\n\nDialogo\n\n\nDinamita\n\n\nDisparoLaser\n\n\nEjes\n\n\nEmisor\n\n\nEnergia\n\n\nEstrella\n\n\nEstrellaNinja\n\n\nEstudiante\n\n\nExplosion\n\n\nExplosionDeHumo\n\n\nFantasma\n\n\nGlobo\n\n\nGrupo\n\n\nHumo\n\n\nManejadorPropiedad\n\n\nManzana\n\n\nMapa\n\n\nMapaTiled\n\n\nMartian\n\n\nMaton\n\n\nMensajeError\n\n\nMenu\n\n\nMenu\n\n\nMisil\n\n\nMoneda\n\n\nMono\n\n\nMunicion\n\n\nNave\n\n\nNaveKids\n\n\nNaveRoja\n\n\nOpcion\n\n\nOvni\n\n\nPacman\n\n\nPalo\n\n\nParticula\n\n\nPelota\n\n\nPiedra\n\n\nPingu\n\n\nPizarra\n\n\nPlaneta\n\n\nPuntaje\n\n\nShaolin\n\n\nSombra\n\n\nSonido\n\n\nTemporizador\n\n\nTexto\n\n\nTextoInferior\n\n\nTortuga\n\n\nZanahoria\n\n\n\n\nActor\n\n\nRepresenta un objeto visible en pantalla, algo que se ve y tiene\nla estructura inicial de actor\n\n\n\n\nUn objeto Actor se tiene que crear siempre indicando una imagen. Si no\nse especifica una imagen, se ver\u00e1n los signos de interrogaci\u00f3n de\ncolor rojo.\n\n\nUna forma de crear el actor con una imagen es:\n\n\nprotagonista = pilas.actores.Actor(imagen=\"planeta_azul.png\")\n\n\n\nincluso, es equivalente hacer lo siguiente:\n\n\nimagen = pilas.imagenes.cargar(\"planeta_azul.png\")\nprotagonista = pilas.actores.Actor(imagen=imagen)\n\n\n\nEl resultado ser\u00e1:\n\n\n\n\nLuego, una vez que ha sido ejecutada la sentencia aparecer\u00e1\nel nuevo actor para que puedas manipularlo. Por ejemplo\nalterando sus propiedades:\n\n\nprotagonista.x = 100\nprotagonista.escala = 2\nprotagonista.rotacion = 30\n\n\n\nEstas propiedades tambi\u00e9n se pueden manipular mediante\ninterpolaciones. Por ejemplo, para aumentar el tama\u00f1o del\npersonaje de 1 a 5 en 7 segundos:\n\n\nprotagonista.escala = 1\nprotagonista.escala = [5], 7\n\n\n\nSi quieres que el actor sea invisible, un truco es crearlo\ncon la imagen \ninvisible.png\n:\n\n\ninvisible = pilas.actores.Actor(imagen='invisible.png')\n\n\n\nAceituna\n\n\nEl actor aceituna es super simple\n\n\n\n\naceituna = pilas.actores.Aceituna()\n\n\n\nComportamientos:\n\n\n\n\naceituna.decir(mensaje)\n\n\n\n\nAnimacion\n\n\nRepresenta una animaci\u00f3n de una grilla de im\u00e1genes.\n\n\nEste actor toma una grilla de cuadros de animaci\u00f3n\ny los reproduce hasta que la animaci\u00f3n termina. Cuando\nla animaci\u00f3n termina se elimina a si mismo.\n\n\nEl constructor tiene algunos par\u00e1metros de utilidad:\n\n\n\n\nEl par\u00e1metro \nciclica\n permite hacer animaciones infinitas,\nque se repiten siempre, por defecto vale \nFalse\n que significa que\nla animaci\u00f3n terminar\u00e1 y no se repetir\u00e1.\n\n\nEl par\u00e1metro \nvelocidad\n tiene que ser un n\u00famero que indicar\u00e1 la\ncantidad de cuadros por segundo que se tienen que mostrar\nen la animaci\u00f3n.\n\n\n\n\nPor ejemplo, para mostrar una explosi\u00f3n infinita podr\u00edas escribir:\n\n\ngrilla = pilas.imagenes.cargar_grilla(\nexplosion.png\n, 7)\nanimacion = pilas.actores.Animacion(grilla, ciclica=True, velocidad=1)\n\n\n\n\n\n\nComportamientos:\n\n\n\n\nanimacion.definir_velocidad_de_animacion(velocidad_de_animacion)\n\n\nanimacion.obtener_velocidad_de_animacion()\n\n\n\n\nAnimado\n\n\nRepresenta un actor que tiene asociada una grilla con cuadros de animacion.\n\n\nUna de las variantes que introduce este actor es el\nm\u00e9todo 'definir_cuadro', que facilita la animaci\u00f3n de personajes.\n\n\nPor ejemplo, si tenemos una grilla con un ping\u00fcino, podr\u00edamos\nmostrarlo usando este c\u00f3digo:\n\n\ngrilla = pilas.imagenes.cargar_grilla(\npingu.png\n, 10)\nactor = Animado(grilla)\nactor.definir_cuadro(2)\nactor.definir_cuadro(5)\n\n\n\n\n\n\nComportamientos:\n\n\n\n\nactor.definir_cuadro(indice)\n\n\n\n\nBala\n\n\nRepresenta un disparo que avanza en linea recta, con un \u00e1ngulo\nde direcci\u00f3n y un sentido determinado.\n\n\nbala = pilas.actores.Bala(rotacion=0, velocidad_maxima=9, angulo_de_movimiento=90)\n\n\n\n\ny opcionalmente, si queremos que se llame a una funci\u00f3n en el momento\nde eliminaci\u00f3n del disparo podemos hacer as\u00ed:\n\n\nbala.cuando_se_elimina = funcion_a_invocar\n\n\n\n\nBanana\n\n\nMuestra una banana que se combina (tem\u00e1ticamente) con el actor Mono.\n\n\n\n\nEste actor se podr\u00eda usar c\u00f3mo alimento o bonus para otros\nactores.\n\n\nEste actor tiene solo dos cuadros de animaci\u00f3n que se pueden\nmostrar con los m\u00e9todos \nabrir\n y \ncerrar\n:\n\n\nbanana = pilas.actores.Banana()\nbanana.abrir()\nbanana.cerrar()\n\n\n\n\nComportamientos:\n\n\n\n\nbanana.abrir()\n\n\nbanana.cerrar()\n\n\n\n\nBomba\n\n\nRepresenta una bomba que puede explotar...\n\n\nLa bomba adquiere la habilidad explotar al momento de crearse, as\u00ed\nque puedes invocar a su m\u00e9todo \"explotar\" y la bomba har\u00e1 un\nexplosi\u00f3n en pantalla con sonido.\n\n\n\n\nbomba = pilas.actores.Bomba()\nbomba.explotar()\n\n\n\n\nComportamientos:\n\n\n\n\nbomba.explotar()\n\n\n\n\nBoton\n\n\nRepresenta un boton que reacciona al ser presionado\n\n\n\n\nComportamientos:\n\n\n\n\nboton.conectar_normal(funcion, argumentos...)\n\n\nboton.conectar_presionado(funcion, argumentos...)\n\n\nboton.activar()\n\n\nboton.desactivar()\n\n\nboton.desconectar_normal(function)\n\n\nboton.desconectar_presionado(function)\n\n\n\n\nCaja\n\n\nRepresenta una caja que posee fisica.\n\n\n\n\nCalvo\n\n\nRepresenta un personaje de juego tipo RPG.\n\n\n\n\nCooperativista\n\n\nRepresenta un Cooperativista que puede caminar y trabajar.\n\n\n\n\nComportamientos:\n\n\n\n\ncooperativista.cambiar_animacion(nombre)\n\n\n\n\nDeslizadorHorizontal\n\n\nComportamientos:\n\n\n\n\ndeslizador.conectar(function)\n\n\ndeslizador.desconectar(function)\n\n\n\n\nDi\u00e1logo\n\n\nRepresenta una secuencia de mensajes entre varios actores.\n\n\nmono = pilas.actores.Mono()\nmono2 = pilas.actores.Mono()\ndialogo = pilas.actores.Dialogo()\ndialogo.decir(mono, \nHola Mundo\n)\ndialogo.decir(mono2, \nEstoy diciendo algo\n)\ndialogo.comenzar()\n\n\n\n\n\n\nComportamientos:\n\n\n\n\ndialogo.decir(actor, mensaje)\n\n\ndialogo.comenzar()\n\n\n\n\nDinamita\n\n\nUna dinamita que puede explotar.\n\n\n\n\nComportamientos:\n\n\n\n\ndinamita.explotar()\n\n\n\n\nDisparoLaser\n\n\nMuestra un disparo que avanza por la pantalla.\n\n\nEste actor se podr\u00eda usar como arma para juegos de naves\ngeneralmente. Por ejemplo, el actor NaveRoja dispara usando\neste actor como munici\u00f3n.\n\n\n\n\nEmisor\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nEnergia\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nEstrella\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nEstrellaNinja\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nExplosion\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nExplosionDeHumo\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nFantasma\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nManejadorPropiedad\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nManzana\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nMartian\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nMaton\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nMenu\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nMisil\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nMoneda\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nMono\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nNave\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nNaveKids\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nNaveRoja\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nOvni\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nPacman\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nPelota\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nPiedra\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nPingu\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nPizarra\n\n\n...\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nPlaneta\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nPuntaje\n\n\n...\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nShaolin\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nSombra\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nTexto\n\n\n...\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nTortuga\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..\n\n\n\n\nZanahoria\n\n\n...\n\n\n\n\nComportamientos:\n\n\n\n\n..", 
            "title": "Actores"
        }, 
        {
            "location": "/actores/#actores", 
            "text": "Los actores son una pieza clave de pilas, nos sirven para representar\na los personajes dentro de videojuego, con sus propios atributos, apariencia\ny comportamiento.  Puedes utilizar los actores predise\u00f1ados de pilas, o crear tus propios\nactores. Existe una p\u00e1gina separada del manual que explica  como crear tus\npropios actores , en lugar de utilizar los incluidos en pilas.", 
            "title": "Actores"
        }, 
        {
            "location": "/actores/#galeria-de-actores-incluidos", 
            "text": "Hay varios actores pre-dise\u00f1ados incluidos en pilas, pod\u00e9s usarlos\nsiguiendo los ejemplos de esta p\u00e1gina o adaptarlos para crear los\ntuyos propios:   Actor  Aceituna  Animacion  Animado  Bala  Banana  ActorEliminadoException  ActorEliminado  Banana  Bomba  Boton  Caja  Calvo  Controlador  Cooperativista  DeslizadorHorizontal  Dialogo  Dinamita  DisparoLaser  Ejes  Emisor  Energia  Estrella  EstrellaNinja  Estudiante  Explosion  ExplosionDeHumo  Fantasma  Globo  Grupo  Humo  ManejadorPropiedad  Manzana  Mapa  MapaTiled  Martian  Maton  MensajeError  Menu  Menu  Misil  Moneda  Mono  Municion  Nave  NaveKids  NaveRoja  Opcion  Ovni  Pacman  Palo  Particula  Pelota  Piedra  Pingu  Pizarra  Planeta  Puntaje  Shaolin  Sombra  Sonido  Temporizador  Texto  TextoInferior  Tortuga  Zanahoria", 
            "title": "Galer\u00eda de actores inclu\u00eddos"
        }, 
        {
            "location": "/actores/#actor", 
            "text": "Representa un objeto visible en pantalla, algo que se ve y tiene\nla estructura inicial de actor   Un objeto Actor se tiene que crear siempre indicando una imagen. Si no\nse especifica una imagen, se ver\u00e1n los signos de interrogaci\u00f3n de\ncolor rojo.  Una forma de crear el actor con una imagen es:  protagonista = pilas.actores.Actor(imagen=\"planeta_azul.png\")  incluso, es equivalente hacer lo siguiente:  imagen = pilas.imagenes.cargar(\"planeta_azul.png\")\nprotagonista = pilas.actores.Actor(imagen=imagen)  El resultado ser\u00e1:   Luego, una vez que ha sido ejecutada la sentencia aparecer\u00e1\nel nuevo actor para que puedas manipularlo. Por ejemplo\nalterando sus propiedades:  protagonista.x = 100\nprotagonista.escala = 2\nprotagonista.rotacion = 30  Estas propiedades tambi\u00e9n se pueden manipular mediante\ninterpolaciones. Por ejemplo, para aumentar el tama\u00f1o del\npersonaje de 1 a 5 en 7 segundos:  protagonista.escala = 1\nprotagonista.escala = [5], 7  Si quieres que el actor sea invisible, un truco es crearlo\ncon la imagen  invisible.png :  invisible = pilas.actores.Actor(imagen='invisible.png')", 
            "title": "Actor"
        }, 
        {
            "location": "/actores/#aceituna", 
            "text": "El actor aceituna es super simple   aceituna = pilas.actores.Aceituna()  Comportamientos:   aceituna.decir(mensaje)", 
            "title": "Aceituna"
        }, 
        {
            "location": "/actores/#animacion", 
            "text": "Representa una animaci\u00f3n de una grilla de im\u00e1genes.  Este actor toma una grilla de cuadros de animaci\u00f3n\ny los reproduce hasta que la animaci\u00f3n termina. Cuando\nla animaci\u00f3n termina se elimina a si mismo.  El constructor tiene algunos par\u00e1metros de utilidad:   El par\u00e1metro  ciclica  permite hacer animaciones infinitas,\nque se repiten siempre, por defecto vale  False  que significa que\nla animaci\u00f3n terminar\u00e1 y no se repetir\u00e1.  El par\u00e1metro  velocidad  tiene que ser un n\u00famero que indicar\u00e1 la\ncantidad de cuadros por segundo que se tienen que mostrar\nen la animaci\u00f3n.   Por ejemplo, para mostrar una explosi\u00f3n infinita podr\u00edas escribir:  grilla = pilas.imagenes.cargar_grilla( explosion.png , 7)\nanimacion = pilas.actores.Animacion(grilla, ciclica=True, velocidad=1)   Comportamientos:   animacion.definir_velocidad_de_animacion(velocidad_de_animacion)  animacion.obtener_velocidad_de_animacion()", 
            "title": "Animacion"
        }, 
        {
            "location": "/actores/#animado", 
            "text": "Representa un actor que tiene asociada una grilla con cuadros de animacion.  Una de las variantes que introduce este actor es el\nm\u00e9todo 'definir_cuadro', que facilita la animaci\u00f3n de personajes.  Por ejemplo, si tenemos una grilla con un ping\u00fcino, podr\u00edamos\nmostrarlo usando este c\u00f3digo:  grilla = pilas.imagenes.cargar_grilla( pingu.png , 10)\nactor = Animado(grilla)\nactor.definir_cuadro(2)\nactor.definir_cuadro(5)   Comportamientos:   actor.definir_cuadro(indice)", 
            "title": "Animado"
        }, 
        {
            "location": "/actores/#bala", 
            "text": "Representa un disparo que avanza en linea recta, con un \u00e1ngulo\nde direcci\u00f3n y un sentido determinado.  bala = pilas.actores.Bala(rotacion=0, velocidad_maxima=9, angulo_de_movimiento=90)  y opcionalmente, si queremos que se llame a una funci\u00f3n en el momento\nde eliminaci\u00f3n del disparo podemos hacer as\u00ed:  bala.cuando_se_elimina = funcion_a_invocar", 
            "title": "Bala"
        }, 
        {
            "location": "/actores/#banana", 
            "text": "Muestra una banana que se combina (tem\u00e1ticamente) con el actor Mono.   Este actor se podr\u00eda usar c\u00f3mo alimento o bonus para otros\nactores.  Este actor tiene solo dos cuadros de animaci\u00f3n que se pueden\nmostrar con los m\u00e9todos  abrir  y  cerrar :  banana = pilas.actores.Banana()\nbanana.abrir()\nbanana.cerrar()  Comportamientos:   banana.abrir()  banana.cerrar()", 
            "title": "Banana"
        }, 
        {
            "location": "/actores/#bomba", 
            "text": "Representa una bomba que puede explotar...  La bomba adquiere la habilidad explotar al momento de crearse, as\u00ed\nque puedes invocar a su m\u00e9todo \"explotar\" y la bomba har\u00e1 un\nexplosi\u00f3n en pantalla con sonido.   bomba = pilas.actores.Bomba()\nbomba.explotar()  Comportamientos:   bomba.explotar()", 
            "title": "Bomba"
        }, 
        {
            "location": "/actores/#boton", 
            "text": "Representa un boton que reacciona al ser presionado   Comportamientos:   boton.conectar_normal(funcion, argumentos...)  boton.conectar_presionado(funcion, argumentos...)  boton.activar()  boton.desactivar()  boton.desconectar_normal(function)  boton.desconectar_presionado(function)", 
            "title": "Boton"
        }, 
        {
            "location": "/actores/#caja", 
            "text": "Representa una caja que posee fisica.", 
            "title": "Caja"
        }, 
        {
            "location": "/actores/#calvo", 
            "text": "Representa un personaje de juego tipo RPG.", 
            "title": "Calvo"
        }, 
        {
            "location": "/actores/#cooperativista", 
            "text": "Representa un Cooperativista que puede caminar y trabajar.   Comportamientos:   cooperativista.cambiar_animacion(nombre)", 
            "title": "Cooperativista"
        }, 
        {
            "location": "/actores/#deslizadorhorizontal", 
            "text": "Comportamientos:   deslizador.conectar(function)  deslizador.desconectar(function)", 
            "title": "DeslizadorHorizontal"
        }, 
        {
            "location": "/actores/#dialogo", 
            "text": "Representa una secuencia de mensajes entre varios actores.  mono = pilas.actores.Mono()\nmono2 = pilas.actores.Mono()\ndialogo = pilas.actores.Dialogo()\ndialogo.decir(mono,  Hola Mundo )\ndialogo.decir(mono2,  Estoy diciendo algo )\ndialogo.comenzar()   Comportamientos:   dialogo.decir(actor, mensaje)  dialogo.comenzar()", 
            "title": "Di\u00e1logo"
        }, 
        {
            "location": "/actores/#dinamita", 
            "text": "Una dinamita que puede explotar.   Comportamientos:   dinamita.explotar()", 
            "title": "Dinamita"
        }, 
        {
            "location": "/actores/#disparolaser", 
            "text": "Muestra un disparo que avanza por la pantalla.  Este actor se podr\u00eda usar como arma para juegos de naves\ngeneralmente. Por ejemplo, el actor NaveRoja dispara usando\neste actor como munici\u00f3n.", 
            "title": "DisparoLaser"
        }, 
        {
            "location": "/actores/#emisor", 
            "text": "...   Comportamientos:   ..", 
            "title": "Emisor"
        }, 
        {
            "location": "/actores/#energia", 
            "text": "...   Comportamientos:   ..", 
            "title": "Energia"
        }, 
        {
            "location": "/actores/#estrella", 
            "text": "...   Comportamientos:   ..", 
            "title": "Estrella"
        }, 
        {
            "location": "/actores/#estrellaninja", 
            "text": "...   Comportamientos:   ..", 
            "title": "EstrellaNinja"
        }, 
        {
            "location": "/actores/#explosion", 
            "text": "...   Comportamientos:   ..", 
            "title": "Explosion"
        }, 
        {
            "location": "/actores/#explosiondehumo", 
            "text": "...   Comportamientos:   ..", 
            "title": "ExplosionDeHumo"
        }, 
        {
            "location": "/actores/#fantasma", 
            "text": "...   Comportamientos:   ..", 
            "title": "Fantasma"
        }, 
        {
            "location": "/actores/#manejadorpropiedad", 
            "text": "...   Comportamientos:   ..", 
            "title": "ManejadorPropiedad"
        }, 
        {
            "location": "/actores/#manzana", 
            "text": "...   Comportamientos:   ..", 
            "title": "Manzana"
        }, 
        {
            "location": "/actores/#martian", 
            "text": "...   Comportamientos:   ..", 
            "title": "Martian"
        }, 
        {
            "location": "/actores/#maton", 
            "text": "...   Comportamientos:   ..", 
            "title": "Maton"
        }, 
        {
            "location": "/actores/#menu", 
            "text": "...   Comportamientos:   ..", 
            "title": "Menu"
        }, 
        {
            "location": "/actores/#misil", 
            "text": "...   Comportamientos:   ..", 
            "title": "Misil"
        }, 
        {
            "location": "/actores/#moneda", 
            "text": "...   Comportamientos:   ..", 
            "title": "Moneda"
        }, 
        {
            "location": "/actores/#mono", 
            "text": "...   Comportamientos:   ..", 
            "title": "Mono"
        }, 
        {
            "location": "/actores/#nave", 
            "text": "...   Comportamientos:   ..", 
            "title": "Nave"
        }, 
        {
            "location": "/actores/#navekids", 
            "text": "...   Comportamientos:   ..", 
            "title": "NaveKids"
        }, 
        {
            "location": "/actores/#naveroja", 
            "text": "...   Comportamientos:   ..", 
            "title": "NaveRoja"
        }, 
        {
            "location": "/actores/#ovni", 
            "text": "...   Comportamientos:   ..", 
            "title": "Ovni"
        }, 
        {
            "location": "/actores/#pacman", 
            "text": "...   Comportamientos:   ..", 
            "title": "Pacman"
        }, 
        {
            "location": "/actores/#pelota", 
            "text": "...   Comportamientos:   ..", 
            "title": "Pelota"
        }, 
        {
            "location": "/actores/#piedra", 
            "text": "...   Comportamientos:   ..", 
            "title": "Piedra"
        }, 
        {
            "location": "/actores/#pingu", 
            "text": "...   Comportamientos:   ..", 
            "title": "Pingu"
        }, 
        {
            "location": "/actores/#pizarra", 
            "text": "...  Comportamientos:   ..", 
            "title": "Pizarra"
        }, 
        {
            "location": "/actores/#planeta", 
            "text": "...   Comportamientos:   ..", 
            "title": "Planeta"
        }, 
        {
            "location": "/actores/#puntaje", 
            "text": "...  Comportamientos:   ..", 
            "title": "Puntaje"
        }, 
        {
            "location": "/actores/#shaolin", 
            "text": "...   Comportamientos:   ..", 
            "title": "Shaolin"
        }, 
        {
            "location": "/actores/#sombra", 
            "text": "...   Comportamientos:   ..", 
            "title": "Sombra"
        }, 
        {
            "location": "/actores/#texto", 
            "text": "...  Comportamientos:   ..", 
            "title": "Texto"
        }, 
        {
            "location": "/actores/#tortuga", 
            "text": "...   Comportamientos:   ..", 
            "title": "Tortuga"
        }, 
        {
            "location": "/actores/#zanahoria", 
            "text": "...   Comportamientos:   ..", 
            "title": "Zanahoria"
        }, 
        {
            "location": "/actores_personalizados/", 
            "text": "Actores personalizados\n\n\nCuando tu juego crece, comienza la necesidad de crear\ntus propios actores, darles personalidad y lograr\nfuncionalidad personalizada.\n\n\nEsta p\u00e1gina describe como crear tus propios actores\nusando im\u00e1genes y algunos comportamientos propios.\n\n\nCreando una clase\n\n\nEl primer paso para crear un actor personalizado\nes construir una clase para agrupar toda la funcionalidad\nesperada.\n\n\nComencemos con una imagen sencilla para el\nactor, este archivo se llama \nalien.png\n y est\u00e1\nen el directorio de nuestro c\u00f3digo:\n\n\n\n\nLuego, es momento de crear el c\u00f3digo de la clase para\nagrupar todo lo relacionado a este nuevo actor. Por\nejemplo con un c\u00f3digo as\u00ed:\n\n\nimport pilasengine\n\nclass Alien(pilasengine.actores.Actor):\n\n    def iniciar(self):\n        self.imagen = \nalien.png\n\n\n\n\n\nMostrando el actor en la pantalla\n\n\nMeditante la clase solamente hemos creado la \"definici\u00f3n\"\ndel actor, pero no lo hemos incorporado en el juego\na\u00fan.\n\n\nEl siguiente paso es incorporarlo al juego usando\nla sentencia:\n\n\nalien = Alien(pilas)\n\n\n\n\nAhora con el c\u00f3digo completo, tendr\u00edas que ver al personaje\nen el centro de la pantalla:\n\n\n\n\nComportamiento heredado\n\n\nAlgo interesante de los nuevos actores es que incorporan\npor herencia lo que saben hacer casi todos los actores\nde \npilas\n, ya que le hemos indicado que heredar\u00e1\nde clase actor con la linea \nclass Alien(pilasengine.actores.Actor):\n.\n\n\nPor ejemplo, podr\u00edas escribir algo como:\n\n\nalien.decir(u\"\u00a1oh, no, humanos!\")\n\n\n\n\n\nCreando m\u00e9todos nuevos\n\n\nTen en cuenta que ahora con nuestra nueva\nclase podemos crear funcionalidad nueva y espec\u00edfica\npara este actor alien.\n\n\nSolo tenemos que tener precauci\u00f3n de dirigirnos al\nactor como \nself\n dentro de los m\u00e9todos. Por ejemplo,\nsi quiero crear un m\u00e9todo para saludar puedo escribir:\n\n\nimport pilasengine\n\nclass Alien(pilasengine.actores.Actor):\n\n    def iniciar(self):\n        self.imagen = \nalien.png\n\n\n    def saludar(self):\n        self.decir(\nHola mundo!!!, soy el nuevo actor alien\n)\n\n    def dar_vuelta(self):\n        self.rotacion = [360]\n\n\n\n\nY ahora tenemos dos m\u00e9todos nuevos para invocar:\n\n\nalien.saludar()\n\n\n\n\n\ny otro un poquito mas complejo:\n\n\nalien.dar_vuelta()\n\n\n\n\n\nEl m\u00e9todo especial \"actualizar\"\n\n\nUna de las cosas mas importantes de la clase actor\nes que incorpora un m\u00e9todo especial llamado \nactualizar\n. Este m\u00e9todo se llamar\u00e1 autom\u00e1ticamente\n60 veces por segundo.\n\n\nPor ejemplo, imagina que buscamos hacer que el\nactor se mueva para los costados usando las flechas\ndel teclado, podemos usar est\u00e9 m\u00e9todo, simplemente\nas\u00ed:\n\n\nclass Alien(pilasengine.actores.Actor):\n\n    def iniciar(self):\n        self.imagen = \nalien.png\n\n\n    def saludar(self):\n        self.decir(\nHola mundo!!!, soy el nuevo actor alien\n)\n\n    def dar_vuelta(self):\n        self.rotacion = [360]\n\n    def actualizar(self):\n        if self.pilas.control.izquierda:\n            self.x -= 5\n            self.espejado = True\n        if self.pilas.control.derecha:\n            self.x += 5\n            self.espejado = False\n\n\n\n\nEs decir, como el m\u00e9todo actualizar se llama casi\ntodo el tiempo, podemos usarlo para consultar\nel estado del teclado y hacer algo.\n\n\nEn este caso, si se pulsa hacia la izquierda movemos\nel actor un poquito a la izquierda (con \nself.x -= 5\n)\ny adem\u00e1s invertimos el gr\u00e1fico del actor para que mire a la\nizquierda (con \nself.espejado = True\n). Y claro, hacemos lo\nopuesto para el lado\nderecho.\n\n\nAs\u00ed se ve mientras voy pulsando las teclas \nizquierda\n\ny \nderecha\n:\n\n\n\n\nTambi\u00e9n existe otro m\u00e9todo llamado \nluego_de_actualizar\n, que se llamar\u00e1\njusto despu\u00e9s de aplicarle f\u00edsica al actor. A grandes rasgos es muy similar\nal m\u00e9todo \nactualizar\n, ya que se llamar\u00e1 60 veces por segundo y recibe los\nmismos argumentos.\n\n\nLeyendo el c\u00f3digo de otros actores\n\n\nPilas viene con una funci\u00f3n especial llamada\n\npilas.ver\n, que te permite ver el c\u00f3digo de\ncualquier objeto y conocer su funcionamiento.\n\n\nEsta funci\u00f3n es super \u00fatil para conocer el c\u00f3digo\nde otras clases actor, e incluso aprender algunas\nideas interesantes.\n\n\nEstos son algunos ejemplos de invocaci\u00f3n, cada\nuna de estas sentencias te mostrar\u00e1 el c\u00f3digo\nde la clase completa:\n\n\npilas.ver(pilasengine.actores.Mono)\npilas.ver(pilasengine.actores.Aceituna)\npilas.ver(pilasengine.actores.Pacman)\npilas.ver(mono)\n\n\n\n\nParametros iniciales para los actores\n\n\nExisten varios casos en donde queremos crear actores\npero especificando algunos parametros iniciales, como\nla posici\u00f3n, energia o cualquier otro valor\nexterno a la clase.\n\n\nPara estos par\u00e1metros podemos crear argumentos personalizados\nen la clase nueva, por ejemplo, si quieres crear al actor\n\nAlien\n (que tomamos de ejemplo aqu\u00ed) pero quieres especificarle\nenergia, podr\u00edas escribir:\n\n\nalien = Alien(pilas, energia=100, nombre=\npepe alien\n, con_sombra=True)\n\n\n\n\nY atender esos argumentos desde el m\u00e9todo iniciar:\n\n\nclass Alien(pilasengine.actores.Actor):\n\n    def iniciar(self, energia, nombre, con_sombra):\n        self.imagen = \nalien.png\n\n\n        self.nombre = nombre\n        self.energia = energia\n\n        if con_sombra:\n            self.sombra = pilas.actores.Sombra()\n            self.sombra.escala = 0.6\n            self.sombra.y = -45\n        else:\n            self.sombra = None\n\n        self.decir(\nHola, me llamo \n + nombre)\n\n    def actualizar(self):\n        # Si el actor tiene sombra, hacemos que siga al\n        # actor.\n        if self.sombra:\n            self.sombra.x = self.x\n            self.sombra.y = self.y -45\n\n\n\n\nY el resultado deber\u00eda quedarte as\u00ed:\n\n\n\n\nDetectando errores y problemas al inicializar\n\n\nEs muy importante que al momento de crear actores a partir\nde clases especifiques los argumentos a utilizar. Hemos inclu\u00eddo\nalgo de c\u00f3digo especial en \npilas\n para detectar errores comunes, como\nargumentos faltantes o incorrectos.\n\n\nPero a\u00fan as\u00ed, ten en cuenta que todo argumento que le env\u00edes\na un actor al crearlo tiene que estar declarado como argumento\nen el m\u00e9todo \niniciar\n.\n\n\nPor ejemplo, un mensaje de error habitual que mostrar\u00e1 pilas si olvidamos\nel nombre de los argumentos podr\u00eda ser:\n\n\n\u00d7 TypeError: No se puede llamar al metodo 'iniciar' de la clase 'Alien'.\n\u00d7    Faltan 3 argumentos: energia, nombre, con_sombra.\n\u00d7    El m\u00e9todo 'iniciar' espera estos 3 argumentos: ['energia', 'nombre', 'con_sombra']\n\n\n\n\nEsto significa que hemos querido crear un actor a partir de una clase\nque espera 3 argumentos, pero solo hemos llamado incorrectamente.\n\n\nRegresando a nuestro ejemplo anterior, esto producir\u00eda un error:\n\n\nalien = Alien(pilas)\n\n\n\n\nmientras que este otro ejemplo s\u00ed funcionar\u00e1, porque el m\u00e9todo\n\niniciar\n de la clase \nAlien\n espera los argumentos \nenergia\n, \nnombre\n y\n\ncon_sombra\n:\n\n\nalien = Alien(pilas, energia=100, nombre=\npepe alien\n, con_sombra=True))", 
            "title": "Actores personalizados"
        }, 
        {
            "location": "/actores_personalizados/#actores-personalizados", 
            "text": "Cuando tu juego crece, comienza la necesidad de crear\ntus propios actores, darles personalidad y lograr\nfuncionalidad personalizada.  Esta p\u00e1gina describe como crear tus propios actores\nusando im\u00e1genes y algunos comportamientos propios.", 
            "title": "Actores personalizados"
        }, 
        {
            "location": "/actores_personalizados/#creando-una-clase", 
            "text": "El primer paso para crear un actor personalizado\nes construir una clase para agrupar toda la funcionalidad\nesperada.  Comencemos con una imagen sencilla para el\nactor, este archivo se llama  alien.png  y est\u00e1\nen el directorio de nuestro c\u00f3digo:   Luego, es momento de crear el c\u00f3digo de la clase para\nagrupar todo lo relacionado a este nuevo actor. Por\nejemplo con un c\u00f3digo as\u00ed:  import pilasengine\n\nclass Alien(pilasengine.actores.Actor):\n\n    def iniciar(self):\n        self.imagen =  alien.png", 
            "title": "Creando una clase"
        }, 
        {
            "location": "/actores_personalizados/#mostrando-el-actor-en-la-pantalla", 
            "text": "Meditante la clase solamente hemos creado la \"definici\u00f3n\"\ndel actor, pero no lo hemos incorporado en el juego\na\u00fan.  El siguiente paso es incorporarlo al juego usando\nla sentencia:  alien = Alien(pilas)  Ahora con el c\u00f3digo completo, tendr\u00edas que ver al personaje\nen el centro de la pantalla:", 
            "title": "Mostrando el actor en la pantalla"
        }, 
        {
            "location": "/actores_personalizados/#comportamiento-heredado", 
            "text": "Algo interesante de los nuevos actores es que incorporan\npor herencia lo que saben hacer casi todos los actores\nde  pilas , ya que le hemos indicado que heredar\u00e1\nde clase actor con la linea  class Alien(pilasengine.actores.Actor): .  Por ejemplo, podr\u00edas escribir algo como:  alien.decir(u\"\u00a1oh, no, humanos!\")", 
            "title": "Comportamiento heredado"
        }, 
        {
            "location": "/actores_personalizados/#creando-metodos-nuevos", 
            "text": "Ten en cuenta que ahora con nuestra nueva\nclase podemos crear funcionalidad nueva y espec\u00edfica\npara este actor alien.  Solo tenemos que tener precauci\u00f3n de dirigirnos al\nactor como  self  dentro de los m\u00e9todos. Por ejemplo,\nsi quiero crear un m\u00e9todo para saludar puedo escribir:  import pilasengine\n\nclass Alien(pilasengine.actores.Actor):\n\n    def iniciar(self):\n        self.imagen =  alien.png \n\n    def saludar(self):\n        self.decir( Hola mundo!!!, soy el nuevo actor alien )\n\n    def dar_vuelta(self):\n        self.rotacion = [360]  Y ahora tenemos dos m\u00e9todos nuevos para invocar:  alien.saludar()   y otro un poquito mas complejo:  alien.dar_vuelta()", 
            "title": "Creando m\u00e9todos nuevos"
        }, 
        {
            "location": "/actores_personalizados/#el-metodo-especial-actualizar", 
            "text": "Una de las cosas mas importantes de la clase actor\nes que incorpora un m\u00e9todo especial llamado  actualizar . Este m\u00e9todo se llamar\u00e1 autom\u00e1ticamente\n60 veces por segundo.  Por ejemplo, imagina que buscamos hacer que el\nactor se mueva para los costados usando las flechas\ndel teclado, podemos usar est\u00e9 m\u00e9todo, simplemente\nas\u00ed:  class Alien(pilasengine.actores.Actor):\n\n    def iniciar(self):\n        self.imagen =  alien.png \n\n    def saludar(self):\n        self.decir( Hola mundo!!!, soy el nuevo actor alien )\n\n    def dar_vuelta(self):\n        self.rotacion = [360]\n\n    def actualizar(self):\n        if self.pilas.control.izquierda:\n            self.x -= 5\n            self.espejado = True\n        if self.pilas.control.derecha:\n            self.x += 5\n            self.espejado = False  Es decir, como el m\u00e9todo actualizar se llama casi\ntodo el tiempo, podemos usarlo para consultar\nel estado del teclado y hacer algo.  En este caso, si se pulsa hacia la izquierda movemos\nel actor un poquito a la izquierda (con  self.x -= 5 )\ny adem\u00e1s invertimos el gr\u00e1fico del actor para que mire a la\nizquierda (con  self.espejado = True ). Y claro, hacemos lo\nopuesto para el lado\nderecho.  As\u00ed se ve mientras voy pulsando las teclas  izquierda \ny  derecha :   Tambi\u00e9n existe otro m\u00e9todo llamado  luego_de_actualizar , que se llamar\u00e1\njusto despu\u00e9s de aplicarle f\u00edsica al actor. A grandes rasgos es muy similar\nal m\u00e9todo  actualizar , ya que se llamar\u00e1 60 veces por segundo y recibe los\nmismos argumentos.", 
            "title": "El m\u00e9todo especial \"actualizar\""
        }, 
        {
            "location": "/actores_personalizados/#leyendo-el-codigo-de-otros-actores", 
            "text": "Pilas viene con una funci\u00f3n especial llamada pilas.ver , que te permite ver el c\u00f3digo de\ncualquier objeto y conocer su funcionamiento.  Esta funci\u00f3n es super \u00fatil para conocer el c\u00f3digo\nde otras clases actor, e incluso aprender algunas\nideas interesantes.  Estos son algunos ejemplos de invocaci\u00f3n, cada\nuna de estas sentencias te mostrar\u00e1 el c\u00f3digo\nde la clase completa:  pilas.ver(pilasengine.actores.Mono)\npilas.ver(pilasengine.actores.Aceituna)\npilas.ver(pilasengine.actores.Pacman)\npilas.ver(mono)", 
            "title": "Leyendo el c\u00f3digo de otros actores"
        }, 
        {
            "location": "/actores_personalizados/#parametros-iniciales-para-los-actores", 
            "text": "Existen varios casos en donde queremos crear actores\npero especificando algunos parametros iniciales, como\nla posici\u00f3n, energia o cualquier otro valor\nexterno a la clase.  Para estos par\u00e1metros podemos crear argumentos personalizados\nen la clase nueva, por ejemplo, si quieres crear al actor Alien  (que tomamos de ejemplo aqu\u00ed) pero quieres especificarle\nenergia, podr\u00edas escribir:  alien = Alien(pilas, energia=100, nombre= pepe alien , con_sombra=True)  Y atender esos argumentos desde el m\u00e9todo iniciar:  class Alien(pilasengine.actores.Actor):\n\n    def iniciar(self, energia, nombre, con_sombra):\n        self.imagen =  alien.png \n\n        self.nombre = nombre\n        self.energia = energia\n\n        if con_sombra:\n            self.sombra = pilas.actores.Sombra()\n            self.sombra.escala = 0.6\n            self.sombra.y = -45\n        else:\n            self.sombra = None\n\n        self.decir( Hola, me llamo   + nombre)\n\n    def actualizar(self):\n        # Si el actor tiene sombra, hacemos que siga al\n        # actor.\n        if self.sombra:\n            self.sombra.x = self.x\n            self.sombra.y = self.y -45  Y el resultado deber\u00eda quedarte as\u00ed:", 
            "title": "Parametros iniciales para los actores"
        }, 
        {
            "location": "/actores_personalizados/#detectando-errores-y-problemas-al-inicializar", 
            "text": "Es muy importante que al momento de crear actores a partir\nde clases especifiques los argumentos a utilizar. Hemos inclu\u00eddo\nalgo de c\u00f3digo especial en  pilas  para detectar errores comunes, como\nargumentos faltantes o incorrectos.  Pero a\u00fan as\u00ed, ten en cuenta que todo argumento que le env\u00edes\na un actor al crearlo tiene que estar declarado como argumento\nen el m\u00e9todo  iniciar .  Por ejemplo, un mensaje de error habitual que mostrar\u00e1 pilas si olvidamos\nel nombre de los argumentos podr\u00eda ser:  \u00d7 TypeError: No se puede llamar al metodo 'iniciar' de la clase 'Alien'.\n\u00d7    Faltan 3 argumentos: energia, nombre, con_sombra.\n\u00d7    El m\u00e9todo 'iniciar' espera estos 3 argumentos: ['energia', 'nombre', 'con_sombra']  Esto significa que hemos querido crear un actor a partir de una clase\nque espera 3 argumentos, pero solo hemos llamado incorrectamente.  Regresando a nuestro ejemplo anterior, esto producir\u00eda un error:  alien = Alien(pilas)  mientras que este otro ejemplo s\u00ed funcionar\u00e1, porque el m\u00e9todo iniciar  de la clase  Alien  espera los argumentos  energia ,  nombre  y con_sombra :  alien = Alien(pilas, energia=100, nombre= pepe alien , con_sombra=True))", 
            "title": "Detectando errores y problemas al inicializar"
        }, 
        {
            "location": "/grupos/", 
            "text": "Grupos\n\n\nAhora que podemos manejar a los actores de manera individual, vamos a ver como organizarlos en grupos.\n\n\nOrganizar a los actores en grupos es \u00fatil porque generalmente\nbuscamos clasificar a los actores por caracter\u00edsticas y\ntratarlos a todos por igual. Por ejemplo, en un juego de naves\npodr\u00edamos tener un grupo de naves, un grupo de estrellas y un\ngrupo de disparos.\n\n\nCreando grupos de actores\n\n\nPara crear varios actores de una misma clase\npodr\u00edamos ejecutar algo como lo que sigue:\n\n\nbombas = pilas.actores.Bomba() * 5\n\n\n\n\nes decir, creamos un actor y luego lo multiplicamos\npara construir un grupo con muchos actores de la misma\nespecie.\n\n\nAl crear un grupo de esta forma, todos los actores\nse colocar\u00e1n en posiciones aleatorias.\n\n\nEsto es lo que ver\u00edamos en la ventana de pilas:\n\n\n\n\nA partir de ahora, la referencia \nbombas\n nos servir\u00e1 para\ncontrolar a todas las bombas al mismo tiempo.\n\n\nEsta referencia (que llamamos \nbombas\n) es parecida a una lista de datos en \npython\n. Podr\u00edamos realizar operaciones t\u00edpicas como contar, recorrer o clasificar de la misma forma que se hace en el lenguaje \npython\n.\n\n\nPor ejemplo, para contar la cantidad de bombas que hemos creado y conocer sus coordenadas podemos ejecutar:\n\n\n print(\nhay\n, len(bombas), \nbombas\n)\nhay 5 bombas\n\n\n for una_bomba in bombas:\n...     print(una_bomba.x, una_bomba.y)\n\n\n\n\nAhora bien, algo que hace un poquito diferente a los\ngrupos de las listas de python, es que los grupos\nte permiten alterar a varios actores al mismo tiempo\ncon mas facilidad.\n\n\nPor ejemplo, imagina que quieres hacer que todas las\nbombas aparezcan en el centro de la ventana. Podr\u00edas\nhacer algo c\u00f3mo esto:\n\n\nbombas.x = 0\n\n\n\n\nY en la ventana obtendremos:\n\n\n\n\nIncluso, les podr\u00edamos ense\u00f1ar a las bombas a reaccionar\ncomo si fueran pelotas, es decir, que reboten e interact\u00faen\ncon la aceleraci\u00f3n gravitatoria:\n\n\nbombas.aprender(pilas.habilidades.RebotarComoPelota)\n\n\n\n\nAhora tendr\u00e1s algo mucho mas interesante, un mont\u00f3n de\nactores rebotando entre s\u00ed:\n\n\n\n\nUn consejo, la gravedad del escenario se puede modificar\nusando una sentencia como la que sigue:\n\n\npilas.fisica.gravedad_x = 200\npilas.fisica.gravedad_y = 0\n\n\n\n\nEn este caso \ngravedad_x\n con un valor de 200 va a empujar los objetos\nhacia la derecha de la pantalla, mientras que los objetos en el eje vertical\nvan a flotar.\n\n\nIntent\u00e1 ver esto en funcionamiento, \u00a1es divertido!\n\n\nCreando un grupo para distintos actores\n\n\nHay ocasiones, donde quieres tener un grupo\ndesde cero e ir agregando actores en \u00e9l.\n\n\nEsto se puede hacer f\u00e1cilmente, e incluso\nabre las puertas a que puedas mezclar actores\nde distintas especies.\n\n\nPara crear un grupo vac\u00edo tienes que crear\nun objeto de la clase Grupo:\n\n\nmi_grupo = pilas.actores.Grupo()\n\n\n\n\ny luego, para a\u00f1adir actores al grupo puedes usar el\nm\u00e9todo \nagregar\n e indicar la referencia del actor\nque quieres agregar:\n\n\nbomba = pilas.actores.Bomba()\npelota = pilas.actores.Pelota()\n\nmi_grupo.agregar(bomba)\nmi_grupo.agregar(pelota)\n\nmi_grupo.escala = [2]\n\n\n\n\n\n\nUn detalle a tener en cuenta, el m\u00e9todo \nagregar\n no solo te permite agregar actores, tambi\u00e9n podr\u00edas tomar un grupo y agregarle con algo como \ngrupo.agregar(otro_grupo)\n.", 
            "title": "Grupos"
        }, 
        {
            "location": "/grupos/#grupos", 
            "text": "Ahora que podemos manejar a los actores de manera individual, vamos a ver como organizarlos en grupos.  Organizar a los actores en grupos es \u00fatil porque generalmente\nbuscamos clasificar a los actores por caracter\u00edsticas y\ntratarlos a todos por igual. Por ejemplo, en un juego de naves\npodr\u00edamos tener un grupo de naves, un grupo de estrellas y un\ngrupo de disparos.", 
            "title": "Grupos"
        }, 
        {
            "location": "/grupos/#creando-grupos-de-actores", 
            "text": "Para crear varios actores de una misma clase\npodr\u00edamos ejecutar algo como lo que sigue:  bombas = pilas.actores.Bomba() * 5  es decir, creamos un actor y luego lo multiplicamos\npara construir un grupo con muchos actores de la misma\nespecie.  Al crear un grupo de esta forma, todos los actores\nse colocar\u00e1n en posiciones aleatorias.  Esto es lo que ver\u00edamos en la ventana de pilas:   A partir de ahora, la referencia  bombas  nos servir\u00e1 para\ncontrolar a todas las bombas al mismo tiempo.  Esta referencia (que llamamos  bombas ) es parecida a una lista de datos en  python . Podr\u00edamos realizar operaciones t\u00edpicas como contar, recorrer o clasificar de la misma forma que se hace en el lenguaje  python .  Por ejemplo, para contar la cantidad de bombas que hemos creado y conocer sus coordenadas podemos ejecutar:   print( hay , len(bombas),  bombas )\nhay 5 bombas  for una_bomba in bombas:\n...     print(una_bomba.x, una_bomba.y)  Ahora bien, algo que hace un poquito diferente a los\ngrupos de las listas de python, es que los grupos\nte permiten alterar a varios actores al mismo tiempo\ncon mas facilidad.  Por ejemplo, imagina que quieres hacer que todas las\nbombas aparezcan en el centro de la ventana. Podr\u00edas\nhacer algo c\u00f3mo esto:  bombas.x = 0  Y en la ventana obtendremos:   Incluso, les podr\u00edamos ense\u00f1ar a las bombas a reaccionar\ncomo si fueran pelotas, es decir, que reboten e interact\u00faen\ncon la aceleraci\u00f3n gravitatoria:  bombas.aprender(pilas.habilidades.RebotarComoPelota)  Ahora tendr\u00e1s algo mucho mas interesante, un mont\u00f3n de\nactores rebotando entre s\u00ed:   Un consejo, la gravedad del escenario se puede modificar\nusando una sentencia como la que sigue:  pilas.fisica.gravedad_x = 200\npilas.fisica.gravedad_y = 0  En este caso  gravedad_x  con un valor de 200 va a empujar los objetos\nhacia la derecha de la pantalla, mientras que los objetos en el eje vertical\nvan a flotar.  Intent\u00e1 ver esto en funcionamiento, \u00a1es divertido!", 
            "title": "Creando grupos de actores"
        }, 
        {
            "location": "/grupos/#creando-un-grupo-para-distintos-actores", 
            "text": "Hay ocasiones, donde quieres tener un grupo\ndesde cero e ir agregando actores en \u00e9l.  Esto se puede hacer f\u00e1cilmente, e incluso\nabre las puertas a que puedas mezclar actores\nde distintas especies.  Para crear un grupo vac\u00edo tienes que crear\nun objeto de la clase Grupo:  mi_grupo = pilas.actores.Grupo()  y luego, para a\u00f1adir actores al grupo puedes usar el\nm\u00e9todo  agregar  e indicar la referencia del actor\nque quieres agregar:  bomba = pilas.actores.Bomba()\npelota = pilas.actores.Pelota()\n\nmi_grupo.agregar(bomba)\nmi_grupo.agregar(pelota)\n\nmi_grupo.escala = [2]   Un detalle a tener en cuenta, el m\u00e9todo  agregar  no solo te permite agregar actores, tambi\u00e9n podr\u00edas tomar un grupo y agregarle con algo como  grupo.agregar(otro_grupo) .", 
            "title": "Creando un grupo para distintos actores"
        }, 
        {
            "location": "/colisiones/", 
            "text": "Colisiones F\u00edsicas\n\n\nEl sistema de colisiones te permite disparar acciones cuando dos o m\u00e1s actores\nentran en contacto. Esto nos permite hacer que los personajes puedan\nchocar con enemigos, capturar objetos y mucho m\u00e1s.\n\n\nDos tipos de colisiones\n\n\nEn pilas-engine tenemos dos tipos de colisiones: colisiones\nf\u00edsicas y colisiones programadas.\n\n\nLas \ncolisiones f\u00edsicas\n son aquellas que generan una reacci\u00f3n que se puede\nvisualizar como una respuesta f\u00edsica, por ejemplo si creamos 5 cajas y las\nhacemos rebotar entre s\u00ed, estas ser\u00edan colisiones f\u00edsicas:\n\n\n\n\ncajas = pilas.actores.Caja() * 5\n\n\n\n\nPodr\u00edamos decir que las colisiones f\u00edsicas son casi autom\u00e1ticas, las genera\nel mismo motor de f\u00edsica que trae pilas-engine sin mucho c\u00f3digo.\n\n\nEn cambio, las \ncolisiones programadas\n son aquellas que tienen una reacci\u00f3n\npor c\u00f3digo, y generalmente tienen que ver con la l\u00f3gica del juego (perder, ganar\npuntos, pasar de nivel etc..)\n\n\nPor ejemplo, una colisi\u00f3n programada sencilla se puede visualizar si creamos\nun personaje que se pueda mover con el mouse y se alimente comiendo bananas:\n\n\n\n\nmono = pilas.actores.Mono()\nmono.aprender(\nArrastrable\n)\nbananas = pilas.actores.Banana() * 10\n\ndef cuando_colisiona(mono, banana):\n    banana.eliminar()\n    mono.sonreir()\n\npilas.colisiones.agregar(mono, bananas, cuando_colisiona)\n\n\n\n\nModo depuraci\u00f3n f\u00edsica\n\n\nEl modo depuraci\u00f3n f\u00edsica nos permite observar las figuras f\u00edsicas de\ncada uno de los actores. Para activar este modo, pod\u00e9s pulsar la tecla \nF12\n\no simplemente hacer click sobre el \u00edcono \"mostrar figuras f\u00edsicas\":\n\n\n\n\nCon este modo habilitado, vas a poder observar la figura de colisi\u00f3n\nque lo representa:\n\n\n\n\nEn color blanco aparecen las figuras f\u00edsicas, que al rebotar con otras\nproducir\u00e1n una reacci\u00f3n de choque y rebote. Y de color verde van a aparecer\nlos sensores.\n\n\nLos sensores son figuras f\u00edscias pero que no generan una reacci\u00f3n\nal momento del choque.\n\n\nAcceder a las figuras de colisi\u00f3n\n\n\nEn muchos momentos vas a necesitar hacer ajustes sobre las figuras\nde colisi\u00f3n. Lo mas com\u00fan es cambiar el tama\u00f1o de las figuras (para ajustarlas\n  al tama\u00f1o del actor) o convertir las figuras a sensores.\n\n\nPara acceder a las figuras de colisi\u00f3n tienes que usar el atributo\n\nfigura_de_colisi\u00f3n\n del actor, o bien cambiar su tama\u00f1o directamente\ncambiando el atributo \nradio_de_colisi\u00f3n\n por ejemplo:\n\n\nmono = pilas.actores.Mono()\nmono.radio_de_colision = 30\nmono.radio_de_colision = 80\nmono.radio_de_colision = 10\n\n\n\n\nCada vez que asignes un valor al atributo \nradio_de_colision\n, pilas va a\ngenerar una circunferencia y la va a colocar como figura de colisi\u00f3n para el\nactor.\n\n\nCambiando las figuras de colisi\u00f3n\n\n\nEn la mayor\u00eda de los casos la figura circular es la que mejor se ajusta\nal area de un actor.\n\n\nSin embargo, hay algunos casos en donde necesitamos cambiar completamente\nla figura de colisi\u00f3n por otra.\n\n\nLa forma mas sencilla de cambiar una figura por otra, es crear la figura\nf\u00edsica primero y luego asignarla a la propiedad \nfigura_de_colision\n del\nactor:\n\n\n\n\nPara construir este ejemplo constru\u00edmos dos actores, al primero lo dejamos\ntal cual, pero al segundo le cambiamos la figura de colisi\u00f3n por un rect\u00e1ngulo:\n\n\nzanahoria_normal = pilas.actores.Zanahoria(x=-100)\n\nzanahoria = pilas.actores.Zanahoria(x=100)\nrectangulo = pilas.fisica.Rectangulo(0, 0, 40, 100, sensor=True, dinamica=False)\nzanahoria.figura_de_colision = rectangulo\n\n\n\n\nDetecci\u00f3n constante de colisiones\n\n\nPilas tambi\u00e9n incluye un forma constante de detectar colisiones, algo que\npuede ser mucho m\u00e1s sencillo de implementar en juegos de acci\u00f3n.\n\n\nCada figura f\u00edsica tiene una propiedad llamada \nfiguras_en_contacto\n con\nuna lista de todas las figuras con las que colisiona.\n\n\nPor ejemplo, tomemos de ejemplo un actor \"Pelota\". Si queremos consultar\nsi el actor Pelota est\u00e1 colisionando con alguna figura podemos ejecutar:\n\n\n pelota = pilas.actores.Pelota()\n\n print(pelota.figura_de_colision.figuras_en_contacto)\n\n\n\n\nSi el actor no colisiona con nada, se nos retornar\u00e1 una lista vac\u00eda:\n\n\n[]\n\n\n\n\nEn cambio, si el actor est\u00e1 en colisi\u00f3n con alguna figura, la lista\nque se retornar\u00e1 contendr\u00e1 al menos un elemento:\n\n\n[\nFigura Rectangulo en (0, -240)\n]\n\n\n\n\nEste tipo de colisiones constantes son super \u00fatiles cuando creamos\nactores personalizados (como se indica en el apartado\n\nActores personalizados\n), ya que desde el m\u00e9todo\nactualizar vamos a poder comprobar colisiones constantemente.\n\n\nPor ejemplo, para emitir un mensaje cada vez que se produce una colisi\u00f3n\npodr\u00edamos escribir un c\u00f3digo como el siguiente:\n\n\nindicador_de_colision = pilas.actores.Texto(\nHAY COLISION!\n, y=100)\nindicador_de_colision.transparencia = 100\n\nclass PelotaTransparente(pilasengine.actores.Pelota):\n\n    def iniciar(self):\n        pilasengine.actores.Pelota.iniciar(self)\n        self.aprender('arrastrable')\n\n    def actualizar(self):\n\n        if self.figura_de_colision.figuras_en_contacto:\n            self.transparencia = 0\n            indicador_de_colision.transparencia = 0\n        else:\n            self.transparencia = 50\n            indicador_de_colision.transparencia = 100\n\npilas.actores.vincular(PelotaTransparente)\npilas.actores.PelotaTransparente()\n\npilas.actores.Aceituna()\n\n\n\n\n\n\nEso s\u00ed, ten en cuenta que la lista de \nfiguras_en_contacto\n no es una\nreferencia a los actores, sino la lista de figuras. Si lo que quieres es\nobtener informaci\u00f3n de los actores tendr\u00edas que usar el atributo\n\nactor_que_representa_como_area_de_colision\n de la figura.\n\n\nPor ejemplo, podemos cambiar el c\u00f3digo que maneja la colisi\u00f3n para\nque indique si el actor que colisiona es aceituna o no:\n\n\n\n\nindicador_de_colision = pilas.actores.Texto(\nHAY COLISION!\n, y=100)\nindicador_de_colision.transparencia = 100\n\ndef es_aceituna(actor):\n    return 'aceituna' in actor.etiquetas.lista\n\nclass PelotaTransparente(pilasengine.actores.Pelota):\n\n    def iniciar(self):\n        pilasengine.actores.Pelota.iniciar(self)\n        self.aprender('arrastrable')\n\n    def actualizar(self):\n        figura = self.figura_de_colision.figuras_en_contacto\n\n        if figura:\n            indicador_de_colision.transparencia = 0\n            self.cambiar_texto(figura[0])\n        else:\n            indicador_de_colision.transparencia = 100\n\n    def cambiar_texto(self, figura):\n        actor = getattr(figura, \nactor_que_representa_como_area_de_colision\n, None)\n\n        if actor:\n            # Ha colisionado con una figura que tiene un actor enlazado.\n            if es_aceituna(actor):\n                indicador_de_colision.texto = \nColisiona con actor aceituna.\n\n            else:\n                indicador_de_colision.texto = \nColisiona con Actor, no es Aceituna!!!\n\n\n\npilas.actores.vincular(PelotaTransparente)\npilas.actores.PelotaTransparente()\n\npilas.actores.Aceituna()\npilas.actores.Zanahoria(x=150)\n\n\n\n\nColisiones con etiquetas\n\n\nTen en cuenta que existe un atajo para definir colisiones\nusando el concepto de etiquetas, que se ver\u00e1 en la siguiente\np\u00e1gina de este manual.", 
            "title": "Colisiones"
        }, 
        {
            "location": "/colisiones/#colisiones-fisicas", 
            "text": "El sistema de colisiones te permite disparar acciones cuando dos o m\u00e1s actores\nentran en contacto. Esto nos permite hacer que los personajes puedan\nchocar con enemigos, capturar objetos y mucho m\u00e1s.", 
            "title": "Colisiones F\u00edsicas"
        }, 
        {
            "location": "/colisiones/#dos-tipos-de-colisiones", 
            "text": "En pilas-engine tenemos dos tipos de colisiones: colisiones\nf\u00edsicas y colisiones programadas.  Las  colisiones f\u00edsicas  son aquellas que generan una reacci\u00f3n que se puede\nvisualizar como una respuesta f\u00edsica, por ejemplo si creamos 5 cajas y las\nhacemos rebotar entre s\u00ed, estas ser\u00edan colisiones f\u00edsicas:   cajas = pilas.actores.Caja() * 5  Podr\u00edamos decir que las colisiones f\u00edsicas son casi autom\u00e1ticas, las genera\nel mismo motor de f\u00edsica que trae pilas-engine sin mucho c\u00f3digo.  En cambio, las  colisiones programadas  son aquellas que tienen una reacci\u00f3n\npor c\u00f3digo, y generalmente tienen que ver con la l\u00f3gica del juego (perder, ganar\npuntos, pasar de nivel etc..)  Por ejemplo, una colisi\u00f3n programada sencilla se puede visualizar si creamos\nun personaje que se pueda mover con el mouse y se alimente comiendo bananas:   mono = pilas.actores.Mono()\nmono.aprender( Arrastrable )\nbananas = pilas.actores.Banana() * 10\n\ndef cuando_colisiona(mono, banana):\n    banana.eliminar()\n    mono.sonreir()\n\npilas.colisiones.agregar(mono, bananas, cuando_colisiona)", 
            "title": "Dos tipos de colisiones"
        }, 
        {
            "location": "/colisiones/#modo-depuracion-fisica", 
            "text": "El modo depuraci\u00f3n f\u00edsica nos permite observar las figuras f\u00edsicas de\ncada uno de los actores. Para activar este modo, pod\u00e9s pulsar la tecla  F12 \no simplemente hacer click sobre el \u00edcono \"mostrar figuras f\u00edsicas\":   Con este modo habilitado, vas a poder observar la figura de colisi\u00f3n\nque lo representa:   En color blanco aparecen las figuras f\u00edsicas, que al rebotar con otras\nproducir\u00e1n una reacci\u00f3n de choque y rebote. Y de color verde van a aparecer\nlos sensores.  Los sensores son figuras f\u00edscias pero que no generan una reacci\u00f3n\nal momento del choque.", 
            "title": "Modo depuraci\u00f3n f\u00edsica"
        }, 
        {
            "location": "/colisiones/#acceder-a-las-figuras-de-colision", 
            "text": "En muchos momentos vas a necesitar hacer ajustes sobre las figuras\nde colisi\u00f3n. Lo mas com\u00fan es cambiar el tama\u00f1o de las figuras (para ajustarlas\n  al tama\u00f1o del actor) o convertir las figuras a sensores.  Para acceder a las figuras de colisi\u00f3n tienes que usar el atributo figura_de_colisi\u00f3n  del actor, o bien cambiar su tama\u00f1o directamente\ncambiando el atributo  radio_de_colisi\u00f3n  por ejemplo:  mono = pilas.actores.Mono()\nmono.radio_de_colision = 30\nmono.radio_de_colision = 80\nmono.radio_de_colision = 10  Cada vez que asignes un valor al atributo  radio_de_colision , pilas va a\ngenerar una circunferencia y la va a colocar como figura de colisi\u00f3n para el\nactor.", 
            "title": "Acceder a las figuras de colisi\u00f3n"
        }, 
        {
            "location": "/colisiones/#cambiando-las-figuras-de-colision", 
            "text": "En la mayor\u00eda de los casos la figura circular es la que mejor se ajusta\nal area de un actor.  Sin embargo, hay algunos casos en donde necesitamos cambiar completamente\nla figura de colisi\u00f3n por otra.  La forma mas sencilla de cambiar una figura por otra, es crear la figura\nf\u00edsica primero y luego asignarla a la propiedad  figura_de_colision  del\nactor:   Para construir este ejemplo constru\u00edmos dos actores, al primero lo dejamos\ntal cual, pero al segundo le cambiamos la figura de colisi\u00f3n por un rect\u00e1ngulo:  zanahoria_normal = pilas.actores.Zanahoria(x=-100)\n\nzanahoria = pilas.actores.Zanahoria(x=100)\nrectangulo = pilas.fisica.Rectangulo(0, 0, 40, 100, sensor=True, dinamica=False)\nzanahoria.figura_de_colision = rectangulo", 
            "title": "Cambiando las figuras de colisi\u00f3n"
        }, 
        {
            "location": "/colisiones/#deteccion-constante-de-colisiones", 
            "text": "Pilas tambi\u00e9n incluye un forma constante de detectar colisiones, algo que\npuede ser mucho m\u00e1s sencillo de implementar en juegos de acci\u00f3n.  Cada figura f\u00edsica tiene una propiedad llamada  figuras_en_contacto  con\nuna lista de todas las figuras con las que colisiona.  Por ejemplo, tomemos de ejemplo un actor \"Pelota\". Si queremos consultar\nsi el actor Pelota est\u00e1 colisionando con alguna figura podemos ejecutar:   pelota = pilas.actores.Pelota()  print(pelota.figura_de_colision.figuras_en_contacto)  Si el actor no colisiona con nada, se nos retornar\u00e1 una lista vac\u00eda:  []  En cambio, si el actor est\u00e1 en colisi\u00f3n con alguna figura, la lista\nque se retornar\u00e1 contendr\u00e1 al menos un elemento:  [ Figura Rectangulo en (0, -240) ]  Este tipo de colisiones constantes son super \u00fatiles cuando creamos\nactores personalizados (como se indica en el apartado Actores personalizados ), ya que desde el m\u00e9todo\nactualizar vamos a poder comprobar colisiones constantemente.  Por ejemplo, para emitir un mensaje cada vez que se produce una colisi\u00f3n\npodr\u00edamos escribir un c\u00f3digo como el siguiente:  indicador_de_colision = pilas.actores.Texto( HAY COLISION! , y=100)\nindicador_de_colision.transparencia = 100\n\nclass PelotaTransparente(pilasengine.actores.Pelota):\n\n    def iniciar(self):\n        pilasengine.actores.Pelota.iniciar(self)\n        self.aprender('arrastrable')\n\n    def actualizar(self):\n\n        if self.figura_de_colision.figuras_en_contacto:\n            self.transparencia = 0\n            indicador_de_colision.transparencia = 0\n        else:\n            self.transparencia = 50\n            indicador_de_colision.transparencia = 100\n\npilas.actores.vincular(PelotaTransparente)\npilas.actores.PelotaTransparente()\n\npilas.actores.Aceituna()   Eso s\u00ed, ten en cuenta que la lista de  figuras_en_contacto  no es una\nreferencia a los actores, sino la lista de figuras. Si lo que quieres es\nobtener informaci\u00f3n de los actores tendr\u00edas que usar el atributo actor_que_representa_como_area_de_colision  de la figura.  Por ejemplo, podemos cambiar el c\u00f3digo que maneja la colisi\u00f3n para\nque indique si el actor que colisiona es aceituna o no:   indicador_de_colision = pilas.actores.Texto( HAY COLISION! , y=100)\nindicador_de_colision.transparencia = 100\n\ndef es_aceituna(actor):\n    return 'aceituna' in actor.etiquetas.lista\n\nclass PelotaTransparente(pilasengine.actores.Pelota):\n\n    def iniciar(self):\n        pilasengine.actores.Pelota.iniciar(self)\n        self.aprender('arrastrable')\n\n    def actualizar(self):\n        figura = self.figura_de_colision.figuras_en_contacto\n\n        if figura:\n            indicador_de_colision.transparencia = 0\n            self.cambiar_texto(figura[0])\n        else:\n            indicador_de_colision.transparencia = 100\n\n    def cambiar_texto(self, figura):\n        actor = getattr(figura,  actor_que_representa_como_area_de_colision , None)\n\n        if actor:\n            # Ha colisionado con una figura que tiene un actor enlazado.\n            if es_aceituna(actor):\n                indicador_de_colision.texto =  Colisiona con actor aceituna. \n            else:\n                indicador_de_colision.texto =  Colisiona con Actor, no es Aceituna!!! \n\n\npilas.actores.vincular(PelotaTransparente)\npilas.actores.PelotaTransparente()\n\npilas.actores.Aceituna()\npilas.actores.Zanahoria(x=150)", 
            "title": "Detecci\u00f3n constante de colisiones"
        }, 
        {
            "location": "/colisiones/#colisiones-con-etiquetas", 
            "text": "Ten en cuenta que existe un atajo para definir colisiones\nusando el concepto de etiquetas, que se ver\u00e1 en la siguiente\np\u00e1gina de este manual.", 
            "title": "Colisiones con etiquetas"
        }, 
        {
            "location": "/etiquetas/", 
            "text": "Etiquetas\n\n\nLas etiquetas nos permite clasificar actores y describir\na los actores de manera simple.\n\n\nCada etiqueta es solamente una palabra, por ejemplo \"enemigo\",\n\"protagonista\", \"munici\u00f3n\" etc... y podemos vincularla\ncon cualquier actor o grupo, para se\u00f1alar el rol de ese actor\no grupo.\n\n\nLas etiquetas se utilizan principalmente para simplificar\nla creaci\u00f3n de colisiones, que vimos en el\ncap\u00edtulo anterior.\n\n\nConociendo las Etiquetas\n\n\nCada actor que existe en pilas tiene un atributo \netiquetas\n,\nque inicialmente tiene el nombre de la clase que origin\u00f3\nal actor, por ejemplo:\n\n\n mono = pilas.actores.Mono()\n\n mono.etiquetas\n['mono']\n\n\n aceituna = pilas.actores.Aceituna()\n\n aceituna.etiquetas\n['aceituna']\n\n\n\ny estas etiquetas, a su vez, se pueden a\u00f1adir usando el m\u00e9todo \nagregar\n:\n\n\n mono.etiquetas.agregar('protagonista')\n['mono', 'protagonista']\n\n\n\no incluso consultar si un actor tiene o no una determinada etiqueta:\n\n\n mono.tiene_etiqueta(\"enemigo\")\nFalse\n\n mono.tiene_etiqueta(\"mono\")\nTrue\n\n\n\nUsando grupos\n\n\nLos grupos tambi\u00e9n nos brindan la posibilidad de consultar o definir las\netiquetas de varios actores al mismo tiempo:\n\n\nnaves = pilas.actores.Nave() * 10\nnaves.etiquetas.agregar('enemigo')\n\nitems = pilas.actores.Banana() * 5\nitems.etiquetas.agregar('comestible')\n\notro_grupo = pilas.actores.Manzana() * 2\notro_grupo.etiquetas.agregar('comestible')\n\n\n\n\nA\u00f1adiendo colisiones mediante etiquetas\n\n\nAhora que podemos a\u00f1adir etiquetas a los actores, podemos describir las\ncolisiones de forma mas sencilla.\n\n\nPor ejemplo, si creamos un escenario con monedas y un mono que se pueda\nmover con el teclado as\u00ed:\n\n\nmono = pilas.actores.Mono()\nmonedas = pilas.actores.Moneda() * 20\n\nmono.aprender('arrastrable')\n\n\n\n\npodemos definir una acci\u00f3n de colisi\u00f3n simplemente indicando la funci\u00f3n\nde respuesta y las etiquetas que intervienen:\n\n\ndef capturar(mono, cosa):\n    cosa.eliminar()\n    mono.sonreir()\n\npilas.colisiones.agregar('mono', 'moneda', capturar)\n\n\n\n\nAhora, incluso aunque se elimine las monedas de la pantalla, si creamos\nnuevas van a seguir siendo \"comestibles\" por el mono:\n\n\nmas_monedas = pilas.actores.Moneda() * 10\n\n\n\n\nIncluso cualquier otra cosa que tenga estas etiquetas va a ser\ncapturado por el mono:\n\n\ncajas = pilas.actores.Caja() * 10\ncajas.etiquetas.agregar('moneda')\n\n\n\n\nClaro, lo ideal en este caso es definir las colisiones usando etiquetas\ngen\u00e9ricas como: 'comestible', 'enemigo', 'vida' etc...\n\n\nLas etiquetas tambi\u00e9n sirven con figuras\n\n\nTen en cuenta que las figuras f\u00edsicas tambi\u00e9n pueden contener etiquetas de la misma forma de los actores.\n\n\nEsto es super \u00fatil cuando queremos crear colisiones mas gen\u00e9ricas o invisibles.\n\n\nPor ejemplo, podr\u00edamos tener una circunferencia que al momento de tocar\ncualquier rect\u00e1ngulo desaparezca:\n\n\ncirculo = pilas.fisica.Circulo()\ncirculo.etiquetas.agregar(\ncolisionable\n)\n\ndef destruir(circulo_que_colisiona, un_rectangulo):\n    circulo_que_colisiona.eliminar()\n\npilas.colisiones.agregar(\ncolisionable\n, \nrectangulo\n, destruir)\n\n\n\n\nEso s\u00ed, tenemos que tener en cuenta que la funci\u00f3n \"destruir\" va a recibir las dos figuras en contacto y no dos actores como vimos en los otros\nejemplos de colisi\u00f3n entre actores.", 
            "title": "Etiquetas"
        }, 
        {
            "location": "/etiquetas/#etiquetas", 
            "text": "Las etiquetas nos permite clasificar actores y describir\na los actores de manera simple.  Cada etiqueta es solamente una palabra, por ejemplo \"enemigo\",\n\"protagonista\", \"munici\u00f3n\" etc... y podemos vincularla\ncon cualquier actor o grupo, para se\u00f1alar el rol de ese actor\no grupo.  Las etiquetas se utilizan principalmente para simplificar\nla creaci\u00f3n de colisiones, que vimos en el\ncap\u00edtulo anterior.", 
            "title": "Etiquetas"
        }, 
        {
            "location": "/etiquetas/#conociendo-las-etiquetas", 
            "text": "Cada actor que existe en pilas tiene un atributo  etiquetas ,\nque inicialmente tiene el nombre de la clase que origin\u00f3\nal actor, por ejemplo:   mono = pilas.actores.Mono()  mono.etiquetas\n['mono']  aceituna = pilas.actores.Aceituna()  aceituna.etiquetas\n['aceituna']  y estas etiquetas, a su vez, se pueden a\u00f1adir usando el m\u00e9todo  agregar :   mono.etiquetas.agregar('protagonista')\n['mono', 'protagonista']  o incluso consultar si un actor tiene o no una determinada etiqueta:   mono.tiene_etiqueta(\"enemigo\")\nFalse  mono.tiene_etiqueta(\"mono\")\nTrue", 
            "title": "Conociendo las Etiquetas"
        }, 
        {
            "location": "/etiquetas/#usando-grupos", 
            "text": "Los grupos tambi\u00e9n nos brindan la posibilidad de consultar o definir las\netiquetas de varios actores al mismo tiempo:  naves = pilas.actores.Nave() * 10\nnaves.etiquetas.agregar('enemigo')\n\nitems = pilas.actores.Banana() * 5\nitems.etiquetas.agregar('comestible')\n\notro_grupo = pilas.actores.Manzana() * 2\notro_grupo.etiquetas.agregar('comestible')", 
            "title": "Usando grupos"
        }, 
        {
            "location": "/etiquetas/#anadiendo-colisiones-mediante-etiquetas", 
            "text": "Ahora que podemos a\u00f1adir etiquetas a los actores, podemos describir las\ncolisiones de forma mas sencilla.  Por ejemplo, si creamos un escenario con monedas y un mono que se pueda\nmover con el teclado as\u00ed:  mono = pilas.actores.Mono()\nmonedas = pilas.actores.Moneda() * 20\n\nmono.aprender('arrastrable')  podemos definir una acci\u00f3n de colisi\u00f3n simplemente indicando la funci\u00f3n\nde respuesta y las etiquetas que intervienen:  def capturar(mono, cosa):\n    cosa.eliminar()\n    mono.sonreir()\n\npilas.colisiones.agregar('mono', 'moneda', capturar)  Ahora, incluso aunque se elimine las monedas de la pantalla, si creamos\nnuevas van a seguir siendo \"comestibles\" por el mono:  mas_monedas = pilas.actores.Moneda() * 10  Incluso cualquier otra cosa que tenga estas etiquetas va a ser\ncapturado por el mono:  cajas = pilas.actores.Caja() * 10\ncajas.etiquetas.agregar('moneda')  Claro, lo ideal en este caso es definir las colisiones usando etiquetas\ngen\u00e9ricas como: 'comestible', 'enemigo', 'vida' etc...", 
            "title": "A\u00f1adiendo colisiones mediante etiquetas"
        }, 
        {
            "location": "/etiquetas/#las-etiquetas-tambien-sirven-con-figuras", 
            "text": "Ten en cuenta que las figuras f\u00edsicas tambi\u00e9n pueden contener etiquetas de la misma forma de los actores.  Esto es super \u00fatil cuando queremos crear colisiones mas gen\u00e9ricas o invisibles.  Por ejemplo, podr\u00edamos tener una circunferencia que al momento de tocar\ncualquier rect\u00e1ngulo desaparezca:  circulo = pilas.fisica.Circulo()\ncirculo.etiquetas.agregar( colisionable )\n\ndef destruir(circulo_que_colisiona, un_rectangulo):\n    circulo_que_colisiona.eliminar()\n\npilas.colisiones.agregar( colisionable ,  rectangulo , destruir)  Eso s\u00ed, tenemos que tener en cuenta que la funci\u00f3n \"destruir\" va a recibir las dos figuras en contacto y no dos actores como vimos en los otros\nejemplos de colisi\u00f3n entre actores.", 
            "title": "Las etiquetas tambi\u00e9n sirven con figuras"
        }, 
        {
            "location": "/fisica/", 
            "text": "F\u00edsica\n\n\nPilas incluye integraci\u00f3n con un sistema de f\u00edsica\npara realizar simulaciones y dotar a tus juegos\nde mas realismo y diversi\u00f3n.\n\n\nEl motor: Box2D\n\n\nEl motor de f\u00edsica seleccionado para pilas se llama Box2D, el mismo\nmotor de f\u00edsica utilizado en el juego Angry Birds.\n\n\nAs\u00ed, Box2D y PyBox2D son las bibliotecas protagonistas\nde casi toda la funcionalidad que vas a ver en este m\u00f3dulo.\n\n\nEl m\u00f3dulo \npilas.fisica\n es solamente un facilitador para utilizar Box2D, y\nque puedas comenzar a jugar con f\u00edsicas r\u00e1pidamente.\n\n\nAs\u00ed que aprovecho este espacio para dar las gracias a \nErin Catto\n, y\nsu grupo de desarrollo por haber creado \nBox2D\n.\n\n\nUnos ejemplos\n\n\nEl motor de f\u00edsica se puede mostrar en funcionamiento\nusando un ejemplo, escribe el siguiente c\u00f3digo:\n\n\npelotas = pilas.actores.Pelota() * 10\n\n\n\n\nesto crear\u00e1 un grupo de circunferencias que rebotar\u00e1n\nhasta la parte inferior de la pantalla.\n\n\nDe manera similar puedes crear un mont\u00f3n de cajas y\nhacerlas rebotar:\n\n\ncajas = pilas.actores.Caja() * 10\n\n\n\n\nComo puedes ver, el resultado es un grupo ca\u00f3tico\nde actores chocando entre s\u00ed. Mas adelante veremos\ncomo personalizar y \"controlar\" un poco el escenario.\n\n\n\n\nLos actores que tienen f\u00edsica son un poco particulares, pero\na\u00fan as\u00ed se los puede tratar como a otros actores. Por\nejemplo, si quieres poder arrastrar y soltar figuras con\nel mouse, puedes ense\u00f1arles una habilidad:\n\n\npelotas.aprender(\narrastrable\n)\ncajas.aprender(\narrastrable\n)\n\n\n\n\nModo depuraci\u00f3n de f\u00edsica\n\n\nCuando haces juegos con f\u00edsica o movimientos realistas es\nmuy importante tener en cuenta un concepto importate:\n\n\nSi bien uno observa pelotas y cajas, en realidad, internamente\nson solo cuadrados y circunferencias.\n\n\nLo que ocurre en pantalla son dos cosas, por una lado vemos im\u00e1genes\ncon aspecto de caja o pelota, y por el otro se nos oculta una\nsimulaci\u00f3n entre pol\u00edgonos mucho mas primitiva y simple.\n\n\nObserva esta escena:\n\n\n\n\nCada uno de esos actores est\u00e1 asociado a una figura\ngeom\u00e9trica, la f\u00edsica en realidad se da en un nivel muy\nprimitivo de figuras. El aspecto de las cosas es\nsolo eso, un aspecto. Lo que \"manda\" en el comportamiento\nf\u00edsico son las figuras geom\u00e9tricas (cuerpos).\n\n\nIntenta lo siguiente, pulsa la tecla \nF11\n o puls\u00e1 el\nbot\u00f3n \"mostrar figuras f\u00edsicas\" que aparece abajo a la\nderecha:\n\n\n\n\nLas lineas blancas indican pol\u00edgonos que el\nmotor de f\u00edsica puede controlar, las cajas tienen forma\nrectangular, los actores Pelota tienen figuras circulares, y\nel suelo y las paredes tambi\u00e9n est\u00e1n en el sistema de f\u00edsica.\n\n\nSi por alg\u00fan motivo quieres que los objetos no est\u00e9n contenidos\nen la pantalla, y sean un poco mas libres, podr\u00edas eliminar\nlas paredes:\n\n\npilas.fisica.eliminar_paredes()\n\n\n\n\no incluso podr\u00edas eliminar el suelo:\n\n\npilas.fisica.eliminar_suelo()\n\n\n\n\nPero recuerda que los objetos que no se ven en la pantalla\nde todas maneras estar\u00e1n ah\u00ed. Una buena idea es eliminarlos\nni bien los dejas de usar.\n\n\nF\u00edsica personalizada\n\n\nLos actores \nPelota\n y \nCaja\n est\u00e1n bien para simulaciones\nsimples y generales. Pero, \u00bfc\u00f3mo podemos dotar a nuestros\npropios actores de ese comportamiento?.\n\n\nLos objetos o figuras f\u00edsicas viven dentro del m\u00f3dulo de f\u00edsica\ny son invisibles (al principio), pero luego se pueden vincular\na cualquier actor con facilidad.\n\n\nIntenta lo siguiente, ingresa en el modo interactivo de pilas\ny pulsa la tecla \nF11\n o puls\u00e1 el bot\u00f3n \"mostrar figuras f\u00edsicas\" que\naparece abajo a la derecha:\n\n\n\n\nAhora cre\u00e1 dos figuras f\u00edsicas, una circunferencia est\u00e1tica\ny otra din\u00e1mica:\n\n\ncirculo = pilas.fisica.Circulo(0, 0, 50, dinamica=False)\ncirculo_dinamico = pilas.fisica.Circulo(10, 200, 50)\n\n\n\n\nEl primer c\u00edrculo aparecer\u00e1 en el centro de la ventana, y el\nsegundo comenzar\u00e1 en la posici\u00f3n \n(10, 200)\n, es decir,\nen la parte superior de la ventana y luego caer\u00e1\nrebotando. Algo as\u00ed:\n\n\n\n\nAhora bien, habr\u00e1s notado que estas dos circunferencias las\npodemos ver porque est\u00e1 habilitado el m\u00f3dulo de depuraci\u00f3n (que\nactivamos con \nF11\n), pero esto no lo va a ver alguien que juegue\na nuestro juego. El modo depuraci\u00f3n es solo para desarrolladores.\n\n\nLo que nos falta hacer, es darles apariencia a esas figuras. Algo\nas\u00ed como una piel..\n\n\nPara esto podemos usar actores. La din\u00e1mica es as\u00ed, tenemos que\ncrear dos actores, y luego decirle a estos actores que se comporten\nc\u00f3mo figuras geom\u00e9tricas.\n\n\nAgreguemos a nuestro programa estas 4 lineas de c\u00f3digo, queremos\nque el primer circulo (el del centro) sea un mono, y el otro\nc\u00edrculo que sea una bomba:\n\n\nmono = pilas.actores.Mono()\nmono.aprender(pilas.habilidades.Imitar, circulo)\n\nbomba = pilas.actores.Bomba()\nbomba.aprender(pilas.habilidades.Imitar, circulo_dinamico)\n\n\n\n\nEsto es diferente a lo anterior, los objetos f\u00edsicos ahora\ntienen apariencia:\n\n\n\n\nAhora podr\u00edamos desactivar el modo depuraci\u00f3n f\u00edsica (pulsando\nnuevamente \nF11\n) y jugar un poco impulsando la bomba de un\nlado a otro:\n\n\ncirculo_dinamico.y = 200\n\n\n\n\nTen en cuenta que ahora la figura del motor f\u00edsico es la\nque determina el movimiento y la rotaci\u00f3n, as\u00ed que ya no\nfuncionar\u00e1 escribir algo c\u00f3mo \nbomba.y = 200\n, ahora tienes\nque escribir \ncirculo_dinamico.y = 200\n para mover al actor...\n\n\nOtra cosa a considerar, es que en nuestro ejemplo no ajustamos\nmuy bien el tama\u00f1o del \ncirculo_dinamico\n con el de la\nbomba. Esto es un detalle poco relevante aqu\u00ed, porque solo\nquiero explicar c\u00f3mo se usa el motor, pero cuando hagas tus\njuegos, recuerda usar el modo depuraci\u00f3n de f\u00edsica para detectar\nestos detalles y corregirlos, son muy importantes para que\ntus usuarios disfruten del juego. Recuerda que ellos no\nver\u00e1n los c\u00edrculos rojos... solo ver\u00e1n la apariencia\nde los actores.\n\n\nEscala real y tama\u00f1o de figuras\n\n\nPilas utiliza una pantalla que se puede medir en pixels, de hecho, todas\nlas im\u00e1genes tienen un tama\u00f1o en pixels predefinido.\n\n\nPero dentro del mundo f\u00edsico de box2d, las figuras no tienen tama\u00f1o en pixels\nsino en metros.\n\n\n\u00bfCual es la relaci\u00f3n?, pilas convierte pixels a metros para mantener al mundo\nde box2D en coherencia con lo que estamos viendo en pantalla.\n\n\n30 pixels son equivalentes a 1 metro:\n\n\n\n\nCambiando la gravedad interactivamente\n\n\nPor defecto, la gravedad del escenario es de (0, -9), esto\nsignifica que los objetos se dirigen hacia abajo, y lo hacen con\nuna aceleraci\u00f3n de 90 mts/s^2 (metros sobre segundos cuadrados).\n\n\nPero no est\u00e1s obligado a que esto sea siempre as\u00ed, de hecho\nsi quieres hacer un juego que transcurra en el espacio seguramente\nvas a querer eliminar por completo la gravedad del escenario\npara que los objetos puedan \"flotar\", \u00bfno?.\n\n\nEntonces, Podr\u00edas cambiar la gravedad en cualquier momento cambiando\nlos atributos \ngravedad_x\n o \ngravedad_y\n del objeto\n\nfisica\n as\u00ed:\n\n\npilas.fisica.gravedad_x = 20\npilas.fisica.gravedad_y = 0\n\n\n\n\nEl atributo \ngravedad_x\n representar\u00e1 la aceleraci\u00f3n horizontal, donde los\nvalores positivos aceler\u00e1n los objetos hacia la derecha, y los valores\nnegativos a la izquierda.\n\n\nDe forma similar funciona el atributo \ngravedad_y\n, los valores positivos\naceleran los objetos hacia arriba y los valores negativos hacia abajo.", 
            "title": "Fisica"
        }, 
        {
            "location": "/fisica/#fisica", 
            "text": "Pilas incluye integraci\u00f3n con un sistema de f\u00edsica\npara realizar simulaciones y dotar a tus juegos\nde mas realismo y diversi\u00f3n.", 
            "title": "F\u00edsica"
        }, 
        {
            "location": "/fisica/#el-motor-box2d", 
            "text": "El motor de f\u00edsica seleccionado para pilas se llama Box2D, el mismo\nmotor de f\u00edsica utilizado en el juego Angry Birds.  As\u00ed, Box2D y PyBox2D son las bibliotecas protagonistas\nde casi toda la funcionalidad que vas a ver en este m\u00f3dulo.  El m\u00f3dulo  pilas.fisica  es solamente un facilitador para utilizar Box2D, y\nque puedas comenzar a jugar con f\u00edsicas r\u00e1pidamente.  As\u00ed que aprovecho este espacio para dar las gracias a  Erin Catto , y\nsu grupo de desarrollo por haber creado  Box2D .", 
            "title": "El motor: Box2D"
        }, 
        {
            "location": "/fisica/#unos-ejemplos", 
            "text": "El motor de f\u00edsica se puede mostrar en funcionamiento\nusando un ejemplo, escribe el siguiente c\u00f3digo:  pelotas = pilas.actores.Pelota() * 10  esto crear\u00e1 un grupo de circunferencias que rebotar\u00e1n\nhasta la parte inferior de la pantalla.  De manera similar puedes crear un mont\u00f3n de cajas y\nhacerlas rebotar:  cajas = pilas.actores.Caja() * 10  Como puedes ver, el resultado es un grupo ca\u00f3tico\nde actores chocando entre s\u00ed. Mas adelante veremos\ncomo personalizar y \"controlar\" un poco el escenario.   Los actores que tienen f\u00edsica son un poco particulares, pero\na\u00fan as\u00ed se los puede tratar como a otros actores. Por\nejemplo, si quieres poder arrastrar y soltar figuras con\nel mouse, puedes ense\u00f1arles una habilidad:  pelotas.aprender( arrastrable )\ncajas.aprender( arrastrable )", 
            "title": "Unos ejemplos"
        }, 
        {
            "location": "/fisica/#modo-depuracion-de-fisica", 
            "text": "Cuando haces juegos con f\u00edsica o movimientos realistas es\nmuy importante tener en cuenta un concepto importate:  Si bien uno observa pelotas y cajas, en realidad, internamente\nson solo cuadrados y circunferencias.  Lo que ocurre en pantalla son dos cosas, por una lado vemos im\u00e1genes\ncon aspecto de caja o pelota, y por el otro se nos oculta una\nsimulaci\u00f3n entre pol\u00edgonos mucho mas primitiva y simple.  Observa esta escena:   Cada uno de esos actores est\u00e1 asociado a una figura\ngeom\u00e9trica, la f\u00edsica en realidad se da en un nivel muy\nprimitivo de figuras. El aspecto de las cosas es\nsolo eso, un aspecto. Lo que \"manda\" en el comportamiento\nf\u00edsico son las figuras geom\u00e9tricas (cuerpos).  Intenta lo siguiente, pulsa la tecla  F11  o puls\u00e1 el\nbot\u00f3n \"mostrar figuras f\u00edsicas\" que aparece abajo a la\nderecha:   Las lineas blancas indican pol\u00edgonos que el\nmotor de f\u00edsica puede controlar, las cajas tienen forma\nrectangular, los actores Pelota tienen figuras circulares, y\nel suelo y las paredes tambi\u00e9n est\u00e1n en el sistema de f\u00edsica.  Si por alg\u00fan motivo quieres que los objetos no est\u00e9n contenidos\nen la pantalla, y sean un poco mas libres, podr\u00edas eliminar\nlas paredes:  pilas.fisica.eliminar_paredes()  o incluso podr\u00edas eliminar el suelo:  pilas.fisica.eliminar_suelo()  Pero recuerda que los objetos que no se ven en la pantalla\nde todas maneras estar\u00e1n ah\u00ed. Una buena idea es eliminarlos\nni bien los dejas de usar.", 
            "title": "Modo depuraci\u00f3n de f\u00edsica"
        }, 
        {
            "location": "/fisica/#fisica-personalizada", 
            "text": "Los actores  Pelota  y  Caja  est\u00e1n bien para simulaciones\nsimples y generales. Pero, \u00bfc\u00f3mo podemos dotar a nuestros\npropios actores de ese comportamiento?.  Los objetos o figuras f\u00edsicas viven dentro del m\u00f3dulo de f\u00edsica\ny son invisibles (al principio), pero luego se pueden vincular\na cualquier actor con facilidad.  Intenta lo siguiente, ingresa en el modo interactivo de pilas\ny pulsa la tecla  F11  o puls\u00e1 el bot\u00f3n \"mostrar figuras f\u00edsicas\" que\naparece abajo a la derecha:   Ahora cre\u00e1 dos figuras f\u00edsicas, una circunferencia est\u00e1tica\ny otra din\u00e1mica:  circulo = pilas.fisica.Circulo(0, 0, 50, dinamica=False)\ncirculo_dinamico = pilas.fisica.Circulo(10, 200, 50)  El primer c\u00edrculo aparecer\u00e1 en el centro de la ventana, y el\nsegundo comenzar\u00e1 en la posici\u00f3n  (10, 200) , es decir,\nen la parte superior de la ventana y luego caer\u00e1\nrebotando. Algo as\u00ed:   Ahora bien, habr\u00e1s notado que estas dos circunferencias las\npodemos ver porque est\u00e1 habilitado el m\u00f3dulo de depuraci\u00f3n (que\nactivamos con  F11 ), pero esto no lo va a ver alguien que juegue\na nuestro juego. El modo depuraci\u00f3n es solo para desarrolladores.  Lo que nos falta hacer, es darles apariencia a esas figuras. Algo\nas\u00ed como una piel..  Para esto podemos usar actores. La din\u00e1mica es as\u00ed, tenemos que\ncrear dos actores, y luego decirle a estos actores que se comporten\nc\u00f3mo figuras geom\u00e9tricas.  Agreguemos a nuestro programa estas 4 lineas de c\u00f3digo, queremos\nque el primer circulo (el del centro) sea un mono, y el otro\nc\u00edrculo que sea una bomba:  mono = pilas.actores.Mono()\nmono.aprender(pilas.habilidades.Imitar, circulo)\n\nbomba = pilas.actores.Bomba()\nbomba.aprender(pilas.habilidades.Imitar, circulo_dinamico)  Esto es diferente a lo anterior, los objetos f\u00edsicos ahora\ntienen apariencia:   Ahora podr\u00edamos desactivar el modo depuraci\u00f3n f\u00edsica (pulsando\nnuevamente  F11 ) y jugar un poco impulsando la bomba de un\nlado a otro:  circulo_dinamico.y = 200  Ten en cuenta que ahora la figura del motor f\u00edsico es la\nque determina el movimiento y la rotaci\u00f3n, as\u00ed que ya no\nfuncionar\u00e1 escribir algo c\u00f3mo  bomba.y = 200 , ahora tienes\nque escribir  circulo_dinamico.y = 200  para mover al actor...  Otra cosa a considerar, es que en nuestro ejemplo no ajustamos\nmuy bien el tama\u00f1o del  circulo_dinamico  con el de la\nbomba. Esto es un detalle poco relevante aqu\u00ed, porque solo\nquiero explicar c\u00f3mo se usa el motor, pero cuando hagas tus\njuegos, recuerda usar el modo depuraci\u00f3n de f\u00edsica para detectar\nestos detalles y corregirlos, son muy importantes para que\ntus usuarios disfruten del juego. Recuerda que ellos no\nver\u00e1n los c\u00edrculos rojos... solo ver\u00e1n la apariencia\nde los actores.", 
            "title": "F\u00edsica personalizada"
        }, 
        {
            "location": "/fisica/#escala-real-y-tamano-de-figuras", 
            "text": "Pilas utiliza una pantalla que se puede medir en pixels, de hecho, todas\nlas im\u00e1genes tienen un tama\u00f1o en pixels predefinido.  Pero dentro del mundo f\u00edsico de box2d, las figuras no tienen tama\u00f1o en pixels\nsino en metros.  \u00bfCual es la relaci\u00f3n?, pilas convierte pixels a metros para mantener al mundo\nde box2D en coherencia con lo que estamos viendo en pantalla.  30 pixels son equivalentes a 1 metro:", 
            "title": "Escala real y tama\u00f1o de figuras"
        }, 
        {
            "location": "/fisica/#cambiando-la-gravedad-interactivamente", 
            "text": "Por defecto, la gravedad del escenario es de (0, -9), esto\nsignifica que los objetos se dirigen hacia abajo, y lo hacen con\nuna aceleraci\u00f3n de 90 mts/s^2 (metros sobre segundos cuadrados).  Pero no est\u00e1s obligado a que esto sea siempre as\u00ed, de hecho\nsi quieres hacer un juego que transcurra en el espacio seguramente\nvas a querer eliminar por completo la gravedad del escenario\npara que los objetos puedan \"flotar\", \u00bfno?.  Entonces, Podr\u00edas cambiar la gravedad en cualquier momento cambiando\nlos atributos  gravedad_x  o  gravedad_y  del objeto fisica  as\u00ed:  pilas.fisica.gravedad_x = 20\npilas.fisica.gravedad_y = 0  El atributo  gravedad_x  representar\u00e1 la aceleraci\u00f3n horizontal, donde los\nvalores positivos aceler\u00e1n los objetos hacia la derecha, y los valores\nnegativos a la izquierda.  De forma similar funciona el atributo  gravedad_y , los valores positivos\naceleran los objetos hacia arriba y los valores negativos hacia abajo.", 
            "title": "Cambiando la gravedad interactivamente"
        }, 
        {
            "location": "/controles/", 
            "text": "Controles\n\n\nSi quieres conocer el estado de los controles en pilas,\ntienes que usar el objeto \npilas.control\n.\n\n\nPor ejemplo, para hacer que un actor se mueva por la pantalla simplemente puedes crear al actor y escribir estas sentencias.\n\n\nif pilas.control.izquierda:\n    mono.x -= 1\nelif pilas.control.derecha:\n    mono.x += 1\n\n\n\nEsta no es la \u00fanica forma de mover a un personaje por la pantalla, pero suele ser la mas conveniente porque es muy directa, y se puede escribir en cualquier parte del c\u00f3digo.\n\n\n\n\nNota: Recuerda que para poder interactuar con el teclado, debes seleccionar la ventana de resultado. Haz click en la parte de arriba del int\u00e9rprete de pilas para seleccionarla.\n\n\n\n\nInvestigando al objeto control\n\n\nEn realidad, cuando usamos a \npilas.control\n,\naccedemos a un objeto que tienen varios atributos.\n\n\nEstos atributos pueden valer \nTrue\n o \nFalse\n,\ndependiendo de la pulsaci\u00f3n de las teclas:\n\n\n\n\nizquierda\n\n\nderecha\n\n\narriba\n\n\nabajo\n\n\nboton\n\n\n\n\nEsto te permite simplificar el c\u00f3digo, porque no tienes que conocer espec\u00edficamente las teclas que activan cada acci\u00f3n, y en todos los juegos ser\u00e1n las mismas teclas.\n\n\n\u00bfD\u00f3nde consultar los controles?\n\n\nEl mejor lugar para consultar el estado de los controles es en la actualizaci\u00f3n de un actor.\n\n\nEsto se logra colocando un m\u00e9todo llamado \nactualizar\n dentro del actor y haciendo la consulta ah\u00ed. Veamos un actor sencillo que se pueda mover de izquierda a derecha. El c\u00f3digo ser\u00eda as\u00ed:\n\n\nimport pilasengine\n\npilas = pilasengine.iniciar()\n\nclass MiActor(pilasengine.actores.Actor):\n\n    def iniciar(self):\n        self.imagen = pilas.imagenes.cargar(\"aceituna.png\")\n\n    def actualizar(self):\n        if pilas.control.izquierda:\n            self.x -= 10\n\n        if pilas.control.derecha:\n            self.x += 10\n\nMiActor(pilas)\n\npilas.ejecutar() # Necesario al ejecutar en scripts.", 
            "title": "Controles"
        }, 
        {
            "location": "/controles/#controles", 
            "text": "Si quieres conocer el estado de los controles en pilas,\ntienes que usar el objeto  pilas.control .  Por ejemplo, para hacer que un actor se mueva por la pantalla simplemente puedes crear al actor y escribir estas sentencias.  if pilas.control.izquierda:\n    mono.x -= 1\nelif pilas.control.derecha:\n    mono.x += 1  Esta no es la \u00fanica forma de mover a un personaje por la pantalla, pero suele ser la mas conveniente porque es muy directa, y se puede escribir en cualquier parte del c\u00f3digo.   Nota: Recuerda que para poder interactuar con el teclado, debes seleccionar la ventana de resultado. Haz click en la parte de arriba del int\u00e9rprete de pilas para seleccionarla.", 
            "title": "Controles"
        }, 
        {
            "location": "/controles/#investigando-al-objeto-control", 
            "text": "En realidad, cuando usamos a  pilas.control ,\naccedemos a un objeto que tienen varios atributos.  Estos atributos pueden valer  True  o  False ,\ndependiendo de la pulsaci\u00f3n de las teclas:   izquierda  derecha  arriba  abajo  boton   Esto te permite simplificar el c\u00f3digo, porque no tienes que conocer espec\u00edficamente las teclas que activan cada acci\u00f3n, y en todos los juegos ser\u00e1n las mismas teclas.", 
            "title": "Investigando al objeto control"
        }, 
        {
            "location": "/controles/#donde-consultar-los-controles", 
            "text": "El mejor lugar para consultar el estado de los controles es en la actualizaci\u00f3n de un actor.  Esto se logra colocando un m\u00e9todo llamado  actualizar  dentro del actor y haciendo la consulta ah\u00ed. Veamos un actor sencillo que se pueda mover de izquierda a derecha. El c\u00f3digo ser\u00eda as\u00ed:  import pilasengine\n\npilas = pilasengine.iniciar()\n\nclass MiActor(pilasengine.actores.Actor):\n\n    def iniciar(self):\n        self.imagen = pilas.imagenes.cargar(\"aceituna.png\")\n\n    def actualizar(self):\n        if pilas.control.izquierda:\n            self.x -= 10\n\n        if pilas.control.derecha:\n            self.x += 10\n\nMiActor(pilas)\n\npilas.ejecutar() # Necesario al ejecutar en scripts.", 
            "title": "\u00bfD\u00f3nde consultar los controles?"
        }, 
        {
            "location": "/joystick/", 
            "text": "Joystick\n\n\nEl soporte para joysticks nos permite controlar actores usando varios\nmodelos de mandos usb, por ejemplos los de \nxbox\n o similares:\n\n\n\n\nObtener dispositivos conectados\n\n\nEl primer paso para obtener acceso a los joysticks es listar\nlos dispositivos conectados con la funci\u00f3n \nlistar\n. Por ejemplo\nen este caso hay un solo mando usb conectado:\n\n\n\u00bb pilas.pad.listar()\n['Wireless 360 Controller']\n\n\n\nAcceder a los controles\n\n\nCuando pilas-engine detecta el primer \njoystick\n, todos los eventos\nque genera el \njoystick\n se almacenar\u00e1n en el objeto \npilas.pad\n. As\u00ed\nque el acceso a las palancas o los botones se puede hacer directamente\ndesde ah\u00ed.\n\n\nEl control de posici\u00f3n anal\u00f3gico se puede acceder directamente con\nlas variables \nx\n e \ny\n\n\n\u00bb pilas.pad.x\n0\n\u00bb pilas.pad.y\n0\n\n\n\ny si se pulsa el pad, las variables retornar\u00e1n un valor entre \n-1\n y \n1\n\ndependiendo del eje. En el siguiente caso, el movimiento indica que el pad\nse movi\u00f3 para arriba a la derecha:\n\n\n\u00bb pilas.pad.x\n0.999123\n\u00bb pilas.pad.y\n1\n\n\n\nAcceso a eventos\n\n\nTambi\u00e9n se puede acceder al joystick mediante eventos, para que pilas nos\ninforme el estado del control de forma mas directa.", 
            "title": "Joystick"
        }, 
        {
            "location": "/joystick/#joystick", 
            "text": "El soporte para joysticks nos permite controlar actores usando varios\nmodelos de mandos usb, por ejemplos los de  xbox  o similares:", 
            "title": "Joystick"
        }, 
        {
            "location": "/joystick/#obtener-dispositivos-conectados", 
            "text": "El primer paso para obtener acceso a los joysticks es listar\nlos dispositivos conectados con la funci\u00f3n  listar . Por ejemplo\nen este caso hay un solo mando usb conectado:  \u00bb pilas.pad.listar()\n['Wireless 360 Controller']", 
            "title": "Obtener dispositivos conectados"
        }, 
        {
            "location": "/joystick/#acceder-a-los-controles", 
            "text": "Cuando pilas-engine detecta el primer  joystick , todos los eventos\nque genera el  joystick  se almacenar\u00e1n en el objeto  pilas.pad . As\u00ed\nque el acceso a las palancas o los botones se puede hacer directamente\ndesde ah\u00ed.  El control de posici\u00f3n anal\u00f3gico se puede acceder directamente con\nlas variables  x  e  y  \u00bb pilas.pad.x\n0\n\u00bb pilas.pad.y\n0  y si se pulsa el pad, las variables retornar\u00e1n un valor entre  -1  y  1 \ndependiendo del eje. En el siguiente caso, el movimiento indica que el pad\nse movi\u00f3 para arriba a la derecha:  \u00bb pilas.pad.x\n0.999123\n\u00bb pilas.pad.y\n1", 
            "title": "Acceder a los controles"
        }, 
        {
            "location": "/joystick/#acceso-a-eventos", 
            "text": "Tambi\u00e9n se puede acceder al joystick mediante eventos, para que pilas nos\ninforme el estado del control de forma mas directa.", 
            "title": "Acceso a eventos"
        }, 
        {
            "location": "/imagen/", 
            "text": "Manejo de im\u00e1genes\n\n\nEn los videojuegos 2D las im\u00e1genes suelen estar en formatos\ngr\u00e1ficos como \npng\n o \njpg\n ya dise\u00f1ados con anterioridad.\n\n\nEn \npilas\n se pueden cargar estos recursos usando\nel m\u00f3dulo \nimagenes\n. Por ejemplo, si tenemos una\nimagen llamada \nhola.png\n podr\u00edamos incorporarla a\nnuestro juego as\u00ed:\n\n\nhola = pilas.imagenes.cargar('hola.png')\n\n\n\n\nLas im\u00e1genes no se imprimen directamente en pantalla, en\nsu lugar tienes que crear un Actor y asignarle la\nimagen.\n\n\nPor ejemplo, el siguiente c\u00f3digo muestra la imagen\nen pantalla:\n\n\nimagen = pilas.imagenes.cargar(\"mi_personaje.png\")\nactor = pilas.actores.Actor(imagen)\n\n\n\notra opci\u00f3n similar es crear al actor, y luego\nasignarle la imagen:\n\n\nimagen = pilas.imagenes.cargar(\"mi_personaje.png\")\nactor = pilas.actores.Actor()\n\nactor.imagen = imagen\n\n\n\nCualquiera de las dos opciones produce el mismo\nresultado, personaje \"cambiar\u00e1\" de apariencia\ncuando se le asigne una nueva imagen.\n\n\nIm\u00e1genes de fondo\n\n\nMuchas veces queremos que las im\u00e1genes cubran el fondo de pantalla\ncompletamente, como si se tratara de un fondo o papel tapiz.\n\n\nSi la imagen es suficientemente gr\u00e1nde para cubrir la pantalla, podemos\ncargarla como una imagen normal y luego crear un fondo que la represente:\n\n\nfondo = pilas.fondos.Fondo()\nfondo.imagen = pilas.imagenes.cargar('mi_fondo.png')\n\n\n\nAhora, 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 \nrepetir_horizontal\n y\n\nrepetir_vertical\n\n\nfondo = pilas.fondos.Fondo()\nfondo.imagen = pilas.imagenes.cargar('mi_fondo.png')\n\nfondo.imagen.repetir_vertical = True\nfondo.imagen.repetir_horizontal = True\n\n\n\nGrillas de im\u00e1genes\n\n\nUn forma conveniente de almacenar las im\u00e1genes de tus\npersonajes es usar una grilla.\n\n\nLa siguiente imagen es una grilla de 10 columnas\nque utilizamos para crear al personaje \"pingu\":\n\n\n\n\nInternamente la imagen se almacena as\u00ed, pero a la\nhora de mostrarse en pantalla se puede seleccionar\nel cuadro.\n\n\nEste es un ejemplo que carga la grilla de mas arriba\ny genera un actor para mostrar el cuadro 1:\n\n\nactor = pilas.actores.Actor()\ngrilla = pilas.imagenes.cargar_grilla(\"pingu.png\", 10)\nactor.imagen = grilla\n\n\n\nTen en cuenta que el \u00faltimo argumento de la funci\u00f3n \npilas.imagenes.cargar_grilla\n 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.\n\n\nPuedes ejecutar la siguiente sentencia para ver\nla documentaci\u00f3n completa de esta funci\u00f3n:\n\n\nhelp(pilas.imagenes.cargar_grilla)\n\n\n\nReproduciendo animaciones\n\n\nTener una grilla de imagenes es una buena\nforma de comenzar a realizar animaciones.\n\n\nSi quieres tomar una grilla y mostrar una\ny otra vez sus cuadros podr\u00edas usar el actor Animaci\u00f3n.\n\n\nEl siguiente c\u00f3digo genera un actor que mostrar\u00e1\nuno a uno los cuadros de la grilla:\n\n\ngrilla = pilas.imagenes.cargar_grilla(\"explosion.png\", 7)\np = pilas.actores.Animacion(grilla, True)\n\n\n\nEl actor \nAnimacion\n, tambi\u00e9n puede recibir c\u00f3mo argumento\nla velocidad con la que tiene que reproducir la animaci\u00f3n (medida\nen cuadros por segundo).\n\n\nEl segundo argumento indica que la animaci\u00f3n tiene que ser\nc\u00edclica (nunca termina).\n\n\nObserva este ejemplo, muestra la misma animaci\u00f3n de antes pero\nmostrando un cuadro por segundo y se elimina cuando termina:\n\n\ngrilla = pilas.imagenes.cargar_grilla(\"explosion.png\", 7)\np = pilas.actores.Animacion(grilla, False, velocidad=1)\n\n\n\nAnimaciones controladas a mano con una grilla\n\n\nOtra forma de hacer animaciones, es asociar una grilla\ndirectamente a un actor y cambiar el cuadro a mostrar.\n\n\nPor ejemplo, la siguiente sentencia avanza al siguiente\ncuadro de animaci\u00f3n en la grilla. Recuerda que\ncomienza en 1:\n\n\ngrilla.avanzar()\nactor.imagen = grilla\n\n\n\nTen en cuenta que el m\u00e9todo \navanzar\n va a retornar \nTrue\n o \nFalse\n.\n\nTrue\n significa que la grilla ha avanzado y ha mostrado un cuadro nuevo.\n\nFalse\n significa que la grilla volvi\u00f3 a mostrar el primer cuadro.\n\n\nEste 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.\n\n\nGrillas con filas y columnas\n\n\nEn 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.\n\n\nEn este caso, la funci\u00f3n \ncargar_grilla\n tambi\u00e9n\npuede recibir la cantidad de filas que tiene una grilla:\n\n\nanimacion = pilas.imagenes.cargar_grilla(\"grilla.png\", 2, 2)\n\n\n\nel primer n\u00famero \n2\n indica que la grilla tiene dos\ncolumnas y el segudo \n2\n indica que la grilla tiene dos\nfilas.\n\n\nCuando usas una grilla con pilas y columnas, la funci\u00f3n \navanzar\n\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).\n\n\nEsta es la apariencia de la im\u00e1gen que usamos antes y\nlos n\u00fameros indican el \u00f3rden con que pilas leer\u00e1 los cuadros:\n\n\n\n\nHaciendo animaciones sencillas\n\n\nEn muchas oportunidades nos interesa hacer animaciones simples\ny que se repitan todo el tiempo sin mucho esfuerzo.\n\n\nCon 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 \navanzar\n.\n\n\nPero como esta es una tarea muy com\u00fan, en \npilas\n hay una forma\nmas sencilla de hacer esto.\n\n\nExiste un actor llamado \nAnimaci\u00f3n\n 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.\n\n\nVeamos un ejemplo, esta imagen tiene \n6\n cuadros de animaci\u00f3n\nordenados en columnas:\n\n\n\n\nUna forma sencilla de convertir esta animaci\u00f3n en un actor\nsimple es crear la grilla, construir un actor \nAnimacion\n e\nindicarle a pilas que ser\u00e1 una animaci\u00f3n c\u00edclica, es decir, que\nse tendr\u00e1 que repetir indefinidamente:\n\n\ngrilla = pilas.imagenes.cargar_grilla(\"fuego.png\", 6)\nactor = pilas.actores.Animacion(grilla, ciclica=True)\n\n\n\nEl 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.\n\n\nOtra posibilidad es especificar el argumento \nciclica=False\n. 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...\n\n\nHaciendo actores con animaci\u00f3n\n\n\nPuede 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.\n\n\nUna forma de lograr esto de manera sencilla es crear tu propio\nactor, y que este tenga dos atributos, uno para cada animaci\u00f3n:\n\n\nclass MiNave(pilasengine.actores.Actor):\n\n    def iniciar(self, x=0, y=0):\n        self.animacion_detenida = pilas.imagenes.cargar_grilla(\nnave_detenida.png\n, 1)\n        self.animacion_movimiento = pilas.imagenes.cargar_grilla(\nnave_en_movimiento.png\n, 3)\n\n\n\n\nLuego, en el m\u00e9todo \nactualizar\n del propio actor podr\u00edas\navanzar la animaci\u00f3n actual y permitirle al programador invocar\nm\u00e9todos para intercambiar animaciones:\n\n\nclass 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\n\n\n\nComo 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 \navanzar\n.\n\n\nAnimaciones\n\n\nAdem\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.\n\n\nPor ejemplo, si tenemos una grilla con varios cuadros de animaci\u00f3n como aqu\u00ed:\n\n\n\n\npodemos cargar la grilla completa y definir las dos\nanimaciones por separado.\n\n\nEnumerando los cuadros de animaci\u00f3n nos quedar\u00eda as\u00ed:\n\n\n\n\ny desde aqu\u00ed podemos extraer dos animaciones:\n\n\n\n\nLa animaci\u00f3n que podemos armar con los cuadros \n0, 1, 4\n:\n\n\n\n\n\n\n\n\nY la animaci\u00f3n que se puede armar con los cuadros \n3, 4, 5\n:\n\n\n\n\n\n\nLuego, para indicarle a \npilas\n como interpretar las animaciones podemos\ncargar la animaci\u00f3n y especificar los cuadros:\n\n\nanimacion = 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\n\n\n\nAl llamar al m\u00e9todo \ndefinir_animacion\n tenemos que especificar\nen nombre de la animaci\u00f3n, los cuadros a mostrar y luego la velocidad (medido\nen cuadros por segundo.)\n\n\nEl siguiente paso es crear al actor e indicarle que animaci\u00f3n mostrar en\ncada momento:\n\n\n\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\n\n\n\nEs decir, con esta nueva clase, podremos representar\na nuestro actor y seleccionar cualquiera de las dos\nanimaciones que declaramos usando el m\u00e9todo \ncargar_animacion\n, que en este caso usamos para cargar\nla animaci\u00f3n \nparado\n.", 
            "title": "Imagen"
        }, 
        {
            "location": "/imagen/#manejo-de-imagenes", 
            "text": "En los videojuegos 2D las im\u00e1genes suelen estar en formatos\ngr\u00e1ficos como  png  o  jpg  ya dise\u00f1ados con anterioridad.  En  pilas  se pueden cargar estos recursos usando\nel m\u00f3dulo  imagenes . Por ejemplo, si tenemos una\nimagen llamada  hola.png  podr\u00edamos incorporarla a\nnuestro juego as\u00ed:  hola = pilas.imagenes.cargar('hola.png')  Las im\u00e1genes no se imprimen directamente en pantalla, en\nsu lugar tienes que crear un Actor y asignarle la\nimagen.  Por ejemplo, el siguiente c\u00f3digo muestra la imagen\nen pantalla:  imagen = pilas.imagenes.cargar(\"mi_personaje.png\")\nactor = pilas.actores.Actor(imagen)  otra opci\u00f3n similar es crear al actor, y luego\nasignarle la imagen:  imagen = pilas.imagenes.cargar(\"mi_personaje.png\")\nactor = pilas.actores.Actor()\n\nactor.imagen = imagen  Cualquiera de las dos opciones produce el mismo\nresultado, personaje \"cambiar\u00e1\" de apariencia\ncuando se le asigne una nueva imagen.", 
            "title": "Manejo de im\u00e1genes"
        }, 
        {
            "location": "/imagen/#imagenes-de-fondo", 
            "text": "Muchas veces queremos que las im\u00e1genes cubran el fondo de pantalla\ncompletamente, como si se tratara de un fondo o papel tapiz.  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:  fondo = pilas.fondos.Fondo()\nfondo.imagen = pilas.imagenes.cargar('mi_fondo.png')  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  repetir_horizontal  y repetir_vertical  fondo = pilas.fondos.Fondo()\nfondo.imagen = pilas.imagenes.cargar('mi_fondo.png')\n\nfondo.imagen.repetir_vertical = True\nfondo.imagen.repetir_horizontal = True", 
            "title": "Im\u00e1genes de fondo"
        }, 
        {
            "location": "/imagen/#grillas-de-imagenes", 
            "text": "Un forma conveniente de almacenar las im\u00e1genes de tus\npersonajes es usar una grilla.  La siguiente imagen es una grilla de 10 columnas\nque utilizamos para crear al personaje \"pingu\":   Internamente la imagen se almacena as\u00ed, pero a la\nhora de mostrarse en pantalla se puede seleccionar\nel cuadro.  Este es un ejemplo que carga la grilla de mas arriba\ny genera un actor para mostrar el cuadro 1:  actor = pilas.actores.Actor()\ngrilla = pilas.imagenes.cargar_grilla(\"pingu.png\", 10)\nactor.imagen = grilla  Ten en cuenta que el \u00faltimo argumento de la funci\u00f3n  pilas.imagenes.cargar_grilla  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.  Puedes ejecutar la siguiente sentencia para ver\nla documentaci\u00f3n completa de esta funci\u00f3n:  help(pilas.imagenes.cargar_grilla)", 
            "title": "Grillas de im\u00e1genes"
        }, 
        {
            "location": "/imagen/#reproduciendo-animaciones", 
            "text": "Tener una grilla de imagenes es una buena\nforma de comenzar a realizar animaciones.  Si quieres tomar una grilla y mostrar una\ny otra vez sus cuadros podr\u00edas usar el actor Animaci\u00f3n.  El siguiente c\u00f3digo genera un actor que mostrar\u00e1\nuno a uno los cuadros de la grilla:  grilla = pilas.imagenes.cargar_grilla(\"explosion.png\", 7)\np = pilas.actores.Animacion(grilla, True)  El actor  Animacion , tambi\u00e9n puede recibir c\u00f3mo argumento\nla velocidad con la que tiene que reproducir la animaci\u00f3n (medida\nen cuadros por segundo).  El segundo argumento indica que la animaci\u00f3n tiene que ser\nc\u00edclica (nunca termina).  Observa este ejemplo, muestra la misma animaci\u00f3n de antes pero\nmostrando un cuadro por segundo y se elimina cuando termina:  grilla = pilas.imagenes.cargar_grilla(\"explosion.png\", 7)\np = pilas.actores.Animacion(grilla, False, velocidad=1)", 
            "title": "Reproduciendo animaciones"
        }, 
        {
            "location": "/imagen/#animaciones-controladas-a-mano-con-una-grilla", 
            "text": "Otra forma de hacer animaciones, es asociar una grilla\ndirectamente a un actor y cambiar el cuadro a mostrar.  Por ejemplo, la siguiente sentencia avanza al siguiente\ncuadro de animaci\u00f3n en la grilla. Recuerda que\ncomienza en 1:  grilla.avanzar()\nactor.imagen = grilla  Ten en cuenta que el m\u00e9todo  avanzar  va a retornar  True  o  False . True  significa que la grilla ha avanzado y ha mostrado un cuadro nuevo. False  significa que la grilla volvi\u00f3 a mostrar el primer cuadro.  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.", 
            "title": "Animaciones controladas a mano con una grilla"
        }, 
        {
            "location": "/imagen/#grillas-con-filas-y-columnas", 
            "text": "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.  En este caso, la funci\u00f3n  cargar_grilla  tambi\u00e9n\npuede recibir la cantidad de filas que tiene una grilla:  animacion = pilas.imagenes.cargar_grilla(\"grilla.png\", 2, 2)  el primer n\u00famero  2  indica que la grilla tiene dos\ncolumnas y el segudo  2  indica que la grilla tiene dos\nfilas.  Cuando usas una grilla con pilas y columnas, la funci\u00f3n  avanzar \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).  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:", 
            "title": "Grillas con filas y columnas"
        }, 
        {
            "location": "/imagen/#haciendo-animaciones-sencillas", 
            "text": "En muchas oportunidades nos interesa hacer animaciones simples\ny que se repitan todo el tiempo sin mucho esfuerzo.  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  avanzar .  Pero como esta es una tarea muy com\u00fan, en  pilas  hay una forma\nmas sencilla de hacer esto.  Existe un actor llamado  Animaci\u00f3n  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.  Veamos un ejemplo, esta imagen tiene  6  cuadros de animaci\u00f3n\nordenados en columnas:   Una forma sencilla de convertir esta animaci\u00f3n en un actor\nsimple es crear la grilla, construir un actor  Animacion  e\nindicarle a pilas que ser\u00e1 una animaci\u00f3n c\u00edclica, es decir, que\nse tendr\u00e1 que repetir indefinidamente:  grilla = pilas.imagenes.cargar_grilla(\"fuego.png\", 6)\nactor = pilas.actores.Animacion(grilla, ciclica=True)  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.  Otra posibilidad es especificar el argumento  ciclica=False . 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...", 
            "title": "Haciendo animaciones sencillas"
        }, 
        {
            "location": "/imagen/#haciendo-actores-con-animacion", 
            "text": "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.  Una forma de lograr esto de manera sencilla es crear tu propio\nactor, y que este tenga dos atributos, uno para cada animaci\u00f3n:  class MiNave(pilasengine.actores.Actor):\n\n    def iniciar(self, x=0, y=0):\n        self.animacion_detenida = pilas.imagenes.cargar_grilla( nave_detenida.png , 1)\n        self.animacion_movimiento = pilas.imagenes.cargar_grilla( nave_en_movimiento.png , 3)  Luego, en el m\u00e9todo  actualizar  del propio actor podr\u00edas\navanzar la animaci\u00f3n actual y permitirle al programador invocar\nm\u00e9todos para intercambiar animaciones:  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()  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  avanzar .", 
            "title": "Haciendo actores con animaci\u00f3n"
        }, 
        {
            "location": "/imagen/#animaciones", 
            "text": "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.  Por ejemplo, si tenemos una grilla con varios cuadros de animaci\u00f3n como aqu\u00ed:   podemos cargar la grilla completa y definir las dos\nanimaciones por separado.  Enumerando los cuadros de animaci\u00f3n nos quedar\u00eda as\u00ed:   y desde aqu\u00ed podemos extraer dos animaciones:   La animaci\u00f3n que podemos armar con los cuadros  0, 1, 4 :     Y la animaci\u00f3n que se puede armar con los cuadros  3, 4, 5 :    Luego, para indicarle a  pilas  como interpretar las animaciones podemos\ncargar la animaci\u00f3n y especificar los cuadros:  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)  Al llamar al m\u00e9todo  definir_animacion  tenemos que especificar\nen nombre de la animaci\u00f3n, los cuadros a mostrar y luego la velocidad (medido\nen cuadros por segundo.)  El siguiente paso es crear al actor e indicarle que animaci\u00f3n mostrar en\ncada momento:  \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()  Es decir, con esta nueva clase, podremos representar\na nuestro actor y seleccionar cualquiera de las dos\nanimaciones que declaramos usando el m\u00e9todo  cargar_animacion , que en este caso usamos para cargar\nla animaci\u00f3n  parado .", 
            "title": "Animaciones"
        }, 
        {
            "location": "/sonidos/", 
            "text": "Audio: Sonidos y M\u00fasica\n\n\nNota:\n Ten en cuenta que el m\u00f3dulo de audio puede estar\ndeshabilidado desde las preferencias de pilas-engine. Mir\u00e1\nel final de esta secci\u00f3n si te da problemas reproducir audio.\n\n\nLos sonidos se pueden cargar usando el m\u00f3dulo\n\nsonidos\n de la siguiente manera:\n\n\nsonido_de_explosion = pilas.sonidos.cargar('explosion.wav')\n\n\n\ndonde \nexplosion.wav\n es el nombre del archivo de audio.\n\n\nTen en cuenta que esta funci\u00f3n para cargar sonidos\nse comporta muy parecido a la funci\u00f3n que nos permite\ncargar im\u00e1genes o grillas. El archivo se buscar\u00e1 en\nel directorio principal de nuestro juego, luego en el\ndirectorio \ndata\n y por \u00faltimo en la biblioteca de\nsonidos que trae pilas.\n\n\nReproducir sonidos\n\n\nLa funci\u00f3n \nsonidos.cargar\n nos retorna un objeto de tipo\n\nSonido\n que tiene un m\u00e9todo para reproducirse llamado\n\nreproducir()\n.\n\n\nEntonces, para reproducir un sonido solamente tienes\nque llamar al m\u00e9todo \nreproducir\n:\n\n\nsonido_de_explosion.reproducir()\n\n\n\nSi deseas que un sonido se repita indefinidamente debes utilizar el par\u00e1metro\n\nrepetir=True\n. Por ejemplo:\n\n\nsonido_de_explosion.reproducir(repetir=True)\n\n\n\nPara detener el efecto de sonido, existe\nel m\u00e9todo \ndetener\n. Por ejemplo:\n\n\nsonido_de_explosion.detener()\n\n\n\nY a partir de la versi\u00f3n 1.4.8 de pilas-engine tambi\u00e9n se puede detener\nel audio reduciendo el vol\u00famen gradualmente (tambi\u00e9n conocido como fadeout):\n\n\nsonido_de_explosion.detener_gradualmente(segundos=4)\n\n\n\nReproducir canciones largas y m\u00fasica de fondo\n\n\nComo indicamos al principio de esta p\u00e1gina, utilizar m\u00fasicas o sonidos\nen pilas es muy similar, solamente tenemos que utilizar \npilas.musica\n\nen lugar de \npilas.sonidos\n.\n\n\nLo interesante de distinguir entre m\u00fasicas y sonidos es que los sonidos\nse cargan en memoria inmediatamente, porque queremos que suenen r\u00e1pido, mientras\nque la m\u00fasica se va cargando en memoria a medida que se va reproduciendo\n(tambi\u00e9n conocido como streaming) porque generalmente son archivos grandes y de\nlarga duraci\u00f3n.\n\n\nEntonces, para cargar y poner a sonar una canci\u00f3n podr\u00edamos usar algo as\u00ed:\n\n\ncancion_de_fondo = pilas.musica.cargar('musica_de_presentacion.mp3')\ncancion_de_fondo.reproducir()\n\n\n\nLuego, para detenerla, podemos llamar directamente a \ncancion.detener()\n,\no usar un efecto de vol\u00famen gradual para detenerla as\u00ed:\n\n\ncancion_de_fondo.detener_gradualmente(3)\n\n\n\nDonde el argumento \n3\n es la cantidad de segundos que utilizar\u00e1 pilas para\nbajar el vol\u00famen gradualmente.\n\n\n\u00bfAudio deshabilitado o habilitado?\n\n\nA partir de la versi\u00f3n \n1.4.8\n el sistema de audio est\u00e1\nhabilitado casi siempre, y no deber\u00eda dar problemas de\nning\u00fan tipo.\n\n\nPero en versiones anteriores a la \n1.4.8\n el audio ven\u00eda\ndeshabilitado por omisi\u00f3n, y ten\u00eda que ser habilitado por el\nusuario. Para corroborar que el audio est\u00e1 habilitado en\ntu sistema tendr\u00edas que ingresar en la secci\u00f3n preferencias\ny luego tildar la siguiente opci\u00f3n:\n\n\n\n\nDe hecho, si est\u00e1s realizando un juego y quer\u00e9s asegurarte de\nque el audio est\u00e9 habilitado siempre, podr\u00edas incluir estas lineas\njusto despu\u00e9s de la llamada a \npilas = pilasengine.iniciar()\n:\n\n\ntry:\n  pilas.forzar_habilitacion_de_audio()\nexcept AttributeError:\n  print \nOmitiendo forzar la inicializacion, version anterior a 1.4.8", 
            "title": "Audio: Sonidos y M\u00fasica"
        }, 
        {
            "location": "/sonidos/#audio-sonidos-y-musica", 
            "text": "Nota:  Ten en cuenta que el m\u00f3dulo de audio puede estar\ndeshabilidado desde las preferencias de pilas-engine. Mir\u00e1\nel final de esta secci\u00f3n si te da problemas reproducir audio.  Los sonidos se pueden cargar usando el m\u00f3dulo sonidos  de la siguiente manera:  sonido_de_explosion = pilas.sonidos.cargar('explosion.wav')  donde  explosion.wav  es el nombre del archivo de audio.  Ten en cuenta que esta funci\u00f3n para cargar sonidos\nse comporta muy parecido a la funci\u00f3n que nos permite\ncargar im\u00e1genes o grillas. El archivo se buscar\u00e1 en\nel directorio principal de nuestro juego, luego en el\ndirectorio  data  y por \u00faltimo en la biblioteca de\nsonidos que trae pilas.", 
            "title": "Audio: Sonidos y M\u00fasica"
        }, 
        {
            "location": "/sonidos/#reproducir-sonidos", 
            "text": "La funci\u00f3n  sonidos.cargar  nos retorna un objeto de tipo Sonido  que tiene un m\u00e9todo para reproducirse llamado reproducir() .  Entonces, para reproducir un sonido solamente tienes\nque llamar al m\u00e9todo  reproducir :  sonido_de_explosion.reproducir()  Si deseas que un sonido se repita indefinidamente debes utilizar el par\u00e1metro repetir=True . Por ejemplo:  sonido_de_explosion.reproducir(repetir=True)  Para detener el efecto de sonido, existe\nel m\u00e9todo  detener . Por ejemplo:  sonido_de_explosion.detener()  Y a partir de la versi\u00f3n 1.4.8 de pilas-engine tambi\u00e9n se puede detener\nel audio reduciendo el vol\u00famen gradualmente (tambi\u00e9n conocido como fadeout):  sonido_de_explosion.detener_gradualmente(segundos=4)", 
            "title": "Reproducir sonidos"
        }, 
        {
            "location": "/sonidos/#reproducir-canciones-largas-y-musica-de-fondo", 
            "text": "Como indicamos al principio de esta p\u00e1gina, utilizar m\u00fasicas o sonidos\nen pilas es muy similar, solamente tenemos que utilizar  pilas.musica \nen lugar de  pilas.sonidos .  Lo interesante de distinguir entre m\u00fasicas y sonidos es que los sonidos\nse cargan en memoria inmediatamente, porque queremos que suenen r\u00e1pido, mientras\nque la m\u00fasica se va cargando en memoria a medida que se va reproduciendo\n(tambi\u00e9n conocido como streaming) porque generalmente son archivos grandes y de\nlarga duraci\u00f3n.  Entonces, para cargar y poner a sonar una canci\u00f3n podr\u00edamos usar algo as\u00ed:  cancion_de_fondo = pilas.musica.cargar('musica_de_presentacion.mp3')\ncancion_de_fondo.reproducir()  Luego, para detenerla, podemos llamar directamente a  cancion.detener() ,\no usar un efecto de vol\u00famen gradual para detenerla as\u00ed:  cancion_de_fondo.detener_gradualmente(3)  Donde el argumento  3  es la cantidad de segundos que utilizar\u00e1 pilas para\nbajar el vol\u00famen gradualmente.", 
            "title": "Reproducir canciones largas y m\u00fasica de fondo"
        }, 
        {
            "location": "/sonidos/#audio-deshabilitado-o-habilitado", 
            "text": "A partir de la versi\u00f3n  1.4.8  el sistema de audio est\u00e1\nhabilitado casi siempre, y no deber\u00eda dar problemas de\nning\u00fan tipo.  Pero en versiones anteriores a la  1.4.8  el audio ven\u00eda\ndeshabilitado por omisi\u00f3n, y ten\u00eda que ser habilitado por el\nusuario. Para corroborar que el audio est\u00e1 habilitado en\ntu sistema tendr\u00edas que ingresar en la secci\u00f3n preferencias\ny luego tildar la siguiente opci\u00f3n:   De hecho, si est\u00e1s realizando un juego y quer\u00e9s asegurarte de\nque el audio est\u00e9 habilitado siempre, podr\u00edas incluir estas lineas\njusto despu\u00e9s de la llamada a  pilas = pilasengine.iniciar() :  try:\n  pilas.forzar_habilitacion_de_audio()\nexcept AttributeError:\n  print  Omitiendo forzar la inicializacion, version anterior a 1.4.8", 
            "title": "\u00bfAudio deshabilitado o habilitado?"
        }, 
        {
            "location": "/dibujado_simple_en_pantalla/", 
            "text": "Dibujado simple en pantalla\n\n\nHasta ahora hemos mostrado en la pantalla\nfondos y actores que originalmente estaban\nalmacenados en el disco de la computadora\nc\u00f3mo im\u00e1genes.\n\n\nEn esta secci\u00f3n veremos como dibujar libremente, ya\nsean lineas, c\u00edrculos, texto etc..\n\n\nComenzaremos con una forma de dibujado muy\nsencilla, y luego veremos algunas alternativas\nque ofrecen mas flexibilidad.\n\n\nTen en cuenta que el dibujo avanzado y mas flexible\nlo vamos a ver en el siguiente cap\u00edtulo \nDibujo avanzado\ncon Superficies\n.\n\n\nUsando la Tortuga para dibujar\n\n\nEl actor \nTortuga\n est\u00e1 inspirado en una de\nlas actividades mas divertidas, did\u00e1cticas y simb\u00f3licas\ndel lenguaje de programaci\u00f3n \nlogo\n, creado\npor \nSeymour Papert\n.\n\n\nLa \nTortuga\n b\u00e1sicamente es un actor que sabe\ndibujar sobre la ventana de pilas. Para ello el\nprogramador tiene que indicarle a la tortuga qu\u00e9\nmovimiento debe realizar.\n\n\nLa siguiente imagen muestra lo que podr\u00eda\ndibujar la tortuga con algunas sentencias de\nmovimientos:\n\n\n\n\nLa imagen no alcanza a mostrar por completo el\nconcepto, pero en pocas palabras se puede sintetizar\nlo que realmente hace.\n\n\nEl dibujo de la imagen anterior es una traza que\nva dibujando la tortuga a partir de su movimiento.\n\n\nEl siguiente c\u00f3digo es el que se utiliz\u00f3 para\ndibujar esa linea de dos colores:\n\n\nimport pilasengine\n\npilas = pilasengine.iniciar()\n\ntortuga = pilas.actores.Tortuga()\ntortuga.avanzar(30)\ntortuga.color = pilas.colores.azul\ntortuga.avanzar(200)\n\n\n\n\nAlgo muy valioso en t\u00e9rminos did\u00e1cticos, es que\nuno podr\u00eda animarse a realizar dibujos simples c\u00f3mo\nuna casa, un hex\u00e1gono o cualquier otra figura dise\u00f1ando una estrategia\nde movimiento para la tortuga.\n\n\nInspeccionando a la tortuga\n\n\nPara manejar a este actor tienes varios comandos\ninspirados en logo.\n\n\nEsta es una lista de los comandos mas utilizados:\n\n\n\n\n\n\n\n\nM\u00e9todo completo\n\n\nnombre corto\n\n\nejemplo\n\n\n\u00bfque hace?\n\n\n\n\n\n\n\n\n\n\navanzar\n\n\nav\n\n\ntortuga.av(10)\n\n\navanza en direcci\u00f3n a donde mira la tortuga.\n\n\n\n\n\n\ngiraderecha\n\n\ngd\n\n\ntortuga.gd(45)\n\n\ngira hacia la derecha los grados indicados.\n\n\n\n\n\n\ngiraizquierda\n\n\ngi\n\n\ntortuga.gi(45)\n\n\ngira hacia la izquierda los grados indicados.\n\n\n\n\n\n\nsubelapiz\n\n\nsl\n\n\ntortuga.sl()\n\n\ndeja de dibujar cuando se mueve la tortuga.\n\n\n\n\n\n\nbajalapiz\n\n\nbl\n\n\ntortuga.bl()\n\n\ncomienza a dibujar cuando la tortuga se mueve.\n\n\n\n\n\n\npon_color\n\n\npc\n\n\ntortuga.pc(pilas.colores.rojo)\n\n\ndibuja con el color indicado.\n\n\n\n\n\n\npintar\n\n\npintar\n\n\ntortuga.pintar(pilas.colores.blanco)\n\n\npinta toda la pantala del mismo color.\n\n\n\n\n\n\n\n\nPor supuesto hay algunos mas, pero esos quedan para\ninvestigar en la clase propiamente dicha. Recuerda que\nel auto-completado del int\u00e9rprete de python es bastante\n\u00fatil para estas cosas.\n\n\nUsando una Pizarra\n\n\nSi quieres dibujar sobre la pantalla pero\nde forma inmediata y con algunas posibilidades mas\nelaboradas, puedes\nusar un actor llamado \nPizarra\n. Esta no es la\nforma mas avanzada, pero es el siguiente paso despu\u00e9s\nde dominar al actor \nTortuga\n.\n\n\nEste actor \nPizarra\n es c\u00f3mo un lienzo invisible sobre\nel que podemos pintar im\u00e1genes, figuras\ngeom\u00e9tricas y trazos de cualquier tipo. De hecho, el actor\n\nTortuga\n que vimos antes, en realidad estaba\ndibujando sobre una pizarra, solo que lo hac\u00eda con\nanimaciones y algo lento.\n\n\nComencemos con algo sencillo: para crear la pizarra y\ndibujar un punto en el centro de la\npantalla se puede usar el siguiente\nc\u00f3digo:\n\n\npizarra = pilas.actores.Pizarra()\npizarra.dibujar_punto(0, 0)\n\n\n\n\nincluso podr\u00edas usar el argumento opcional \ncolor\n\nsi prefieres otro color, o trazar una linea:\n\n\npizarra.linea(0, 0, 200, 200, pilas.colores.verdeoscuro, grosor=5)\n\n\n\n\n\n\nPintando im\u00e1genes\n\n\nLas pizarras tambi\u00e9n pueden dibujar im\u00e1genes sobre la superficie,\ny esto es \u00fatil cuando quieras crear pinceles especiales sobre\nla pizarra o construir un escenario usando bloques tipo\nladrillos.\n\n\nPara pintar una imagen solo tienes que cargarla e\nindicarla a la pizarra que la dibuje en una posicion determinada.\n\n\nimagen = pilas.imagenes.cargar(\"pelota.png\")\npizarra.pintar_imagen(imagen, 0, 0)\n\n\n\nAs\u00ed se ver\u00e1:\n\n\n\n\nTen en cuenta que en estos casos, cuando estamos dibujando\nuna imagen sobre otra, el punto destino (x, y) siempre indica\nla esquina superior izquierda de la imagen, no el centro u\notra posici\u00f3n relativa como en el caso de los actores.\n\n\nPintando porciones de im\u00e1genes\n\n\nHay ocasiones en las que te resultar\u00e1 \u00fatil poder\npintar solamente porciones de una imagen sobre otra. Para\nestos casos est\u00e1 el m\u00e9todo \npintar_parte_de_imagen\n.\n\n\nVeamos la definici\u00f3n del m\u00e9todo::\n\n\ndef pintar_parte_de_imagen(self, imagen, origen_x, origen_y, ancho, alto, x, y):\n\n\n\nDibujando grillas\n\n\nDe manera similar a las im\u00e1genes normales, sobre las pizarras\ntambi\u00e9n se pueden pintar grillas.\n\n\nSolamente tenemos que crear la grilla, seleccionar el\ncuadro de animaci\u00f3n y despu\u00e9s decirle a la pizarra\nque pinte el cuadro actual de la grilla:\n\n\ngrilla = pilas.imagenes.cargar_grilla(\"pingu.png\", 10)\npizarra.pintar_grilla(grilla, 0, 0)\n\n\n\nAs\u00ed se ver\u00e1:\n\n\n\n\nEsto es \u00fatil cuando se quieren pintar bloques de un escenario\ncompleto, por ejemplo podr\u00edamos tener una grilla con distintos\ntipos de suelos (pasto, piedra, tierra) y luego ir\nimprimiendo sobre una pizarra para formar un escenario completo.\n\n\nLa pizarra como actor\n\n\nRecuerda que la pizarra tambi\u00e9n es un actor, as\u00ed que puedes ense\u00f1arle\nhabilidades, cambiar su posici\u00f3n, rotaci\u00f3n o lo que quieras.", 
            "title": "Dibujado simple en pantalla"
        }, 
        {
            "location": "/dibujado_simple_en_pantalla/#dibujado-simple-en-pantalla", 
            "text": "Hasta ahora hemos mostrado en la pantalla\nfondos y actores que originalmente estaban\nalmacenados en el disco de la computadora\nc\u00f3mo im\u00e1genes.  En esta secci\u00f3n veremos como dibujar libremente, ya\nsean lineas, c\u00edrculos, texto etc..  Comenzaremos con una forma de dibujado muy\nsencilla, y luego veremos algunas alternativas\nque ofrecen mas flexibilidad.  Ten en cuenta que el dibujo avanzado y mas flexible\nlo vamos a ver en el siguiente cap\u00edtulo  Dibujo avanzado\ncon Superficies .", 
            "title": "Dibujado simple en pantalla"
        }, 
        {
            "location": "/dibujado_simple_en_pantalla/#usando-la-tortuga-para-dibujar", 
            "text": "El actor  Tortuga  est\u00e1 inspirado en una de\nlas actividades mas divertidas, did\u00e1cticas y simb\u00f3licas\ndel lenguaje de programaci\u00f3n  logo , creado\npor  Seymour Papert .  La  Tortuga  b\u00e1sicamente es un actor que sabe\ndibujar sobre la ventana de pilas. Para ello el\nprogramador tiene que indicarle a la tortuga qu\u00e9\nmovimiento debe realizar.  La siguiente imagen muestra lo que podr\u00eda\ndibujar la tortuga con algunas sentencias de\nmovimientos:   La imagen no alcanza a mostrar por completo el\nconcepto, pero en pocas palabras se puede sintetizar\nlo que realmente hace.  El dibujo de la imagen anterior es una traza que\nva dibujando la tortuga a partir de su movimiento.  El siguiente c\u00f3digo es el que se utiliz\u00f3 para\ndibujar esa linea de dos colores:  import pilasengine\n\npilas = pilasengine.iniciar()\n\ntortuga = pilas.actores.Tortuga()\ntortuga.avanzar(30)\ntortuga.color = pilas.colores.azul\ntortuga.avanzar(200)  Algo muy valioso en t\u00e9rminos did\u00e1cticos, es que\nuno podr\u00eda animarse a realizar dibujos simples c\u00f3mo\nuna casa, un hex\u00e1gono o cualquier otra figura dise\u00f1ando una estrategia\nde movimiento para la tortuga.", 
            "title": "Usando la Tortuga para dibujar"
        }, 
        {
            "location": "/dibujado_simple_en_pantalla/#inspeccionando-a-la-tortuga", 
            "text": "Para manejar a este actor tienes varios comandos\ninspirados en logo.  Esta es una lista de los comandos mas utilizados:     M\u00e9todo completo  nombre corto  ejemplo  \u00bfque hace?      avanzar  av  tortuga.av(10)  avanza en direcci\u00f3n a donde mira la tortuga.    giraderecha  gd  tortuga.gd(45)  gira hacia la derecha los grados indicados.    giraizquierda  gi  tortuga.gi(45)  gira hacia la izquierda los grados indicados.    subelapiz  sl  tortuga.sl()  deja de dibujar cuando se mueve la tortuga.    bajalapiz  bl  tortuga.bl()  comienza a dibujar cuando la tortuga se mueve.    pon_color  pc  tortuga.pc(pilas.colores.rojo)  dibuja con el color indicado.    pintar  pintar  tortuga.pintar(pilas.colores.blanco)  pinta toda la pantala del mismo color.     Por supuesto hay algunos mas, pero esos quedan para\ninvestigar en la clase propiamente dicha. Recuerda que\nel auto-completado del int\u00e9rprete de python es bastante\n\u00fatil para estas cosas.", 
            "title": "Inspeccionando a la tortuga"
        }, 
        {
            "location": "/dibujado_simple_en_pantalla/#usando-una-pizarra", 
            "text": "Si quieres dibujar sobre la pantalla pero\nde forma inmediata y con algunas posibilidades mas\nelaboradas, puedes\nusar un actor llamado  Pizarra . Esta no es la\nforma mas avanzada, pero es el siguiente paso despu\u00e9s\nde dominar al actor  Tortuga .  Este actor  Pizarra  es c\u00f3mo un lienzo invisible sobre\nel que podemos pintar im\u00e1genes, figuras\ngeom\u00e9tricas y trazos de cualquier tipo. De hecho, el actor Tortuga  que vimos antes, en realidad estaba\ndibujando sobre una pizarra, solo que lo hac\u00eda con\nanimaciones y algo lento.  Comencemos con algo sencillo: para crear la pizarra y\ndibujar un punto en el centro de la\npantalla se puede usar el siguiente\nc\u00f3digo:  pizarra = pilas.actores.Pizarra()\npizarra.dibujar_punto(0, 0)  incluso podr\u00edas usar el argumento opcional  color \nsi prefieres otro color, o trazar una linea:  pizarra.linea(0, 0, 200, 200, pilas.colores.verdeoscuro, grosor=5)", 
            "title": "Usando una Pizarra"
        }, 
        {
            "location": "/dibujado_simple_en_pantalla/#pintando-imagenes", 
            "text": "Las pizarras tambi\u00e9n pueden dibujar im\u00e1genes sobre la superficie,\ny esto es \u00fatil cuando quieras crear pinceles especiales sobre\nla pizarra o construir un escenario usando bloques tipo\nladrillos.  Para pintar una imagen solo tienes que cargarla e\nindicarla a la pizarra que la dibuje en una posicion determinada.  imagen = pilas.imagenes.cargar(\"pelota.png\")\npizarra.pintar_imagen(imagen, 0, 0)  As\u00ed se ver\u00e1:   Ten en cuenta que en estos casos, cuando estamos dibujando\nuna imagen sobre otra, el punto destino (x, y) siempre indica\nla esquina superior izquierda de la imagen, no el centro u\notra posici\u00f3n relativa como en el caso de los actores.", 
            "title": "Pintando im\u00e1genes"
        }, 
        {
            "location": "/dibujado_simple_en_pantalla/#pintando-porciones-de-imagenes", 
            "text": "Hay ocasiones en las que te resultar\u00e1 \u00fatil poder\npintar solamente porciones de una imagen sobre otra. Para\nestos casos est\u00e1 el m\u00e9todo  pintar_parte_de_imagen .  Veamos la definici\u00f3n del m\u00e9todo::  def pintar_parte_de_imagen(self, imagen, origen_x, origen_y, ancho, alto, x, y):", 
            "title": "Pintando porciones de im\u00e1genes"
        }, 
        {
            "location": "/dibujado_simple_en_pantalla/#dibujando-grillas", 
            "text": "De manera similar a las im\u00e1genes normales, sobre las pizarras\ntambi\u00e9n se pueden pintar grillas.  Solamente tenemos que crear la grilla, seleccionar el\ncuadro de animaci\u00f3n y despu\u00e9s decirle a la pizarra\nque pinte el cuadro actual de la grilla:  grilla = pilas.imagenes.cargar_grilla(\"pingu.png\", 10)\npizarra.pintar_grilla(grilla, 0, 0)  As\u00ed se ver\u00e1:   Esto es \u00fatil cuando se quieren pintar bloques de un escenario\ncompleto, por ejemplo podr\u00edamos tener una grilla con distintos\ntipos de suelos (pasto, piedra, tierra) y luego ir\nimprimiendo sobre una pizarra para formar un escenario completo.", 
            "title": "Dibujando grillas"
        }, 
        {
            "location": "/dibujado_simple_en_pantalla/#la-pizarra-como-actor", 
            "text": "Recuerda que la pizarra tambi\u00e9n es un actor, as\u00ed que puedes ense\u00f1arle\nhabilidades, cambiar su posici\u00f3n, rotaci\u00f3n o lo que quieras.", 
            "title": "La pizarra como actor"
        }, 
        {
            "location": "/dibujado_avanzado_con_superficies/", 
            "text": "Dibujado avanzado con Superficies\n\n\nAnteriormente vimos que los actores pod\u00edan\ntener un aspecto visual, ya sea gracias a\nuna imagen completa, una grilla o un dibujo\nde pizarra.\n\n\nPero hay situaciones donde realmente necesitamos\nalgo mas. En muchas ocasiones necesitamos que\nlos actores puedan tener una apariencia que\nconstruimos program\u00e1ticamente (si existe la palabra...).\n\n\nPor ejemplo, imagina que queremos hacer un indicador\nde energ\u00eda, un cron\u00f3metro, un indicador de vidas, un\nbot\u00f3n etc...\n\n\nDibujando sobre superficies\n\n\nEn pilas una superficie es una imagen, pero que no\nse carga directamente desde el disco, sino que se\nconstruye en memoria de la computadora, se puede\ndibujar sobre ella y luego se le puede aplicar\na un actor como apariencia.\n\n\nComencemos con un ejemplo sencillo, imagina que\nqueremos hacer un actor muy feo, de color \"verde\"\ny con dos ojitos. Lo primero que tenemos que hacer\nes crear una superficie, dibujar sobre ella, y luego\ncrear un actor con esa apariencia:\n\n\nimport pilasengine\n\npilas = pilasengine.iniciar()\n\nsuperficie = pilas.imagenes.cargar_superficie(100, 100)\n\n# dibujamos el cuerpo\nsuperficie.circulo(50, 50, 40, color=pilas.colores.verdeoscuro, relleno=True)\n\n# un ojo\nsuperficie.circulo(35, 35, 10, color=pilas.colores.blanco, relleno=True)\nsuperficie.circulo(32, 35, 5, color=pilas.colores.negro, relleno=True)\n\n# el otro ojo\nsuperficie.circulo(67, 35, 10, color=pilas.colores.blanco, relleno=True)\nsuperficie.circulo(64, 35, 5, color=pilas.colores.negro, relleno=True)\n\npilas.actores.Actor(imagen=superficie)\n\npilas.ejecutar() # Necesario al ejecutar en scripts.\n\n\n\n\nEs decir, una vez que creamos la superficie, en realidad lo que obtenemos\nes un objeto que se comporta c\u00f3mo una imagen, pero con la diferencia\nque podemos dibujar sobre ella libremente y crear desde el c\u00f3digo la\nimagen que queramos:\n\n\n\n\nTen en cuenta que tambi\u00e9n estamos mostrando la superficie gracias a un\nactor, as\u00ed que si rotamos el actor o cambiamos su escala la superficie\nse observar\u00e1 de forma transformada.\n\n\nVamos a ver con mas detalle este recurso de pilas, porque ofrece muchas\nmas funcionalidades de las que vemos en este ejemplo.\n\n\nCreaci\u00f3n de una superficie\n\n\nPara crear una superficie tenemos que invocar a la funci\u00f3n \npilas.imagenes.cargar_superficie\n\ncomo vimos mas arriba. Esta funci\u00f3n admite dos par\u00e1metros que indican\nel ancho y el alto de la superficie.\n\n\nA partir de ese momento, la superficie ser\u00e1 completamente transparente, y lo\nque dibujemos sobre ella har\u00e1 que no se note que en realidad es\nun rect\u00e1ngulo. Vale aclarar que efectivamente todas las im\u00e1genes de los videojuegos\nson rectangulares aunque se disimule...\n\n\nCoordenadas de las superficies\n\n\nLas coordenadas que se tienen que especificar para dibujar\nsobre una superficie son diferentes a las coordenadas cartesianas\nque usamos en la ventana de pilas.\n\n\nEl motivo de este cambio es que las superficies est\u00e1n en la memoria\nde la computadora, y es mas sencillo tratar con ellas si usamos\nel mismo sistema de coordenadas que se usa en casi todas las aplicaciones\ngr\u00e1ficas. Ten en cuenta que estas son funciones avanzadas y\nque generalmente se trabaja sobre estas funciones unas pocas veces\npara lograr lo que ya no est\u00e1 implementado como un actor...\n\n\nEl sistema de coordenadas de las superficies tiene su origen\nen la esquina superior izquierda \n(0, 0)\n, luego el eje \nx\n crece\nhacia la derecha y el eje \ny\n crece hacia abajo.\n\n\nM\u00e9todos para dibujar\n\n\nPintar\n\n\nOriginalmente cuando creamos una superficie es completamente\ntransparente. Si queremos cambiar esto y pintar toda la superficie\nde un color plano, podemos usar el siguiente m\u00e9todo::\n\n\nsuperficie.pintar(color)\n\n\n\nDonde el argumento color puede ser algo c\u00f3mo \npilas.colores.rojo\n o\nun color personalizado indicando las componentes de color\n\nrojo\n, \nverde\n y \nazul\n. Por ejemplo::\n\n\nsuperficie.pintar(pilas.colores.Color(100, 255, 0))\n\n\n\nCirculo\n\n\nPara pintar c\u00edrculos podemos usar el m\u00e9todo \ncirculo\n. Indicando la\nposici\u00f3n del c\u00edrculo, su radio y el color.\n\n\nTen en cuenta que tambi\u00e9n debemos indicar si queremos un c\u00edrculo completamente\ns\u00f3lido y pintado o solamente un borde.\n\n\nEsta es la definici\u00f3n del m\u00e9todo:\n\n\ndef circulo(self, x, y, radio, color=colores.negro, relleno=False, grosor=1):\n\n\n\nSi invocamos a la funci\u00f3n solamente con sus argumentos principales, obtendremos\nuna silueta de circunferencia sin relleno, por ejemplo::\n\n\nfigura.circulo(50, 50, 100)\n\n\n\no si queremos un trazo mas grueso:\n\n\nfigura.circulo(50, 50, 100, grosor=5)\n\n\n\naunque tambi\u00e9n podemos indicarle que la circunferencia tiene que\nestar pintada y con otro color:\n\n\nfigura.circulo(50, 50, 100, pilas.colores.rojo, relleno=True)\n\n\n\nRect\u00e1ngulo\n\n\nEl dibujo de rect\u00e1ngulos es muy similar al de c\u00edrculos, solo que aqu\u00ed\ntenemos que indicar la coordenada de la esquina superior izquierda\ndel rect\u00e1ngulo y el tama\u00f1o, en ancho y alto.\n\n\nEsta es la definici\u00f3n del m\u00e9todo:\n\n\ndef rectangulo(self, x, y, ancho, alto, color=colores.negro, relleno=False, grosor=1):\n\n\n\nLinea\n\n\nUna linea se compone obligatoriamente de puntos, los que marcan el\nprincipio y el final de la linea. Para esto se tienen que usar\n4 n\u00fameros, dos para cada punto.\n\n\nPor ejemplo, el siguiente c\u00f3digo dibuja una linea diagonal\nde color rojo y con 3 p\u00edxeles de grosor:\n\n\nsuperficie.linea(20, 20, 50, 50, pilas.colores.rojo, 3)\n\n\n\nTexto\n\n\nEl dibujo de texto se realiza siempre a partir de una cadena\nde texto. Y opcionalmente se pueden especificar otros\npar\u00e1metros c\u00f3mo la posici\u00f3n del texto, el color, el tama\u00f1o de\nlas letras y la tipograf\u00eda.\n\n\nEste es un ejemplo sencillo que imprime un texto de color\nazul:\n\n\nsuperficie.texto(\"Hola mundo\", magnitud=20, fuente=\"Courrier\", color=pilas.colores.azul)\n\n\n\nTen en cuenta que la fuente se indica como una cadena, y\nel valor que podemos poner ah\u00ed es el de cualquiera de nuestras\nfuentes del sistema. Si nuestro sistema no tiene la fuente que le\nsolicitamos, se imprimir\u00e1 usando una tipograf\u00eda por defecto.", 
            "title": "Dibujado avanzado con Superficies"
        }, 
        {
            "location": "/dibujado_avanzado_con_superficies/#dibujado-avanzado-con-superficies", 
            "text": "Anteriormente vimos que los actores pod\u00edan\ntener un aspecto visual, ya sea gracias a\nuna imagen completa, una grilla o un dibujo\nde pizarra.  Pero hay situaciones donde realmente necesitamos\nalgo mas. En muchas ocasiones necesitamos que\nlos actores puedan tener una apariencia que\nconstruimos program\u00e1ticamente (si existe la palabra...).  Por ejemplo, imagina que queremos hacer un indicador\nde energ\u00eda, un cron\u00f3metro, un indicador de vidas, un\nbot\u00f3n etc...", 
            "title": "Dibujado avanzado con Superficies"
        }, 
        {
            "location": "/dibujado_avanzado_con_superficies/#dibujando-sobre-superficies", 
            "text": "En pilas una superficie es una imagen, pero que no\nse carga directamente desde el disco, sino que se\nconstruye en memoria de la computadora, se puede\ndibujar sobre ella y luego se le puede aplicar\na un actor como apariencia.  Comencemos con un ejemplo sencillo, imagina que\nqueremos hacer un actor muy feo, de color \"verde\"\ny con dos ojitos. Lo primero que tenemos que hacer\nes crear una superficie, dibujar sobre ella, y luego\ncrear un actor con esa apariencia:  import pilasengine\n\npilas = pilasengine.iniciar()\n\nsuperficie = pilas.imagenes.cargar_superficie(100, 100)\n\n# dibujamos el cuerpo\nsuperficie.circulo(50, 50, 40, color=pilas.colores.verdeoscuro, relleno=True)\n\n# un ojo\nsuperficie.circulo(35, 35, 10, color=pilas.colores.blanco, relleno=True)\nsuperficie.circulo(32, 35, 5, color=pilas.colores.negro, relleno=True)\n\n# el otro ojo\nsuperficie.circulo(67, 35, 10, color=pilas.colores.blanco, relleno=True)\nsuperficie.circulo(64, 35, 5, color=pilas.colores.negro, relleno=True)\n\npilas.actores.Actor(imagen=superficie)\n\npilas.ejecutar() # Necesario al ejecutar en scripts.  Es decir, una vez que creamos la superficie, en realidad lo que obtenemos\nes un objeto que se comporta c\u00f3mo una imagen, pero con la diferencia\nque podemos dibujar sobre ella libremente y crear desde el c\u00f3digo la\nimagen que queramos:   Ten en cuenta que tambi\u00e9n estamos mostrando la superficie gracias a un\nactor, as\u00ed que si rotamos el actor o cambiamos su escala la superficie\nse observar\u00e1 de forma transformada.  Vamos a ver con mas detalle este recurso de pilas, porque ofrece muchas\nmas funcionalidades de las que vemos en este ejemplo.", 
            "title": "Dibujando sobre superficies"
        }, 
        {
            "location": "/dibujado_avanzado_con_superficies/#creacion-de-una-superficie", 
            "text": "Para crear una superficie tenemos que invocar a la funci\u00f3n  pilas.imagenes.cargar_superficie \ncomo vimos mas arriba. Esta funci\u00f3n admite dos par\u00e1metros que indican\nel ancho y el alto de la superficie.  A partir de ese momento, la superficie ser\u00e1 completamente transparente, y lo\nque dibujemos sobre ella har\u00e1 que no se note que en realidad es\nun rect\u00e1ngulo. Vale aclarar que efectivamente todas las im\u00e1genes de los videojuegos\nson rectangulares aunque se disimule...", 
            "title": "Creaci\u00f3n de una superficie"
        }, 
        {
            "location": "/dibujado_avanzado_con_superficies/#coordenadas-de-las-superficies", 
            "text": "Las coordenadas que se tienen que especificar para dibujar\nsobre una superficie son diferentes a las coordenadas cartesianas\nque usamos en la ventana de pilas.  El motivo de este cambio es que las superficies est\u00e1n en la memoria\nde la computadora, y es mas sencillo tratar con ellas si usamos\nel mismo sistema de coordenadas que se usa en casi todas las aplicaciones\ngr\u00e1ficas. Ten en cuenta que estas son funciones avanzadas y\nque generalmente se trabaja sobre estas funciones unas pocas veces\npara lograr lo que ya no est\u00e1 implementado como un actor...  El sistema de coordenadas de las superficies tiene su origen\nen la esquina superior izquierda  (0, 0) , luego el eje  x  crece\nhacia la derecha y el eje  y  crece hacia abajo.", 
            "title": "Coordenadas de las superficies"
        }, 
        {
            "location": "/dibujado_avanzado_con_superficies/#metodos-para-dibujar", 
            "text": "", 
            "title": "M\u00e9todos para dibujar"
        }, 
        {
            "location": "/dibujado_avanzado_con_superficies/#pintar", 
            "text": "Originalmente cuando creamos una superficie es completamente\ntransparente. Si queremos cambiar esto y pintar toda la superficie\nde un color plano, podemos usar el siguiente m\u00e9todo::  superficie.pintar(color)  Donde el argumento color puede ser algo c\u00f3mo  pilas.colores.rojo  o\nun color personalizado indicando las componentes de color rojo ,  verde  y  azul . Por ejemplo::  superficie.pintar(pilas.colores.Color(100, 255, 0))", 
            "title": "Pintar"
        }, 
        {
            "location": "/dibujado_avanzado_con_superficies/#circulo", 
            "text": "Para pintar c\u00edrculos podemos usar el m\u00e9todo  circulo . Indicando la\nposici\u00f3n del c\u00edrculo, su radio y el color.  Ten en cuenta que tambi\u00e9n debemos indicar si queremos un c\u00edrculo completamente\ns\u00f3lido y pintado o solamente un borde.  Esta es la definici\u00f3n del m\u00e9todo:  def circulo(self, x, y, radio, color=colores.negro, relleno=False, grosor=1):  Si invocamos a la funci\u00f3n solamente con sus argumentos principales, obtendremos\nuna silueta de circunferencia sin relleno, por ejemplo::  figura.circulo(50, 50, 100)  o si queremos un trazo mas grueso:  figura.circulo(50, 50, 100, grosor=5)  aunque tambi\u00e9n podemos indicarle que la circunferencia tiene que\nestar pintada y con otro color:  figura.circulo(50, 50, 100, pilas.colores.rojo, relleno=True)", 
            "title": "Circulo"
        }, 
        {
            "location": "/dibujado_avanzado_con_superficies/#rectangulo", 
            "text": "El dibujo de rect\u00e1ngulos es muy similar al de c\u00edrculos, solo que aqu\u00ed\ntenemos que indicar la coordenada de la esquina superior izquierda\ndel rect\u00e1ngulo y el tama\u00f1o, en ancho y alto.  Esta es la definici\u00f3n del m\u00e9todo:  def rectangulo(self, x, y, ancho, alto, color=colores.negro, relleno=False, grosor=1):", 
            "title": "Rect\u00e1ngulo"
        }, 
        {
            "location": "/dibujado_avanzado_con_superficies/#linea", 
            "text": "Una linea se compone obligatoriamente de puntos, los que marcan el\nprincipio y el final de la linea. Para esto se tienen que usar\n4 n\u00fameros, dos para cada punto.  Por ejemplo, el siguiente c\u00f3digo dibuja una linea diagonal\nde color rojo y con 3 p\u00edxeles de grosor:  superficie.linea(20, 20, 50, 50, pilas.colores.rojo, 3)", 
            "title": "Linea"
        }, 
        {
            "location": "/dibujado_avanzado_con_superficies/#texto", 
            "text": "El dibujo de texto se realiza siempre a partir de una cadena\nde texto. Y opcionalmente se pueden especificar otros\npar\u00e1metros c\u00f3mo la posici\u00f3n del texto, el color, el tama\u00f1o de\nlas letras y la tipograf\u00eda.  Este es un ejemplo sencillo que imprime un texto de color\nazul:  superficie.texto(\"Hola mundo\", magnitud=20, fuente=\"Courrier\", color=pilas.colores.azul)  Ten en cuenta que la fuente se indica como una cadena, y\nel valor que podemos poner ah\u00ed es el de cualquiera de nuestras\nfuentes del sistema. Si nuestro sistema no tiene la fuente que le\nsolicitamos, se imprimir\u00e1 usando una tipograf\u00eda por defecto.", 
            "title": "Texto"
        }, 
        {
            "location": "/tareas/", 
            "text": "Manejo de tiempo con tareas\n\n\nUna necesidad muy com\u00fan en los videojuegos\nes poder planificar tareas para ser ejecutadas\npor tiempo.\n\n\nPor ejemplo, en un juego de naves podr\u00edamos\nquerer que aparezcan naves enemigas cada\ndos segundos.\n\n\nTareas\n\n\nLas tareas son acciones que elegimos ejecutar\nen un determinado momento.\n\n\nAl momento de crear la tarea tenemos que\npensar \"en qu\u00e9 momento se tiene que ejecutar\nla tarea\", y dependiendo de lo que queramos,\ntenemos que escribir algo c\u00f3mo:\n\n\npilas.tareas.agregar(tiempo, funcion, parametros)\n\n\n\n\nPor ejemplo, para hacer que un actor espere 5 segundos\nantes de emitir un mensaje:\n\n\nmono = pilas.actores.Mono()\n\ndef emitir_mensaje():\n  mono.decir(\nHola\n)\n\npilas.tareas.agregar(5, emitir_mensaje)  \n\n\n\n\nHay tres tipos de creaciones de tareas:\n\n\n\n\ntareas que se ejecutan una vez.\n\n\ntareas que se ejecutan siempre.\n\n\ntareas condicionales.\n\n\n\n\nlas tareas condicionales se ejecutar\u00e1n siempre y cuando\nla funci\u00f3n que las representa retorna True. Si la funci\u00f3n\nretorna False la tarea dejar\u00e1 de ejecutarse.\n\n\nEliminar tareas\n\n\nUna forma sencilla de detener una tarea es iniciarla\nc\u00f3mo condicional, y que la funci\u00f3n que le asignamos\nretorne False.\n\n\nOtra forma es simplemente capturar el retorno de\nla funci\u00f3n que ha creado la tarea y detenerla.\n\n\nPor ejemplo:\n\n\nuna_tarea = pilas.tareas.siempre(5, funcion)\n\n\n\n\ny luego, cuando queramos que la tarea finalice\ny no se vuelva a ejecutar, tendr\u00edamos que ejecutar\nuna sentencia como esta:\n\n\nuna_tarea.terminar()", 
            "title": "Manejo de tiempo con tareas"
        }, 
        {
            "location": "/tareas/#manejo-de-tiempo-con-tareas", 
            "text": "Una necesidad muy com\u00fan en los videojuegos\nes poder planificar tareas para ser ejecutadas\npor tiempo.  Por ejemplo, en un juego de naves podr\u00edamos\nquerer que aparezcan naves enemigas cada\ndos segundos.", 
            "title": "Manejo de tiempo con tareas"
        }, 
        {
            "location": "/tareas/#tareas", 
            "text": "Las tareas son acciones que elegimos ejecutar\nen un determinado momento.  Al momento de crear la tarea tenemos que\npensar \"en qu\u00e9 momento se tiene que ejecutar\nla tarea\", y dependiendo de lo que queramos,\ntenemos que escribir algo c\u00f3mo:  pilas.tareas.agregar(tiempo, funcion, parametros)  Por ejemplo, para hacer que un actor espere 5 segundos\nantes de emitir un mensaje:  mono = pilas.actores.Mono()\n\ndef emitir_mensaje():\n  mono.decir( Hola )\n\npilas.tareas.agregar(5, emitir_mensaje)    Hay tres tipos de creaciones de tareas:   tareas que se ejecutan una vez.  tareas que se ejecutan siempre.  tareas condicionales.   las tareas condicionales se ejecutar\u00e1n siempre y cuando\nla funci\u00f3n que las representa retorna True. Si la funci\u00f3n\nretorna False la tarea dejar\u00e1 de ejecutarse.", 
            "title": "Tareas"
        }, 
        {
            "location": "/tareas/#eliminar-tareas", 
            "text": "Una forma sencilla de detener una tarea es iniciarla\nc\u00f3mo condicional, y que la funci\u00f3n que le asignamos\nretorne False.  Otra forma es simplemente capturar el retorno de\nla funci\u00f3n que ha creado la tarea y detenerla.  Por ejemplo:  una_tarea = pilas.tareas.siempre(5, funcion)  y luego, cuando queramos que la tarea finalice\ny no se vuelva a ejecutar, tendr\u00edamos que ejecutar\nuna sentencia como esta:  una_tarea.terminar()", 
            "title": "Eliminar tareas"
        }, 
        {
            "location": "/interpolacion/", 
            "text": "Interpolaciones\n\n\nLas interpolaciones nos permiten lograr movimientos\nde los actores de manera sencilla.\n\n\nPor ejemplo, tradicionalmente si quisi\u00e9ramos cambiar\nposici\u00f3n de un actor en pantalla podemos usar estas\nsentencias:\n\n\nactor.x = 10\nactor.x = 20\nactor.x = 30\netc ...\n\n\n\nuna forma de lograr lo mismo con pilas\nes asignarle todos los valores en forma de lista:\n\n\nactor.x = range(10, 100, 10)\n\n\n\no lo que es lo mismo:\n\n\nactor.x = [10, 20, 30, 40, 50 ... etc.\n\n\n\nY a estas interpolaciones, tambi\u00e9n le puedes decir\ncuantos segundos puede demorar. Por ejemplo, para\ndar un giro completo de 360 grados en 10\nsegundos puedes hacer algo como:\n\n\nactor.rotacion = [360], 10\n\n\n\nde hecho, puede que te resulte mas conveniente\ntener mas control sobre la interpolaci\u00f3n, as\u00ed\nque puedes usar esta forma:\n\n\npilas.utils.interpolar(actor, 'x', 100)\n\n\n\ndonde el valor inicial ser\u00e1 la posici\u00f3n x del actor y el valor\nfinal ser\u00e1 \n100\n.\n\n\nLa funci\u00f3n \ninterpolar\n, como mencion\u00e9 antes, te da mas\ncontrol sobre la interpolaci\u00f3n, porque admite otros par\u00e1metros\nde ajuste como los siguientes:\n\n\n\n\nPor ejemplo, si queremos que un personaje d\u00e9 un giro\ncompleto de 360 grados en 10 segundos podemos\nhacer algo as\u00ed:\n\n\nactor.rotacion = 0\npilas.utils.interpolar(actor, 'rotacion', 360, duracion=10)\n\n\n\nGirando un actor\n\n\nEsta herramienta se puede aplicar a muchas situaciones distintas, por\nejemplo si queremos hacer girar un personaje\npodemos hacer algo como:\n\n\nactor.rotacion = 0\npilas.utils.interpolar(actor, 'rotacion', 360, duracion=5)\n\n\n\ncon lo que estar\u00edamos diciendo al personaje que d\u00e9 un\ngiro completo (de \n0\n a \n360\n grados) en \n5\n segundos.\n\n\nTambi\u00e9n existe un argumento \ndelay\n para demorar el\ninicio de la interpolaci\u00f3n.\n\n\nEscalando un actor\n\n\nDe manera similar a lo que hicimos anteriormente, podemos\naplicarla a la propiedad \nescala\n una nueva\ninterpolaci\u00f3n:\n\n\npilas.utils.interpolar(actor, 'escala', 2, duracion=5)\n\n\n\nesto duplicar\u00e1 el tama\u00f1o del actor en \n5\n segundos.\n\n\n\u00bfY mas simple?, bueno, como hicimos antes:\n\n\nactor.escala = [2]\n\n\n\nInterpolaciones en cadena\n\n\nSi queremos que una interpolaci\u00f3n pase por distintos\nvalores podemos hacer algo como esto:\n\n\nactor.x = [300, 0, 300], 3\n\n\n\nlo que llevar\u00e1 al actor de su posici\u00f3n \nx\n actual, a \n300\n,\nluego a \n0\n y por \u00faltimo de nuevo a \n300\n en un segundo.\n\n\nEn total, ha consumido 3 segundos por cada movimiento, es decir 9 segundos\nen total.", 
            "title": "Interpolaciones"
        }, 
        {
            "location": "/interpolacion/#interpolaciones", 
            "text": "Las interpolaciones nos permiten lograr movimientos\nde los actores de manera sencilla.  Por ejemplo, tradicionalmente si quisi\u00e9ramos cambiar\nposici\u00f3n de un actor en pantalla podemos usar estas\nsentencias:  actor.x = 10\nactor.x = 20\nactor.x = 30\netc ...  una forma de lograr lo mismo con pilas\nes asignarle todos los valores en forma de lista:  actor.x = range(10, 100, 10)  o lo que es lo mismo:  actor.x = [10, 20, 30, 40, 50 ... etc.  Y a estas interpolaciones, tambi\u00e9n le puedes decir\ncuantos segundos puede demorar. Por ejemplo, para\ndar un giro completo de 360 grados en 10\nsegundos puedes hacer algo como:  actor.rotacion = [360], 10  de hecho, puede que te resulte mas conveniente\ntener mas control sobre la interpolaci\u00f3n, as\u00ed\nque puedes usar esta forma:  pilas.utils.interpolar(actor, 'x', 100)  donde el valor inicial ser\u00e1 la posici\u00f3n x del actor y el valor\nfinal ser\u00e1  100 .  La funci\u00f3n  interpolar , como mencion\u00e9 antes, te da mas\ncontrol sobre la interpolaci\u00f3n, porque admite otros par\u00e1metros\nde ajuste como los siguientes:   Por ejemplo, si queremos que un personaje d\u00e9 un giro\ncompleto de 360 grados en 10 segundos podemos\nhacer algo as\u00ed:  actor.rotacion = 0\npilas.utils.interpolar(actor, 'rotacion', 360, duracion=10)", 
            "title": "Interpolaciones"
        }, 
        {
            "location": "/interpolacion/#girando-un-actor", 
            "text": "Esta herramienta se puede aplicar a muchas situaciones distintas, por\nejemplo si queremos hacer girar un personaje\npodemos hacer algo como:  actor.rotacion = 0\npilas.utils.interpolar(actor, 'rotacion', 360, duracion=5)  con lo que estar\u00edamos diciendo al personaje que d\u00e9 un\ngiro completo (de  0  a  360  grados) en  5  segundos.  Tambi\u00e9n existe un argumento  delay  para demorar el\ninicio de la interpolaci\u00f3n.", 
            "title": "Girando un actor"
        }, 
        {
            "location": "/interpolacion/#escalando-un-actor", 
            "text": "De manera similar a lo que hicimos anteriormente, podemos\naplicarla a la propiedad  escala  una nueva\ninterpolaci\u00f3n:  pilas.utils.interpolar(actor, 'escala', 2, duracion=5)  esto duplicar\u00e1 el tama\u00f1o del actor en  5  segundos.  \u00bfY mas simple?, bueno, como hicimos antes:  actor.escala = [2]", 
            "title": "Escalando un actor"
        }, 
        {
            "location": "/interpolacion/#interpolaciones-en-cadena", 
            "text": "Si queremos que una interpolaci\u00f3n pase por distintos\nvalores podemos hacer algo como esto:  actor.x = [300, 0, 300], 3  lo que llevar\u00e1 al actor de su posici\u00f3n  x  actual, a  300 ,\nluego a  0  y por \u00faltimo de nuevo a  300  en un segundo.  En total, ha consumido 3 segundos por cada movimiento, es decir 9 segundos\nen total.", 
            "title": "Interpolaciones en cadena"
        }, 
        {
            "location": "/controlando_la_pantalla/", 
            "text": "Controlando la pantalla\n\n\nPara posicionar actores en el escenario\nprincipal es importante conocer las\npropiedades de la pantalla.\n\n\nLa pantalla es lo que contiene la ventana\nprincipal de pilas, y que puede observar\nuna porci\u00f3n del escenario y a un grupo de actores.\n\n\nModo depuraci\u00f3n\n\n\nEl modo depuraci\u00f3n te permite ver informaci\u00f3n\nde utilidad cuando est\u00e1s desarrollando un juego\no simplemente buscando alg\u00fan error.\n\n\nPara iniciar el modo depuraci\u00f3n pulsa \nF12\n. En\nla ventana principal aparecer\u00e1n varios textos\nindicando el rendimiento del juego, las coordenadas\nde posici\u00f3n de los actores y la posici\u00f3n del\nmouse.\n\n\nEl centro de la ventana es, inicialmente, el\npunto \n(0, 0)\n. Este modelo de coordenadas\nes el cartesiano, y lo hemos elegido porque es\nel que mejor se adapta a los conocimientos\ngeom\u00e9tricos que se ense\u00f1an en las escuelas.\n\n\nOrden de impresi\u00f3n: atributo z\n\n\nCuando tienes varios actores en pantalla notaras\nque a veces unos aparecen sobre otros.\n\n\nPara cambiar este comportamiento tienes que modificar\nel atributo \nz\n de cada actor.\n\n\nLos valores altos de \nz\n indican mucha distancia\nentre el observador y el escenario. Mientras que\nvalores peque\u00f1os \nz\n har\u00e1n que los actores tapen\na los dem\u00e1s (porque aparecer\u00e1n mas cerca del\nusuario).\n\n\nEste es un ejemplo de dos configuraciones distintas\nde atributos \nz\n:\n\n\n\n\nTen en cuenta que inicialmente todos los actores\ntienen un atributo \nz=0\n.\n\n\nAtributos de posici\u00f3n\n\n\nTodos los actores tienen atributos c\u00f3mo:\n\n\n\n\nx\n\n\ny\n\n\n\n\nque sirven para cambiar la posici\u00f3n del actor dentro de la escena.\n\n\nTambi\u00e9n encontrar\u00e1s atributos que permiten hacer lo mismo, pero\ntomando como referencia alguno de los bordes del\nactor. Por ejemplo:\n\n\n\n\nizquierda\n\n\nderecha\n\n\narriba\n\n\nabajo\n\n\n\n\nTen en cuenta que estos valores indicar\u00e1n la posici\u00f3n del\nactor dentro del escenario, no de la ventana. Esto significa que\nsi cambias la posici\u00f3n de la c\u00e1mara los actores seguir\u00e1n estando\nen la misma posici\u00f3n pero se ver\u00e1n un poco corridos.", 
            "title": "Controlando la pantalla"
        }, 
        {
            "location": "/controlando_la_pantalla/#controlando-la-pantalla", 
            "text": "Para posicionar actores en el escenario\nprincipal es importante conocer las\npropiedades de la pantalla.  La pantalla es lo que contiene la ventana\nprincipal de pilas, y que puede observar\nuna porci\u00f3n del escenario y a un grupo de actores.", 
            "title": "Controlando la pantalla"
        }, 
        {
            "location": "/controlando_la_pantalla/#modo-depuracion", 
            "text": "El modo depuraci\u00f3n te permite ver informaci\u00f3n\nde utilidad cuando est\u00e1s desarrollando un juego\no simplemente buscando alg\u00fan error.  Para iniciar el modo depuraci\u00f3n pulsa  F12 . En\nla ventana principal aparecer\u00e1n varios textos\nindicando el rendimiento del juego, las coordenadas\nde posici\u00f3n de los actores y la posici\u00f3n del\nmouse.  El centro de la ventana es, inicialmente, el\npunto  (0, 0) . Este modelo de coordenadas\nes el cartesiano, y lo hemos elegido porque es\nel que mejor se adapta a los conocimientos\ngeom\u00e9tricos que se ense\u00f1an en las escuelas.", 
            "title": "Modo depuraci\u00f3n"
        }, 
        {
            "location": "/controlando_la_pantalla/#orden-de-impresion-atributo-z", 
            "text": "Cuando tienes varios actores en pantalla notaras\nque a veces unos aparecen sobre otros.  Para cambiar este comportamiento tienes que modificar\nel atributo  z  de cada actor.  Los valores altos de  z  indican mucha distancia\nentre el observador y el escenario. Mientras que\nvalores peque\u00f1os  z  har\u00e1n que los actores tapen\na los dem\u00e1s (porque aparecer\u00e1n mas cerca del\nusuario).  Este es un ejemplo de dos configuraciones distintas\nde atributos  z :   Ten en cuenta que inicialmente todos los actores\ntienen un atributo  z=0 .", 
            "title": "Orden de impresi\u00f3n: atributo z"
        }, 
        {
            "location": "/controlando_la_pantalla/#atributos-de-posicion", 
            "text": "Todos los actores tienen atributos c\u00f3mo:   x  y   que sirven para cambiar la posici\u00f3n del actor dentro de la escena.  Tambi\u00e9n encontrar\u00e1s atributos que permiten hacer lo mismo, pero\ntomando como referencia alguno de los bordes del\nactor. Por ejemplo:   izquierda  derecha  arriba  abajo   Ten en cuenta que estos valores indicar\u00e1n la posici\u00f3n del\nactor dentro del escenario, no de la ventana. Esto significa que\nsi cambias la posici\u00f3n de la c\u00e1mara los actores seguir\u00e1n estando\nen la misma posici\u00f3n pero se ver\u00e1n un poco corridos.", 
            "title": "Atributos de posici\u00f3n"
        }, 
        {
            "location": "/comportamientos/", 
            "text": "Comportamientos\n\n\nEn el desarrollo de videojuegos es conveniente\ntener una forma de indicarle a los actores\nuna rutina o tarea para que la realicen.\n\n\nEn pilas usamos el concepto de comportamiento. Un\ncomportamiento es un objeto que simboliza una\nacci\u00f3n a realizar por un actor.\n\n\nLa utilidad de usar componentes es que puedes\nasociarlos y intercambiarlos libremente para\nlograr efectos \u00fatiles.\n\n\nPor ejemplo: un guardia de un juego de acci\u00f3n puede ir de\nun lado a otro en un pasillo:\n\n\n\n\ncaminar hacia la izquierda hasta el fin del pasillo.\n\n\ndar una vuelta completa.\n\n\ncaminar hacia la derecha hasta el fin del pasillo.\n\n\ndar una vuelta completa.\n\n\ny repetir ...\n\n\n\n\nEn este caso hay 4 comportamientos, y queda en nuestro\ncontrol si queremos que luego de los 4 comportamientos\ncomience nuevamente.\n\n\nUn ejemplo, ir de un lado a otro\n\n\nVeamos un ejemplo sencillo, vamos a crear un actor Mono\ny decirle que se mueva de izquierda a derecha una\nsola vez:\n\n\nimport pilasengine\n\npilas = pilasengine.iniciar()\nmono = pilas.actores.Mono()\n\npasos = 200\n\nmono.hacer(\"Avanzar\", pasos)\n\n# Dar la vuelta.\nmono.rotacion = [180]\n\nmono.hacer(\"Avanzar\", pasos)\n\n# Solo necesario al ejecutar en scripts.\npilas.ejecutar()\n\n\n\nListado de todos los Comportamientos existentes\n\n\n\n\n\n\n\n\nEvento\n\n\nParametros\n\n\n\n\n\n\n\n\n\n\nProyectil\n\n\nvelocidad_maxima, aceleracion, angulo_de_movimiento, gravedad\n\n\n\n\n\n\nSaltar\n\n\nvelocidad_inicial, cuando_termina\n\n\n\n\n\n\nAvanzar\n\n\npasos, velocidad\n\n\n\n\n\n\nGirar\n\n\ndelta, velocidad\n\n\n\n\n\n\nOrbitar\n\n\nx, y, radio, velocidad, direccion\n\n\n\n\n\n\nOrbitarSobreActor\n\n\nactor, radio, velocidad, direccion\n\n\n\n\n\n\n\n\nComportamientos personalizados\n\n\nPara crear un comportamiento personalizado necesitamos crear una\nclase que herede de \npilasengine.comportamientos.Comportamiento\n, \nluego implementar los m\u00e9todos \niniciar\n/\nejecutar\n y por \u00faltimo\nvincular el comportamiento.\n\n\nclass Desaparecer(pilasengine.comportamientos.Comportamiento):\n\n    def iniciar(self, receptor):\n        self.receptor = receptor\n\n    def actualizar(self):\n        if self.receptor.transparencia \n 100:\n            self.receptor.transparencia += 1\n        else:\n            # Con retornar True le indicamos a pilas que este\n            # comportamiento termin\u00f3 y tiene que pasar al siguiente.\n            return True\n\nmono = pilas.actores.Mono()\npilas.comportamientos.vincular(Desaparecer)\nmono.hacer(\"Desaparecer\")\n\n\n\nEncadenando comportamientos\n\n\nLos comportamientos de los actores est\u00e1n dise\u00f1ados para encadenarse, y que\nse puedan reproducir uno detr\u00e1s de otro. Por ejemplo:\n\n\nmono = pilas.actores.Mono()\nmono.hacer(\"Saltar\")\nmono.hacer(\"Avanzar\", 200)\nmono.hacer(\"Saltar\")", 
            "title": "Comportamientos"
        }, 
        {
            "location": "/comportamientos/#comportamientos", 
            "text": "En el desarrollo de videojuegos es conveniente\ntener una forma de indicarle a los actores\nuna rutina o tarea para que la realicen.  En pilas usamos el concepto de comportamiento. Un\ncomportamiento es un objeto que simboliza una\nacci\u00f3n a realizar por un actor.  La utilidad de usar componentes es que puedes\nasociarlos y intercambiarlos libremente para\nlograr efectos \u00fatiles.  Por ejemplo: un guardia de un juego de acci\u00f3n puede ir de\nun lado a otro en un pasillo:   caminar hacia la izquierda hasta el fin del pasillo.  dar una vuelta completa.  caminar hacia la derecha hasta el fin del pasillo.  dar una vuelta completa.  y repetir ...   En este caso hay 4 comportamientos, y queda en nuestro\ncontrol si queremos que luego de los 4 comportamientos\ncomience nuevamente.", 
            "title": "Comportamientos"
        }, 
        {
            "location": "/comportamientos/#un-ejemplo-ir-de-un-lado-a-otro", 
            "text": "Veamos un ejemplo sencillo, vamos a crear un actor Mono\ny decirle que se mueva de izquierda a derecha una\nsola vez:  import pilasengine\n\npilas = pilasengine.iniciar()\nmono = pilas.actores.Mono()\n\npasos = 200\n\nmono.hacer(\"Avanzar\", pasos)\n\n# Dar la vuelta.\nmono.rotacion = [180]\n\nmono.hacer(\"Avanzar\", pasos)\n\n# Solo necesario al ejecutar en scripts.\npilas.ejecutar()", 
            "title": "Un ejemplo, ir de un lado a otro"
        }, 
        {
            "location": "/comportamientos/#listado-de-todos-los-comportamientos-existentes", 
            "text": "Evento  Parametros      Proyectil  velocidad_maxima, aceleracion, angulo_de_movimiento, gravedad    Saltar  velocidad_inicial, cuando_termina    Avanzar  pasos, velocidad    Girar  delta, velocidad    Orbitar  x, y, radio, velocidad, direccion    OrbitarSobreActor  actor, radio, velocidad, direccion", 
            "title": "Listado de todos los Comportamientos existentes"
        }, 
        {
            "location": "/comportamientos/#comportamientos-personalizados", 
            "text": "Para crear un comportamiento personalizado necesitamos crear una\nclase que herede de  pilasengine.comportamientos.Comportamiento , \nluego implementar los m\u00e9todos  iniciar / ejecutar  y por \u00faltimo\nvincular el comportamiento.  class Desaparecer(pilasengine.comportamientos.Comportamiento):\n\n    def iniciar(self, receptor):\n        self.receptor = receptor\n\n    def actualizar(self):\n        if self.receptor.transparencia   100:\n            self.receptor.transparencia += 1\n        else:\n            # Con retornar True le indicamos a pilas que este\n            # comportamiento termin\u00f3 y tiene que pasar al siguiente.\n            return True\n\nmono = pilas.actores.Mono()\npilas.comportamientos.vincular(Desaparecer)\nmono.hacer(\"Desaparecer\")", 
            "title": "Comportamientos personalizados"
        }, 
        {
            "location": "/comportamientos/#encadenando-comportamientos", 
            "text": "Los comportamientos de los actores est\u00e1n dise\u00f1ados para encadenarse, y que\nse puedan reproducir uno detr\u00e1s de otro. Por ejemplo:  mono = pilas.actores.Mono()\nmono.hacer(\"Saltar\")\nmono.hacer(\"Avanzar\", 200)\nmono.hacer(\"Saltar\")", 
            "title": "Encadenando comportamientos"
        }, 
        {
            "location": "/escenas/", 
            "text": "Escenas\n\n\nLas escenas te permiten dividir el juego en partes\nreconocibles y que interact\u00faan de manera diferente\ncon el usuario.\n\n\nUn juego t\u00edpico tendr\u00e1 al menos una escena como\nel men\u00fa principal, una presentanci\u00f3n y una\npantalla de juego.\n\n\n\n\nCosas a tener en cuenta\n\n\nHay algunas cosas a tener en cuenta\na la hora de manejar escenas, porque\nsimplifican mucho el trabajo posterior:\n\n\n\n\nLa escena actual siempre est\u00e1 se\u00f1alada por el atributo \npilas.escena_actual()\n.\n\n\nSolo puede existir una escena activa a la vez.\n\n\n\n\nLa escena Normal\n\n\nCuando iniciamos pilas por primera vez se crear\u00e1\nuna escena llamada \nNormal\n. Esta escena no\ntiene un comportamiento muy elaborado, simplemente\nimprime toda la pantalla de azul para que\npodamos colocar actores sobre ella y veamos una\nescena limpia.\n\n\nCambiando el fondo de las escenas\n\n\nPara hacer una peque\u00f1a prueba sobre una\nescena, podr\u00edas ejecutar la siguiente sentencia\nde c\u00f3digo:\n\n\npilas.fondos.Volley()\n\n\n\nEsto le dar\u00e1 a tu escena una vista\nmas agradable, porque carga un fondo de\npantalla colorido y mas divertido:\n\n\n\n\no podr\u00edas usar un fondo de atardecer:\n\n\npilas.fondos.Tarde()\n\n\n\n\n\nC\u00f3mo crear nuevas escenas\n\n\nImagina que tienes un juego con dos pantallas, una\nque simplemente dice \"bienvenido\" y  otra con\nun personaje para mover.\n\n\nClaramente tendr\u00edamos que hacer dos escenas, e iniciar\nnuestro juego creando la escena principal.\n\n\nLa primer escena tendr\u00edamos que representarla\ncon una clase, que herede de la escena Normal\nas\u00ed:\n\n\nclass PantallaBienvenida(pilasengine.escenas.Escena):\n\n    def iniciar(self):\n        self.fondo = self.pilas.fondos.Volley()\n        pass\n\n    def ejecutar(self):\n        pass\n\n\n\n\nAhora, para poner en funcionamiento esta escena\nsimplemente tienes que decirle a pilas que esta escena es la activa:\n\n\npilas.escenas.vincular(PantallaBienvenida)\npilas.escenas.PantallaBienvenida()\n\n\n\nEsto eliminar\u00e1 las escenas almacenadas y se colocar\u00e1 como la escena\nactual y activa:\n\n\n\n\nAhora, si quieres salir de la escena, simplemente tendr\u00edas\nque cargar una escena nueva, por ejemplo:\n\n\npilas.escenas.Normal()\n\n\n\nEs decir, en el momento que creamos la escena aparecer\u00e1 autom\u00e1ticamente.\n\n\nEscenas con argumentos\n\n\nSi quieres crear una escena pas\u00e1ndole un argumento de esta forma:\n\n\npilas.escenas.vincular(PantallaBienvenida)\npilas.escenas.PantallaBienvenida(\"Mi mensaje personalizado\")\n\n\n\nLo que necesitas hacer es especificar ese nuevo argumento en el m\u00e9todo\n\niniciar\n as\u00ed:\n\n\nclass PantallaBienvenida(pilasengine.escenas.Escena):\n\n    def iniciar(self, mensaje):\n        pilas.fondos.Pasto()\n        self.texto = pilas.actores.Texto(mensaje)\n\n    def actualizar(self):\n        self.texto.rotacion += 1\n\n\n\n\npilas, en este caso, va a tomar el argumento \n\"Mi mensaje personalizado\"\n y lo\nva a enviar al m\u00e9todo \niniciar\n con el nombre \nmensaje\n.", 
            "title": "Escenas"
        }, 
        {
            "location": "/escenas/#escenas", 
            "text": "Las escenas te permiten dividir el juego en partes\nreconocibles y que interact\u00faan de manera diferente\ncon el usuario.  Un juego t\u00edpico tendr\u00e1 al menos una escena como\nel men\u00fa principal, una presentanci\u00f3n y una\npantalla de juego.", 
            "title": "Escenas"
        }, 
        {
            "location": "/escenas/#cosas-a-tener-en-cuenta", 
            "text": "Hay algunas cosas a tener en cuenta\na la hora de manejar escenas, porque\nsimplifican mucho el trabajo posterior:   La escena actual siempre est\u00e1 se\u00f1alada por el atributo  pilas.escena_actual() .  Solo puede existir una escena activa a la vez.", 
            "title": "Cosas a tener en cuenta"
        }, 
        {
            "location": "/escenas/#la-escena-normal", 
            "text": "Cuando iniciamos pilas por primera vez se crear\u00e1\nuna escena llamada  Normal . Esta escena no\ntiene un comportamiento muy elaborado, simplemente\nimprime toda la pantalla de azul para que\npodamos colocar actores sobre ella y veamos una\nescena limpia.", 
            "title": "La escena Normal"
        }, 
        {
            "location": "/escenas/#cambiando-el-fondo-de-las-escenas", 
            "text": "Para hacer una peque\u00f1a prueba sobre una\nescena, podr\u00edas ejecutar la siguiente sentencia\nde c\u00f3digo:  pilas.fondos.Volley()  Esto le dar\u00e1 a tu escena una vista\nmas agradable, porque carga un fondo de\npantalla colorido y mas divertido:   o podr\u00edas usar un fondo de atardecer:  pilas.fondos.Tarde()", 
            "title": "Cambiando el fondo de las escenas"
        }, 
        {
            "location": "/escenas/#como-crear-nuevas-escenas", 
            "text": "Imagina que tienes un juego con dos pantallas, una\nque simplemente dice \"bienvenido\" y  otra con\nun personaje para mover.  Claramente tendr\u00edamos que hacer dos escenas, e iniciar\nnuestro juego creando la escena principal.  La primer escena tendr\u00edamos que representarla\ncon una clase, que herede de la escena Normal\nas\u00ed:  class PantallaBienvenida(pilasengine.escenas.Escena):\n\n    def iniciar(self):\n        self.fondo = self.pilas.fondos.Volley()\n        pass\n\n    def ejecutar(self):\n        pass  Ahora, para poner en funcionamiento esta escena\nsimplemente tienes que decirle a pilas que esta escena es la activa:  pilas.escenas.vincular(PantallaBienvenida)\npilas.escenas.PantallaBienvenida()  Esto eliminar\u00e1 las escenas almacenadas y se colocar\u00e1 como la escena\nactual y activa:   Ahora, si quieres salir de la escena, simplemente tendr\u00edas\nque cargar una escena nueva, por ejemplo:  pilas.escenas.Normal()  Es decir, en el momento que creamos la escena aparecer\u00e1 autom\u00e1ticamente.", 
            "title": "C\u00f3mo crear nuevas escenas"
        }, 
        {
            "location": "/escenas/#escenas-con-argumentos", 
            "text": "Si quieres crear una escena pas\u00e1ndole un argumento de esta forma:  pilas.escenas.vincular(PantallaBienvenida)\npilas.escenas.PantallaBienvenida(\"Mi mensaje personalizado\")  Lo que necesitas hacer es especificar ese nuevo argumento en el m\u00e9todo iniciar  as\u00ed:  class PantallaBienvenida(pilasengine.escenas.Escena):\n\n    def iniciar(self, mensaje):\n        pilas.fondos.Pasto()\n        self.texto = pilas.actores.Texto(mensaje)\n\n    def actualizar(self):\n        self.texto.rotacion += 1  pilas, en este caso, va a tomar el argumento  \"Mi mensaje personalizado\"  y lo\nva a enviar al m\u00e9todo  iniciar  con el nombre  mensaje .", 
            "title": "Escenas con argumentos"
        }, 
        {
            "location": "/interfaz/", 
            "text": "Interfaz de usuario\n\n\nLos componentes del m\u00f3dulo \npilas.interfaz\n permiten crear botones, listas,\ndeslizadores y otros tipos de componentes visuales, todos orientados\na construir interfaces de usuario traducionales.\n\n\nClase: Boton\n\n\nPara crear un bot\u00f3n podemos instalar la clase \nBoton\n especificando\nun texto.\n\n\nboton = pilas.interfaz.Boton(\nSaludar\n)\n\n\n\n\ny casi siempre vas a querer asignarle alguna acci\u00f3n cuando se hace\nclick sobre \u00e9l, para eso necesit\u00e1s una funci\u00f3n y conectarla:\n\n\ndef saludar():\n  boton.decir(\nHola !!!\n)\n\nboton.conectar(saludar)\n\n\n\n\n\n\nTen en cuenta que todos los objetos creados siguen siendo actores, as\u00ed\nque se pueden manipular como vimos antes: escalar, rotar, moverse etc...\n\n\nPropiedades\n\n\n\n\ntexto\n\n\nicono\n\n\n\n\nM\u00e9todos\n\n\n\n\nconectar(funcion)\n - Conecta una funci\u00f3n para responder al click de mouse.\n\n\nocultar()\n\n\nmostrar()\n\n\ndeshabilitar()\n\n\nhabilitar()\n\n\n\n\nEjemplo de integraci\u00f3n\n\n\nY para a\u00f1adir una acci\u00f3n o respuesta al componente, podemos crear una\nfunci\u00f3n y luego vincularla con el evento \nclick\n. Este ejemplo construye\nun bot\u00f3n y realiza un movimiento cada vez que se hace click sobre \u00e9l:\n\n\nb = pilas.interfaz.Boton(u\nRealizar animaci\u00f3n\n)\n\ndef moverse():\n    b.escala_x = [  2, 0.8, 1], 0.15\n    b.escala_y = [0.8, 2,   1], 0.1\n    d = pilas.azar(-50, 50)\n    b.rotacion = [d, 1], 0.1\n\nb.conectar(moverse)\n\n\n\n\nEl resultado en pantalla ser\u00e1 as\u00ed:\n\n\n\n\nClase: Deslizador\n\n\nEl deslizador es \u00fatil para que el usuario pueda seleccionar\nun valor intermedio entre dos n\u00fameros, por ejemplo entre 0 y 1, 0 y\n100 etc.\n\n\nUn ejemplo t\u00edpico de este componente puedes encontrarlo\nen las preferencias de audio de alg\u00fan programa de sonido, los\ndeslizadores te permiten regular el grado de volumen.\n\n\nEsta es una imagen del ejemplo \ndeslizador.py\n que est\u00e1\nen el directorio \nejemplos\n. Tiene tres deslizadores, y\nel usuario puede regular cualquiera de los tres para ver\nlos cambios en el actor:\n\n\n\n\nPara construir un deslizador y asociarlo a una funci\u00f3n\npuedes escribir algo como esto:\n\n\ndef cuando_cambia(valor):\n    print(\nEl deslizador tiene grado:\n, valor)\n\ndeslizador = pilas.interfaz.Deslizador()\ndeslizador.conectar(cuando_cambia)\n\n\n\n\nEntonces, a medida que muevas el deslizador se imprimir\u00e1n\nen pantalla valores del 0 al 1, por ejemplo 0.25, 0.52777 etc...\n\n\nSi quieres cambiar los valores iniciales y finales de la\nescala de valores, lo mas sencillo es multiplicar el argumento\n\nvalor\n de la funci\u00f3n. Por ejemplo, si quieres valores entre\n0 y 100:\n\n\ndef cuando_cambia(valor):\n    valor_entre_cero_y_cien = valor * 100\n\n\n\n\nPropiedades\n\n\n\n\nprogreso\n - Almacen un valor entre 0 y 100\n\n\n\n\nM\u00e9todos\n\n\n\n\nconectar(funcion)\n - Conecta una funci\u00f3n que se llamar\u00e1 cada vez que muevas el deslizador.\n\n\n\n\nClase: Selector\n\n\nEl selector te permite seleccionar una opci\u00f3n con\ndos valores: habilitado, deshabilitado.\n\n\nSe puede usar para opciones c\u00f3mo habilitar o deshabilitar\nel modo pantalla completa o algo as\u00ed.\n\n\nPara usarlo, se tiene que crear un objeto de la\nclase \nSelector\n y un texto a mostrar:\n\n\nselector = pilas.interfaz.Selector(\nHabilitar pantalla completa.\n)\n\n\n\n\nY luego, se puede consultar el valor del selector mediante el\natributo \nseleccionado\n:\n\n\nif selector.seleccionado:\n    print(\nEl selector esta seleccionado.\n)\nelse:\n    print(\nEl selector no esta seleccionado.\n)\n\n\n\n\naunque en lugar de consultar la variable, es mucho mejor asociarle\nuna funci\u00f3n para que el selector la llame solamente cuando el\nselector cambia de estado (seleccionado/deseleccionado):\n\n\ndef cuando_el_selector_cambia(estado):\n    print(\nEl selector ahora esta en estado:\n, estado)\n\nselector.definir_accion(cuando_el_selector_cambia)\n\n\n\n\nEjemplo de integraci\u00f3n\n\n\nPara mostrar el componente en funcionamiento tenemos un peque\u00f1o ejemplo: un\nselector que nos permite alternar el fondo de la escena:\n\n\nselector = pilas.interfaz.Selector(\nDefinir fondo naranja\n)\n\ndef cambiar_el_fondo(ha_seleccionado):\n    if ha_seleccionado:\n        pilas.fondos.Tarde()\n    else:\n        pilas.fondos.Blanco()\n\nselector.conectar(cambiar_el_fondo)\n\n\n\n\nEl resultado en pantalla ser\u00e1 as\u00ed:\n\n\n\n\nPropiedades\n\n\n\n\ntexto\n - Etiqueta que mostrar\u00e1 el deslizador\n\n\nseleccionado\n - Almacena True o False, indicando el estado de selecci\u00f3n.\n\n\n\n\nM\u00e9todos\n\n\n\n\nconectar(funcion)\n - Conecta una funci\u00f3n que se llamar\u00e1 cada vez que muevas el deslizador.\n\n\nalternar_seleccion()\n\n\nseleccionar()\n\n\ndeseleccionar()\n\n\n\n\nClase: IngresoDeTexto\n\n\nSi quieres solicitar datos, como el nombre del\nusuario, puedes usar el objeto \nIngresoDeTexto\n. Ya que\nmuestra una caja y un peque\u00f1o cursor para\ningresar texto:\n\n\n\n\nPara usar este componente tienes que crearlo y luego leer o escribir el\natributo \ntexto\n, que contiene la cadena de texto de la caja:\n\n\nentrada = pilas.interfaz.IngresoDeTexto()\nentrada.texto = \nTexto inicial\n\n\n\n\n\nInicialmente, el objeto IngresoDeTexto toma un tama\u00f1o y apariencia predeterminado. Pero esto se puede cambiar f\u00e1cilmente usando argumentos al momento de crear el componente.\n\n\nPor ejemplo, podr\u00edamos enviarle c\u00f3mo argumento un tama\u00f1o mas peque\u00f1o y un \u00edcono de b\u00fasqueda:\n\n\nentrada = pilas.interfaz.IngresoDeTexto(ancho=100, icono='iconos/lupa.png')\nu otro \u00edcono:\n\n\nentrada = pilas.interfaz.IngresoDeTexto(ancho=100, icono='iconos/ok.png')\nLa caja tambi\u00e9n tiene otros m\u00e9todos para permitir o prohibir el ingreso de datos.\n\n\nPor ejemplo, podr\u00edamos decirle a la caja que solo permita el ingreso de n\u00fameros,\nletras, o poner un l\u00edmite de cantidad de caracteres. Los m\u00e9todos\nque te permite limitar el ingreso son \nsolo_numeros()\n y \nsolo_letras()\n, y el\nl\u00edmite de caracteres est\u00e1 en el atributo \nlimite_de_caracteres\n:\n\n\nPropiedades\n\n\n\n\ntexto\n\n\nicono\n\n\nlimite_de_caracteres\n\n\n\n\nM\u00e9todos\n\n\n\n\ncualquier_caracter()\n\n\nsolo_numeros()\n\n\nsolo_letras()\n\n\n\n\nClase: ListaSeleccion\n\n\nLa lista de selecci\u00f3n se utiliza para mostrar al usuario una lista de cadenas, y permitirle seleccionarlas con el mouse.\n\n\nPara crear un lista de selecci\u00f3n, se tiene que crear una lista de cadenas y declarar una funci\u00f3n para que sea llamada cuando se termina de seleccionar.\n\n\nPor ejemplo, el siguiente c\u00f3digo muestra una lista e imprime por consola cuando el usuario selecciona con el click del mouse:\n\n\ndef cuando_selecciona(opcion):\n    print(\nHa seleccionado la opcion:\n, opcion)\n\nconsulta = pilas.interfaz.ListaSeleccion(['Uno', 'Dos', 'Tres'], cuando_selecciona)\n\n\n\n\nEjemplo de integraci\u00f3n\n\n\nPara mostrar el componente en funcionamiento, hacemos un lista de\ntres opciones, y le conectamos una funci\u00f3n para avisar la opci\u00f3n\nque selecciona el usuario:\n\n\npilas.fondos.Pasto()\n\ndef cuando_selecciona(opcion_seleccionada):\n    pilas.avisar(\nHa seleccionado la opcion: \n + opcion_seleccionada)\n\nopciones = pilas.interfaz.ListaSeleccion(['hola', 'opcion', 'tres'], cuando_selecciona)\n\n\n\n\nDeber\u00edas ver en pantalla lo siguiente:", 
            "title": "Interfaz de usuario"
        }, 
        {
            "location": "/interfaz/#interfaz-de-usuario", 
            "text": "Los componentes del m\u00f3dulo  pilas.interfaz  permiten crear botones, listas,\ndeslizadores y otros tipos de componentes visuales, todos orientados\na construir interfaces de usuario traducionales.", 
            "title": "Interfaz de usuario"
        }, 
        {
            "location": "/interfaz/#clase-boton", 
            "text": "Para crear un bot\u00f3n podemos instalar la clase  Boton  especificando\nun texto.  boton = pilas.interfaz.Boton( Saludar )  y casi siempre vas a querer asignarle alguna acci\u00f3n cuando se hace\nclick sobre \u00e9l, para eso necesit\u00e1s una funci\u00f3n y conectarla:  def saludar():\n  boton.decir( Hola !!! )\n\nboton.conectar(saludar)   Ten en cuenta que todos los objetos creados siguen siendo actores, as\u00ed\nque se pueden manipular como vimos antes: escalar, rotar, moverse etc...", 
            "title": "Clase: Boton"
        }, 
        {
            "location": "/interfaz/#propiedades", 
            "text": "texto  icono", 
            "title": "Propiedades"
        }, 
        {
            "location": "/interfaz/#metodos", 
            "text": "conectar(funcion)  - Conecta una funci\u00f3n para responder al click de mouse.  ocultar()  mostrar()  deshabilitar()  habilitar()", 
            "title": "M\u00e9todos"
        }, 
        {
            "location": "/interfaz/#ejemplo-de-integracion", 
            "text": "Y para a\u00f1adir una acci\u00f3n o respuesta al componente, podemos crear una\nfunci\u00f3n y luego vincularla con el evento  click . Este ejemplo construye\nun bot\u00f3n y realiza un movimiento cada vez que se hace click sobre \u00e9l:  b = pilas.interfaz.Boton(u Realizar animaci\u00f3n )\n\ndef moverse():\n    b.escala_x = [  2, 0.8, 1], 0.15\n    b.escala_y = [0.8, 2,   1], 0.1\n    d = pilas.azar(-50, 50)\n    b.rotacion = [d, 1], 0.1\n\nb.conectar(moverse)  El resultado en pantalla ser\u00e1 as\u00ed:", 
            "title": "Ejemplo de integraci\u00f3n"
        }, 
        {
            "location": "/interfaz/#clase-deslizador", 
            "text": "El deslizador es \u00fatil para que el usuario pueda seleccionar\nun valor intermedio entre dos n\u00fameros, por ejemplo entre 0 y 1, 0 y\n100 etc.  Un ejemplo t\u00edpico de este componente puedes encontrarlo\nen las preferencias de audio de alg\u00fan programa de sonido, los\ndeslizadores te permiten regular el grado de volumen.  Esta es una imagen del ejemplo  deslizador.py  que est\u00e1\nen el directorio  ejemplos . Tiene tres deslizadores, y\nel usuario puede regular cualquiera de los tres para ver\nlos cambios en el actor:   Para construir un deslizador y asociarlo a una funci\u00f3n\npuedes escribir algo como esto:  def cuando_cambia(valor):\n    print( El deslizador tiene grado: , valor)\n\ndeslizador = pilas.interfaz.Deslizador()\ndeslizador.conectar(cuando_cambia)  Entonces, a medida que muevas el deslizador se imprimir\u00e1n\nen pantalla valores del 0 al 1, por ejemplo 0.25, 0.52777 etc...  Si quieres cambiar los valores iniciales y finales de la\nescala de valores, lo mas sencillo es multiplicar el argumento valor  de la funci\u00f3n. Por ejemplo, si quieres valores entre\n0 y 100:  def cuando_cambia(valor):\n    valor_entre_cero_y_cien = valor * 100", 
            "title": "Clase: Deslizador"
        }, 
        {
            "location": "/interfaz/#propiedades_1", 
            "text": "progreso  - Almacen un valor entre 0 y 100", 
            "title": "Propiedades"
        }, 
        {
            "location": "/interfaz/#metodos_1", 
            "text": "conectar(funcion)  - Conecta una funci\u00f3n que se llamar\u00e1 cada vez que muevas el deslizador.", 
            "title": "M\u00e9todos"
        }, 
        {
            "location": "/interfaz/#clase-selector", 
            "text": "El selector te permite seleccionar una opci\u00f3n con\ndos valores: habilitado, deshabilitado.  Se puede usar para opciones c\u00f3mo habilitar o deshabilitar\nel modo pantalla completa o algo as\u00ed.  Para usarlo, se tiene que crear un objeto de la\nclase  Selector  y un texto a mostrar:  selector = pilas.interfaz.Selector( Habilitar pantalla completa. )  Y luego, se puede consultar el valor del selector mediante el\natributo  seleccionado :  if selector.seleccionado:\n    print( El selector esta seleccionado. )\nelse:\n    print( El selector no esta seleccionado. )  aunque en lugar de consultar la variable, es mucho mejor asociarle\nuna funci\u00f3n para que el selector la llame solamente cuando el\nselector cambia de estado (seleccionado/deseleccionado):  def cuando_el_selector_cambia(estado):\n    print( El selector ahora esta en estado: , estado)\n\nselector.definir_accion(cuando_el_selector_cambia)", 
            "title": "Clase: Selector"
        }, 
        {
            "location": "/interfaz/#ejemplo-de-integracion_1", 
            "text": "Para mostrar el componente en funcionamiento tenemos un peque\u00f1o ejemplo: un\nselector que nos permite alternar el fondo de la escena:  selector = pilas.interfaz.Selector( Definir fondo naranja )\n\ndef cambiar_el_fondo(ha_seleccionado):\n    if ha_seleccionado:\n        pilas.fondos.Tarde()\n    else:\n        pilas.fondos.Blanco()\n\nselector.conectar(cambiar_el_fondo)  El resultado en pantalla ser\u00e1 as\u00ed:", 
            "title": "Ejemplo de integraci\u00f3n"
        }, 
        {
            "location": "/interfaz/#propiedades_2", 
            "text": "texto  - Etiqueta que mostrar\u00e1 el deslizador  seleccionado  - Almacena True o False, indicando el estado de selecci\u00f3n.", 
            "title": "Propiedades"
        }, 
        {
            "location": "/interfaz/#metodos_2", 
            "text": "conectar(funcion)  - Conecta una funci\u00f3n que se llamar\u00e1 cada vez que muevas el deslizador.  alternar_seleccion()  seleccionar()  deseleccionar()", 
            "title": "M\u00e9todos"
        }, 
        {
            "location": "/interfaz/#clase-ingresodetexto", 
            "text": "Si quieres solicitar datos, como el nombre del\nusuario, puedes usar el objeto  IngresoDeTexto . Ya que\nmuestra una caja y un peque\u00f1o cursor para\ningresar texto:   Para usar este componente tienes que crearlo y luego leer o escribir el\natributo  texto , que contiene la cadena de texto de la caja:  entrada = pilas.interfaz.IngresoDeTexto()\nentrada.texto =  Texto inicial   Inicialmente, el objeto IngresoDeTexto toma un tama\u00f1o y apariencia predeterminado. Pero esto se puede cambiar f\u00e1cilmente usando argumentos al momento de crear el componente.  Por ejemplo, podr\u00edamos enviarle c\u00f3mo argumento un tama\u00f1o mas peque\u00f1o y un \u00edcono de b\u00fasqueda:  entrada = pilas.interfaz.IngresoDeTexto(ancho=100, icono='iconos/lupa.png')\nu otro \u00edcono:  entrada = pilas.interfaz.IngresoDeTexto(ancho=100, icono='iconos/ok.png')\nLa caja tambi\u00e9n tiene otros m\u00e9todos para permitir o prohibir el ingreso de datos.  Por ejemplo, podr\u00edamos decirle a la caja que solo permita el ingreso de n\u00fameros,\nletras, o poner un l\u00edmite de cantidad de caracteres. Los m\u00e9todos\nque te permite limitar el ingreso son  solo_numeros()  y  solo_letras() , y el\nl\u00edmite de caracteres est\u00e1 en el atributo  limite_de_caracteres :", 
            "title": "Clase: IngresoDeTexto"
        }, 
        {
            "location": "/interfaz/#propiedades_3", 
            "text": "texto  icono  limite_de_caracteres", 
            "title": "Propiedades"
        }, 
        {
            "location": "/interfaz/#metodos_3", 
            "text": "cualquier_caracter()  solo_numeros()  solo_letras()", 
            "title": "M\u00e9todos"
        }, 
        {
            "location": "/interfaz/#clase-listaseleccion", 
            "text": "La lista de selecci\u00f3n se utiliza para mostrar al usuario una lista de cadenas, y permitirle seleccionarlas con el mouse.  Para crear un lista de selecci\u00f3n, se tiene que crear una lista de cadenas y declarar una funci\u00f3n para que sea llamada cuando se termina de seleccionar.  Por ejemplo, el siguiente c\u00f3digo muestra una lista e imprime por consola cuando el usuario selecciona con el click del mouse:  def cuando_selecciona(opcion):\n    print( Ha seleccionado la opcion: , opcion)\n\nconsulta = pilas.interfaz.ListaSeleccion(['Uno', 'Dos', 'Tres'], cuando_selecciona)", 
            "title": "Clase: ListaSeleccion"
        }, 
        {
            "location": "/interfaz/#ejemplo-de-integracion_2", 
            "text": "Para mostrar el componente en funcionamiento, hacemos un lista de\ntres opciones, y le conectamos una funci\u00f3n para avisar la opci\u00f3n\nque selecciona el usuario:  pilas.fondos.Pasto()\n\ndef cuando_selecciona(opcion_seleccionada):\n    pilas.avisar( Ha seleccionado la opcion:   + opcion_seleccionada)\n\nopciones = pilas.interfaz.ListaSeleccion(['hola', 'opcion', 'tres'], cuando_selecciona)  Deber\u00edas ver en pantalla lo siguiente:", 
            "title": "Ejemplo de integraci\u00f3n"
        }, 
        {
            "location": "/menu/", 
            "text": "Como crear men\u00faes para tu juegos\n\n\nPara crear men\u00faes en tus juegos puedes usar\nel actor \nMenu\n.\n\n\nEl actor \nMenu\n tiene la funcionalidad de\nrepresentar opciones y que le puedas asociar\nnombres de funciones para invocar.\n\n\nUn men\u00fa sencillo podr\u00eda tener dos opciones, una\npara iniciar el juego y otra para salir:\n\n\nimport pilasengine\n\npilas = pilasengine.iniciar()\npilas.fondos.Selva()\n\ndef iniciar_juego():\n    print(\nTengo que iniciar el juego\n)\n\ndef salir_del_juego():\n    print(\nTengo que salir...\n)\n\npilas.actores.Menu(\n        [\n            ('iniciar juego', iniciar_juego),\n            ('salir', salir_del_juego),\n        ])\n\npilas.ejecutar()\n\n\n\n\nSi escribes este texto en un programa, funciona, aunque no\nes muy \u00fatil: solamente crear\u00e1 una ventana con dos\nopciones, que se pueden seleccionar usando el\nteclado.\n\n\nEsta es una imagen de c\u00f3mo se v\u00e9 el men\u00fa del\nejemplo de mas arriba:\n\n\n\n\nCada vez que selecciones una opci\u00f3n aparecer\u00e1 un\nmensaje en la consola de python.\n\n\nCreando funciones de respuesta\n\n\nSi observas con atenci\u00f3n el primer ejemplo de c\u00f3digo, hay\ndos partes que son muy importantes.\n\n\nPrimero declaramos funciones que hacen algo, como por\nejemplo:\n\n\ndef iniciar_juego():\n    print(\nTengo que iniciar el juego\n)\n\n\n\n\nY luego, cuando creamos el men\u00fa, armamos una lista\nde tuplas, donde el primer elemento es la cadena\nde texto que queremos mostrar, y el segundo elemento\nes la funci\u00f3n a invocar:\n\n\npilas.actores.Menu(\n        [\n            ('iniciar juego', iniciar_juego),\n            ('salir', salir_del_juego),\n        ])\n\n\n\n\nEs importante que el argumento se construya usando\nuna lista como la anterior.\n\n\nPuedes crear tantas\nopciones como quieras, pero siempre tienen que estar\nen una tupla de dos elementos, el primer con un texto\ny el segundo con el nombre de la funci\u00f3n que se tiene\nque invocar.\n\n\nCuando colocamos un nombre de funci\u00f3n de esa forma, es\ndecir, sin los par\u00e9ntesis, decimos que esa funci\u00f3n\nser\u00e1 una funci\u00f3n de repuesta para el men\u00fa. Y aunque\nparezca un recurso muy simple, funciona bastante bien\nen casi todos los casos. Por ejemplo, nuestro c\u00f3digo\nanterior se podr\u00eda poner mas interesante si mejoramos\nla funci\u00f3n \niniciar_juego\n y la funci\u00f3n \nsalir_del_juego\n:\n\n\ndef iniciar_juego():\n    pilas.escenas.Normal()\n    actor = pilas.actores.Aceituna()\n    actor.decir(\nBienvenido al juego\n)\n\ndef salir_del_juego():\n    pilas.terminar()\n\n\n\n\nLos men\u00faes son actores\n\n\nTen en cuenta que el men\u00fa tambi\u00e9n es un actor, as\u00ed\nque podr\u00e1s posicionarlo en la ventana, o cambiar\nsu tama\u00f1o como si se tratara de cualquier otro\npersonaje del juego:\n\n\nmi_menu.escala = 2\nmi_menu.x = [300, 0]\n\n\n\n\nMuchos juegos hace uso de esta caracter\u00edstica, por\nejemplo, para que el men\u00fa aparezca por debajo de la pantalla\no que se mueva constantemente como si estuviera flotando.\n\n\nTen en cuenta que en realidad no estamos aplicando transformaciones\na todo el men\u00fa, simplemente estamos transmitiendo las transformaciones\na cada uno de los textos que componen el men\u00fa. Si haces un\ncambio de rotaci\u00f3n vas a ver a qu\u00e9 me refiero...", 
            "title": "C\u00f3mo crear men\u00faes para tu juegos"
        }, 
        {
            "location": "/menu/#como-crear-menues-para-tu-juegos", 
            "text": "Para crear men\u00faes en tus juegos puedes usar\nel actor  Menu .  El actor  Menu  tiene la funcionalidad de\nrepresentar opciones y que le puedas asociar\nnombres de funciones para invocar.  Un men\u00fa sencillo podr\u00eda tener dos opciones, una\npara iniciar el juego y otra para salir:  import pilasengine\n\npilas = pilasengine.iniciar()\npilas.fondos.Selva()\n\ndef iniciar_juego():\n    print( Tengo que iniciar el juego )\n\ndef salir_del_juego():\n    print( Tengo que salir... )\n\npilas.actores.Menu(\n        [\n            ('iniciar juego', iniciar_juego),\n            ('salir', salir_del_juego),\n        ])\n\npilas.ejecutar()  Si escribes este texto en un programa, funciona, aunque no\nes muy \u00fatil: solamente crear\u00e1 una ventana con dos\nopciones, que se pueden seleccionar usando el\nteclado.  Esta es una imagen de c\u00f3mo se v\u00e9 el men\u00fa del\nejemplo de mas arriba:   Cada vez que selecciones una opci\u00f3n aparecer\u00e1 un\nmensaje en la consola de python.", 
            "title": "Como crear men\u00faes para tu juegos"
        }, 
        {
            "location": "/menu/#creando-funciones-de-respuesta", 
            "text": "Si observas con atenci\u00f3n el primer ejemplo de c\u00f3digo, hay\ndos partes que son muy importantes.  Primero declaramos funciones que hacen algo, como por\nejemplo:  def iniciar_juego():\n    print( Tengo que iniciar el juego )  Y luego, cuando creamos el men\u00fa, armamos una lista\nde tuplas, donde el primer elemento es la cadena\nde texto que queremos mostrar, y el segundo elemento\nes la funci\u00f3n a invocar:  pilas.actores.Menu(\n        [\n            ('iniciar juego', iniciar_juego),\n            ('salir', salir_del_juego),\n        ])  Es importante que el argumento se construya usando\nuna lista como la anterior.  Puedes crear tantas\nopciones como quieras, pero siempre tienen que estar\nen una tupla de dos elementos, el primer con un texto\ny el segundo con el nombre de la funci\u00f3n que se tiene\nque invocar.  Cuando colocamos un nombre de funci\u00f3n de esa forma, es\ndecir, sin los par\u00e9ntesis, decimos que esa funci\u00f3n\nser\u00e1 una funci\u00f3n de repuesta para el men\u00fa. Y aunque\nparezca un recurso muy simple, funciona bastante bien\nen casi todos los casos. Por ejemplo, nuestro c\u00f3digo\nanterior se podr\u00eda poner mas interesante si mejoramos\nla funci\u00f3n  iniciar_juego  y la funci\u00f3n  salir_del_juego :  def iniciar_juego():\n    pilas.escenas.Normal()\n    actor = pilas.actores.Aceituna()\n    actor.decir( Bienvenido al juego )\n\ndef salir_del_juego():\n    pilas.terminar()", 
            "title": "Creando funciones de respuesta"
        }, 
        {
            "location": "/menu/#los-menues-son-actores", 
            "text": "Ten en cuenta que el men\u00fa tambi\u00e9n es un actor, as\u00ed\nque podr\u00e1s posicionarlo en la ventana, o cambiar\nsu tama\u00f1o como si se tratara de cualquier otro\npersonaje del juego:  mi_menu.escala = 2\nmi_menu.x = [300, 0]  Muchos juegos hace uso de esta caracter\u00edstica, por\nejemplo, para que el men\u00fa aparezca por debajo de la pantalla\no que se mueva constantemente como si estuviera flotando.  Ten en cuenta que en realidad no estamos aplicando transformaciones\na todo el men\u00fa, simplemente estamos transmitiendo las transformaciones\na cada uno de los textos que componen el men\u00fa. Si haces un\ncambio de rotaci\u00f3n vas a ver a qu\u00e9 me refiero...", 
            "title": "Los men\u00faes son actores"
        }, 
        {
            "location": "/mapas_y_plataformas/", 
            "text": "Mapas y plataformas\n\n\nEn los a\u00f1os 80 uno de los g\u00e9neros de videojuegos mas\ncelebrados ha sido el genero de plataformas.\n\n\nEn los juegos de este g\u00e9nero el protagonista de la\naventura estaba en un escenario armado de bloques y\nplataformas en donde pod\u00eda saltar.\n\n\nUno de los juegos mas populares de esos d\u00edas era\nSuper Mario Bros.\n\n\nPilas incluye un actor llamado \nMapa\n que te permite\nhacer juegos de plataformas f\u00e1cilmente.\n\n\nPresentando el actor \nMapa\n\n\nEl \nMapa\n representa un escenario compuesto de bloques\nque pueden ser plataformas, muros o simplemente adornos\ndel escenario.\n\n\nPara crear un \nMapa\n necesitas una grilla de gr\u00e1ficos con los bloques\nque se usar\u00e1n en el escenario. Luego puedes crear el \nMapa\n:\n\n\ngrilla = pilas.imagenes.cargar_grilla(\"grillas/plataformas_10_10.png\", 10, 10)\nmapa = pilas.actores.Mapa(grilla)\n\n\n\nUna vez que ejecutas esas sentencias no observar\u00e1s cambios\nen la ventana, el mapa est\u00e1, pero no tiene bloques a\u00fan.\n\n\nSi quieres dibujar bloques solo tienes que indicar un\n\u00edndice de bloque y la posici\u00f3n en pantalla a dibujar.\n\n\nPor ejemplo, un bloque cerca del centro de la ventana es\nla posici\u00f3n (8, 10):\n\n\nmapa.pintar_bloque(8, 10, 1)\n\n\n\n\n\nOtro ejemplo: si queremos dibujar en la parte inferior de la\nventana, podemos llamar muchas veces al m\u00e9todo \npintar_bloque\n, una\nvez por cada bloque que necesitamos:\n\n\nfor columna in range(20):\n    mapa.pintar_bloque(14, columna, 1)\n\n\n\nEl primer y segundo argumento del m\u00e9todo \npintar_bloque\n indica\nla posici\u00f3n en donde vamos a dibujar el bloque. En este caso la\nfila ser\u00e1 14 y la columna ser\u00e1 0, 1, 2, 3, 4.. etc\n\n\nEl tercer argumento ser\u00e1 el \u00edndice de la grilla que indicamos\nanteriormente.\n\n\n\n\nColisiones con el escenario\n\n\nEn los juegos de plataformas es muy importante que los bloques\npuedan interactuar con los jugadores. Por ejemplo habr\u00e1 bloques\nque sirvan como plataformas y otros impedir\u00e1n que avancemos como\nsi se trataran de muros.\n\n\nLos mapas de pilas te permiten crear esta interacci\u00f3n de manera\nsencilla. El m\u00e9todo que usamos antes \npintar_bloque\n, le\ndice al mapa que dibuje el bloque, pero a la vez te permite\nindicar si ese bloque es s\u00f3lido o no.\n\n\nDiremos que un bloque es s\u00f3lido cuando un personaje no puede\npasar a trav\u00e9s de \u00e9l. Por ejemplo, una plataforma es un bloque\ns\u00f3lido.\n\n\nEntonces, cada vez que invocas al m\u00e9todo \npintar_bloque\n tienes\nla posibilidad de indicar si el bloque es s\u00f3lido o no:\n\n\nmapa.pintar_bloque(14, 10, 1, es_bloque_solido=True)\nmapa.pintar_bloque(14, 10, 1, es_bloque_solido=False)\n\n\n\nY ten en cuenta que si no especificas el \u00faltimo par\u00e1metro, pilas\nasumir\u00e1 que el bloque debe ser s\u00f3lido.\n\n\nPor cierto, los bloques \"no s\u00f3lidos\" son \u00fatiles para representar\nadornos del escenario, como nubes o agua. Incluso en algunos\njuegos se usan para crear pasadizos secretos entre muros o\nplataformas...\n\n\nCreando mapas con el programa tiled\n\n\nCrear los mapas directamente desde el c\u00f3digo est\u00e1 bien, pero\nsi tienes que hacer muchos mapas te llevar\u00e1 un mont\u00f3n de tiempo.\n\n\nUna buena alternativa a esto es usar un software de dise\u00f1o\nde escenarios, crear un archivo con todo el escenario y\nluego cargarlo desde pilas.\n\n\nEl software que te recomiendo para esta tarea se llama \ntiled\n\n(ver http://www.mapeditor.org).\n\n\nVeamos como usar tiled para crear un escenario sencillo, primero\ntienes que crear un mapa desde el men\u00fa \nFile\n, se le solicitar\u00e1\nindicar el tama\u00f1o del escenario:\n\n\n\n\nUsa los valores por defecto, al menos por esta vez.\n\n\nLuego tienes que ir al men\u00fa \nMap\n y luego \nNew tileset\n para\nindicar cual es la grilla de im\u00e1genes que usar\u00e1s en los bloques. Te\nrecomiendo usar la imagen \nbatalhao.png\n (de Silveins Neto), que\nest\u00e1 en la carpeta de ejemplos de pilas:\n\n\n\n\nAhora, lo mas divertido, comienza a dibujar sobre el escenario\nseleccionando bloques. Observa que el programa tiene varias herramientas\npara hacer que esto sea mucho mas sencillo:\n\n\n\n\nLuego, aseg\u00farate de que el programa guarda todos los datos en formato CSV, esto\nes importante para que se pueda vincular con pilas. Para esto tienes\nque abrir el men\u00fa \nEdit\n y luego \nPreferences\n, la pantalla de opciones\nte tiene que quedar as\u00ed:\n\n\n\n\nListo, ahora solamente hay que guardar el mapa en un archivo. Ve al men\u00fa\n\nFile\n y luego selecciona \nSave as\n, tienes que darle un nombre\nal archivo \n.tmx\n.\n\n\nLuego, desde pilas, es muy simple, solamente tienes que crear\nel actor mapa indicando el nombre del archivo \n.tmx\n que has\ngenerado con el programa \ntiled\n:\n\n\nimport pilas\npilas.iniciar()\nmapa_desde_archivo = pilas.actores.MapaTiled(\"archivo.tmx\")\n\n\n\nCreando bloques s\u00f3lidos con tiled\n\n\nSi quieres hacer bloques s\u00f3lidos desde \ntiled\n solamente\ntienes que crear una capa especial. Si una de las capas comienza\ncon el nombre \"solido\" entonces pilas har\u00e1 que cada uno\nde los bloques sea interpretado como un bloque s\u00f3lido.\n\n\nPor ejemplo, en el escenario anterior, ser\u00eda interesante colocar\nlos bloques de pasto y la ruta en la capa que he llamado \"suelo\"\ny el resto de los objetos en otras capas que ser\u00e1n s\u00f3lidas,\nen este caso \"solido obst\u00e1culos\" y \"solido paredes\":\n\n\n\n\nUn ejemplo completo\n\n\nTe recomiendo que observes el ejemplo \nmapa_desde_archivo.py\n del\ndirectorio de ejemplos de pilas, podr\u00e1s observar un escenario\nmuy simple con obst\u00e1culos y un personaje que se puede mover\ncon el teclado:\n\n\n\n\nO bien, el ejemplo \nplataformas\n.", 
            "title": "Mapas y plataformas"
        }, 
        {
            "location": "/mapas_y_plataformas/#mapas-y-plataformas", 
            "text": "En los a\u00f1os 80 uno de los g\u00e9neros de videojuegos mas\ncelebrados ha sido el genero de plataformas.  En los juegos de este g\u00e9nero el protagonista de la\naventura estaba en un escenario armado de bloques y\nplataformas en donde pod\u00eda saltar.  Uno de los juegos mas populares de esos d\u00edas era\nSuper Mario Bros.  Pilas incluye un actor llamado  Mapa  que te permite\nhacer juegos de plataformas f\u00e1cilmente.", 
            "title": "Mapas y plataformas"
        }, 
        {
            "location": "/mapas_y_plataformas/#presentando-el-actor-mapa", 
            "text": "El  Mapa  representa un escenario compuesto de bloques\nque pueden ser plataformas, muros o simplemente adornos\ndel escenario.  Para crear un  Mapa  necesitas una grilla de gr\u00e1ficos con los bloques\nque se usar\u00e1n en el escenario. Luego puedes crear el  Mapa :  grilla = pilas.imagenes.cargar_grilla(\"grillas/plataformas_10_10.png\", 10, 10)\nmapa = pilas.actores.Mapa(grilla)  Una vez que ejecutas esas sentencias no observar\u00e1s cambios\nen la ventana, el mapa est\u00e1, pero no tiene bloques a\u00fan.  Si quieres dibujar bloques solo tienes que indicar un\n\u00edndice de bloque y la posici\u00f3n en pantalla a dibujar.  Por ejemplo, un bloque cerca del centro de la ventana es\nla posici\u00f3n (8, 10):  mapa.pintar_bloque(8, 10, 1)   Otro ejemplo: si queremos dibujar en la parte inferior de la\nventana, podemos llamar muchas veces al m\u00e9todo  pintar_bloque , una\nvez por cada bloque que necesitamos:  for columna in range(20):\n    mapa.pintar_bloque(14, columna, 1)  El primer y segundo argumento del m\u00e9todo  pintar_bloque  indica\nla posici\u00f3n en donde vamos a dibujar el bloque. En este caso la\nfila ser\u00e1 14 y la columna ser\u00e1 0, 1, 2, 3, 4.. etc  El tercer argumento ser\u00e1 el \u00edndice de la grilla que indicamos\nanteriormente.", 
            "title": "Presentando el actor Mapa"
        }, 
        {
            "location": "/mapas_y_plataformas/#colisiones-con-el-escenario", 
            "text": "En los juegos de plataformas es muy importante que los bloques\npuedan interactuar con los jugadores. Por ejemplo habr\u00e1 bloques\nque sirvan como plataformas y otros impedir\u00e1n que avancemos como\nsi se trataran de muros.  Los mapas de pilas te permiten crear esta interacci\u00f3n de manera\nsencilla. El m\u00e9todo que usamos antes  pintar_bloque , le\ndice al mapa que dibuje el bloque, pero a la vez te permite\nindicar si ese bloque es s\u00f3lido o no.  Diremos que un bloque es s\u00f3lido cuando un personaje no puede\npasar a trav\u00e9s de \u00e9l. Por ejemplo, una plataforma es un bloque\ns\u00f3lido.  Entonces, cada vez que invocas al m\u00e9todo  pintar_bloque  tienes\nla posibilidad de indicar si el bloque es s\u00f3lido o no:  mapa.pintar_bloque(14, 10, 1, es_bloque_solido=True)\nmapa.pintar_bloque(14, 10, 1, es_bloque_solido=False)  Y ten en cuenta que si no especificas el \u00faltimo par\u00e1metro, pilas\nasumir\u00e1 que el bloque debe ser s\u00f3lido.  Por cierto, los bloques \"no s\u00f3lidos\" son \u00fatiles para representar\nadornos del escenario, como nubes o agua. Incluso en algunos\njuegos se usan para crear pasadizos secretos entre muros o\nplataformas...", 
            "title": "Colisiones con el escenario"
        }, 
        {
            "location": "/mapas_y_plataformas/#creando-mapas-con-el-programa-tiled", 
            "text": "Crear los mapas directamente desde el c\u00f3digo est\u00e1 bien, pero\nsi tienes que hacer muchos mapas te llevar\u00e1 un mont\u00f3n de tiempo.  Una buena alternativa a esto es usar un software de dise\u00f1o\nde escenarios, crear un archivo con todo el escenario y\nluego cargarlo desde pilas.  El software que te recomiendo para esta tarea se llama  tiled \n(ver http://www.mapeditor.org).  Veamos como usar tiled para crear un escenario sencillo, primero\ntienes que crear un mapa desde el men\u00fa  File , se le solicitar\u00e1\nindicar el tama\u00f1o del escenario:   Usa los valores por defecto, al menos por esta vez.  Luego tienes que ir al men\u00fa  Map  y luego  New tileset  para\nindicar cual es la grilla de im\u00e1genes que usar\u00e1s en los bloques. Te\nrecomiendo usar la imagen  batalhao.png  (de Silveins Neto), que\nest\u00e1 en la carpeta de ejemplos de pilas:   Ahora, lo mas divertido, comienza a dibujar sobre el escenario\nseleccionando bloques. Observa que el programa tiene varias herramientas\npara hacer que esto sea mucho mas sencillo:   Luego, aseg\u00farate de que el programa guarda todos los datos en formato CSV, esto\nes importante para que se pueda vincular con pilas. Para esto tienes\nque abrir el men\u00fa  Edit  y luego  Preferences , la pantalla de opciones\nte tiene que quedar as\u00ed:   Listo, ahora solamente hay que guardar el mapa en un archivo. Ve al men\u00fa File  y luego selecciona  Save as , tienes que darle un nombre\nal archivo  .tmx .  Luego, desde pilas, es muy simple, solamente tienes que crear\nel actor mapa indicando el nombre del archivo  .tmx  que has\ngenerado con el programa  tiled :  import pilas\npilas.iniciar()\nmapa_desde_archivo = pilas.actores.MapaTiled(\"archivo.tmx\")", 
            "title": "Creando mapas con el programa tiled"
        }, 
        {
            "location": "/mapas_y_plataformas/#creando-bloques-solidos-con-tiled", 
            "text": "Si quieres hacer bloques s\u00f3lidos desde  tiled  solamente\ntienes que crear una capa especial. Si una de las capas comienza\ncon el nombre \"solido\" entonces pilas har\u00e1 que cada uno\nde los bloques sea interpretado como un bloque s\u00f3lido.  Por ejemplo, en el escenario anterior, ser\u00eda interesante colocar\nlos bloques de pasto y la ruta en la capa que he llamado \"suelo\"\ny el resto de los objetos en otras capas que ser\u00e1n s\u00f3lidas,\nen este caso \"solido obst\u00e1culos\" y \"solido paredes\":", 
            "title": "Creando bloques s\u00f3lidos con tiled"
        }, 
        {
            "location": "/mapas_y_plataformas/#un-ejemplo-completo", 
            "text": "Te recomiendo que observes el ejemplo  mapa_desde_archivo.py  del\ndirectorio de ejemplos de pilas, podr\u00e1s observar un escenario\nmuy simple con obst\u00e1culos y un personaje que se puede mover\ncon el teclado:   O bien, el ejemplo  plataformas .", 
            "title": "Un ejemplo completo"
        }, 
        {
            "location": "/dialogos/", 
            "text": "Di\u00e1logos\n\n\nPara contar una historia dentro de un juego\npodr\u00edas hacer que los personajes conversen\nentre s\u00ed.\n\n\nEsto es muy habitual en un genero de videojuego\nllamado aventuras gr\u00e1ficas.\n\n\nMensajes de dialogo\n\n\nPara hacer que un personaje emita un mensaje sencillo\npuedes usar el m\u00e9todo \ndecir\n:\n\n\nactor = pilas.actores.Mono()\nactor.decir(\nEh!, ahora puedo hablar...\n)\n\n\n\n\nEsto har\u00e1 que el personaje muestre un globo similar al\nde las historietas con las frases que has colocado.\n\n\n\n\nConversaciones\n\n\nLos mensajes de dialogo se pueden usar para que dos\no mas actores puedan conversar entre s\u00ed. Esto es \u00fatil\npara contar una historia, ya que le permites al usuario\nir viendo paso a paso lo que se dicen los actores entre\ns\u00ed.\n\n\nPara crear una conversaci\u00f3n entre actores tienes que\ncrear un objeto de la clase \nDialogo\n, luego\nindicarle la secuencia de conversaci\u00f3n y por \u00faltimo\niniciar el dialogo:\n\n\ndialogo = pilas.actores.Dialogo()\n\ndialogo.decir(mono, \nHola, como estas?\n)\ndialogo.decir(otro_mono, \nPerfecto!!, gracias...\n)\ndialogo.decir(mono, \ngenial...\n)\n\ndialogo.comenzar()\n\n\n\n\nAhora cuando ejecutes este programa, solamente aparecer\u00e1\nel primer mensaje \n\"Hola, c\u00f3mo estas?\"\n y solo cuando el\nusuario haga click con el mouse avanzar\u00e1.\n\n\nTen en cuenta que el m\u00e9todo \ndecir\n funciona como una\ncola de mensajes, es decir, si llamas a \ndecir\n el mensaje\nno aparecer\u00e1 inmediatamente. El mensaje aparecer\u00e1 cuando\ncorresponda seg\u00fan el orden de la conversaci\u00f3n que se siga.\n\n\nSi quieres que un bot\u00f3n accione un mensaje y lo haga\nde manera inmediata tendr\u00edas que usar un m\u00e9todo c\u00f3mo \ndialogo.decir_inmediatamente\n.", 
            "title": "Di\u00e1logos"
        }, 
        {
            "location": "/dialogos/#dialogos", 
            "text": "Para contar una historia dentro de un juego\npodr\u00edas hacer que los personajes conversen\nentre s\u00ed.  Esto es muy habitual en un genero de videojuego\nllamado aventuras gr\u00e1ficas.", 
            "title": "Di\u00e1logos"
        }, 
        {
            "location": "/dialogos/#mensajes-de-dialogo", 
            "text": "Para hacer que un personaje emita un mensaje sencillo\npuedes usar el m\u00e9todo  decir :  actor = pilas.actores.Mono()\nactor.decir( Eh!, ahora puedo hablar... )  Esto har\u00e1 que el personaje muestre un globo similar al\nde las historietas con las frases que has colocado.", 
            "title": "Mensajes de dialogo"
        }, 
        {
            "location": "/dialogos/#conversaciones", 
            "text": "Los mensajes de dialogo se pueden usar para que dos\no mas actores puedan conversar entre s\u00ed. Esto es \u00fatil\npara contar una historia, ya que le permites al usuario\nir viendo paso a paso lo que se dicen los actores entre\ns\u00ed.  Para crear una conversaci\u00f3n entre actores tienes que\ncrear un objeto de la clase  Dialogo , luego\nindicarle la secuencia de conversaci\u00f3n y por \u00faltimo\niniciar el dialogo:  dialogo = pilas.actores.Dialogo()\n\ndialogo.decir(mono,  Hola, como estas? )\ndialogo.decir(otro_mono,  Perfecto!!, gracias... )\ndialogo.decir(mono,  genial... )\n\ndialogo.comenzar()  Ahora cuando ejecutes este programa, solamente aparecer\u00e1\nel primer mensaje  \"Hola, c\u00f3mo estas?\"  y solo cuando el\nusuario haga click con el mouse avanzar\u00e1.  Ten en cuenta que el m\u00e9todo  decir  funciona como una\ncola de mensajes, es decir, si llamas a  decir  el mensaje\nno aparecer\u00e1 inmediatamente. El mensaje aparecer\u00e1 cuando\ncorresponda seg\u00fan el orden de la conversaci\u00f3n que se siga.  Si quieres que un bot\u00f3n accione un mensaje y lo haga\nde manera inmediata tendr\u00edas que usar un m\u00e9todo c\u00f3mo  dialogo.decir_inmediatamente .", 
            "title": "Conversaciones"
        }, 
        {
            "location": "/camara/", 
            "text": "Manejo de C\u00e1mara\n\n\nEn ocasiones queremos que el escenario de\nnuestro juego sea muy extenso, un bosque, una\nciudad repleta de objetos etc...\n\n\nNuestros juegos con pilas no est\u00e1n limitados\na lo que podemos ver en la ventana, el espacio\ndel escenario puede ser tan grande como queramos. Aqu\u00ed\nes donde la \nc\u00e1mara\n toma protagonismo.\n\n\nEl objeto \nc\u00e1mara\n nos permite desplazar el punto\nde vista en cualquier parte del escenario, dado que nos\nbrinda dos coordenadas: \nx\n e \ny\n, para que le\nindiquemos qu\u00e9 parte del escenario tenemos que observar.\n\n\nLas coordenadas de la c\u00e1mara\n\n\nInicialmente la c\u00e1mara estar\u00e1 mostrando el punto \n(0, 0)\n\ndel escenario, el punto central de la ventana.\n\n\nSi queremos que muestre otra parte del escenario\npodemos ejecutar una sentencia como la que sigue:\n\n\npilas.camara.x = [200]\npilas.camara.y = [200]\n\n\n\n\nCon esto le estar\u00edamos diciendo a la c\u00e1mara que nos\nmuestre el punto \n(200, 200)\n del escenario. As\u00ed\nobservar\u00edamos que podemos explorar la parte superior\nderecha del escenario de forma gradual.\n\n\nObjetos sensibles a la c\u00e1mara\n\n\nHay casos en donde queremos que los actores no\nse desplacen junto con el escenario, es decir,\npuede ocurrir que necesitemos que un actor permanezca\nfijo en su posici\u00f3n de pantalla aunque la c\u00e1mara cambie\nde lugar.\n\n\nEste es el caso de los contadores de vidas, los textos\nque v\u00e9 un usuario o cualquier marcador auxiliar.\n\n\nPara que un actor no se vea afectado por la c\u00e1mara, tienes\nque guardar el valor \nTrue\n dentro del atributo \nfijo\n:\n\n\nactor.fijo = True\n\n\n\n\nPor lo general, todos los actores tienen este atributo a \nFalse\n, porque\nviven en el escenario de juego y no se quedan fijos a la pantalla. Excepto\nlos textos que siempre permanecen en la parte superior de la ventana.\n\n\nMovimientos de c\u00e1mara\n\n\nPara darle acci\u00f3n a los juegos se puede aplicar un movimiento de c\u00e1mara, o vibraci\u00f3n. Por ejemplo al momento de perder una vida o cuando ocurre una explosi\u00f3n.\n\n\nEl m\u00e9todo para realizar un movimiento es \ncamara.vibrar\n y admite dos\nargumentos, uno de intensidad y otro de duraci\u00f3n o tiempo.\n\n\nAqu\u00ed hay dos ejemplos de invocaci\u00f3n:\n\n\npilas.camara.vibrar()\npilas.camara.vibrar(intensidad=2, tiempo=3)", 
            "title": "Manejo de C\u00e1mara"
        }, 
        {
            "location": "/camara/#manejo-de-camara", 
            "text": "En ocasiones queremos que el escenario de\nnuestro juego sea muy extenso, un bosque, una\nciudad repleta de objetos etc...  Nuestros juegos con pilas no est\u00e1n limitados\na lo que podemos ver en la ventana, el espacio\ndel escenario puede ser tan grande como queramos. Aqu\u00ed\nes donde la  c\u00e1mara  toma protagonismo.  El objeto  c\u00e1mara  nos permite desplazar el punto\nde vista en cualquier parte del escenario, dado que nos\nbrinda dos coordenadas:  x  e  y , para que le\nindiquemos qu\u00e9 parte del escenario tenemos que observar.", 
            "title": "Manejo de C\u00e1mara"
        }, 
        {
            "location": "/camara/#las-coordenadas-de-la-camara", 
            "text": "Inicialmente la c\u00e1mara estar\u00e1 mostrando el punto  (0, 0) \ndel escenario, el punto central de la ventana.  Si queremos que muestre otra parte del escenario\npodemos ejecutar una sentencia como la que sigue:  pilas.camara.x = [200]\npilas.camara.y = [200]  Con esto le estar\u00edamos diciendo a la c\u00e1mara que nos\nmuestre el punto  (200, 200)  del escenario. As\u00ed\nobservar\u00edamos que podemos explorar la parte superior\nderecha del escenario de forma gradual.", 
            "title": "Las coordenadas de la c\u00e1mara"
        }, 
        {
            "location": "/camara/#objetos-sensibles-a-la-camara", 
            "text": "Hay casos en donde queremos que los actores no\nse desplacen junto con el escenario, es decir,\npuede ocurrir que necesitemos que un actor permanezca\nfijo en su posici\u00f3n de pantalla aunque la c\u00e1mara cambie\nde lugar.  Este es el caso de los contadores de vidas, los textos\nque v\u00e9 un usuario o cualquier marcador auxiliar.  Para que un actor no se vea afectado por la c\u00e1mara, tienes\nque guardar el valor  True  dentro del atributo  fijo :  actor.fijo = True  Por lo general, todos los actores tienen este atributo a  False , porque\nviven en el escenario de juego y no se quedan fijos a la pantalla. Excepto\nlos textos que siempre permanecen en la parte superior de la ventana.", 
            "title": "Objetos sensibles a la c\u00e1mara"
        }, 
        {
            "location": "/camara/#movimientos-de-camara", 
            "text": "Para darle acci\u00f3n a los juegos se puede aplicar un movimiento de c\u00e1mara, o vibraci\u00f3n. Por ejemplo al momento de perder una vida o cuando ocurre una explosi\u00f3n.  El m\u00e9todo para realizar un movimiento es  camara.vibrar  y admite dos\nargumentos, uno de intensidad y otro de duraci\u00f3n o tiempo.  Aqu\u00ed hay dos ejemplos de invocaci\u00f3n:  pilas.camara.vibrar()\npilas.camara.vibrar(intensidad=2, tiempo=3)", 
            "title": "Movimientos de c\u00e1mara"
        }, 
        {
            "location": "/eventos/", 
            "text": "Eventos, conexiones y respuestas\n\n\nEn el desarrollo de videojuegos es muy importante\npoder comunicarse con el usuario. Lograr que los\npersonajes del juego puedan interactuar con \u00e9l y\nexista una fuerte interacci\u00f3n.\n\n\nEn pilas usamos una estrategia llamada \neventos, conexiones\ny respuestas\n, no solo porque es muy sencilla de usar, sino\ntambi\u00e9n porque es una soluci\u00f3n conocida y muy utilizada\nen otros lugares como en la web.\n\n\n\u00bfQue es un Evento?\n\n\nLos eventos representan algo que esperamos que ocurra\ndentro de un juego, por ejemplo un \nclick\n del mouse, la\n\npulsaci\u00f3n\n de una tecla, el \ncierre\n de la\nventana o la \ncolisi\u00f3n\n entre un enemigo y nuestro\nprotagonista.\n\n\nLo interesante de los eventos, es que pueden ocurrir en\ncualquier momento, y generalmente no lo controlamos, solamente\nlos escuchamos y tomamos alguna respuesta predefinida.\n\n\nPilas representa a los eventos como objetos, y nos brinda\nfunciones para ser avisados cuando un evento ocurre e incluso\nemitir y generar eventos nuevos.\n\n\nVeamos algunos ejemplos:\n\n\nConectando la emisi\u00f3n de eventos a funciones\n\n\nLos \neventos\n no disparan ninguna acci\u00f3n autom\u00e1tica, nosotros\nlos programadores somos los que tenemos que elegir los\neventos importantes y elegir que hacer al respecto.\n\n\nPara utilizar estas se\u00f1ales, tenemos que vincularlas a funciones, de\nforma que al emitirse la se\u00f1al podamos ejecutar c\u00f3digo.\n\n\nLa funci\u00f3n \nconectar\n\n\nLa funci\u00f3n \nconectar\n nos permite conectar una se\u00f1al de\nevento a un m\u00e9todo o una funci\u00f3n.\n\n\nDe esta forma, cada vez que se emita una determinada\nse\u00f1al, se avisar\u00e1 a todos los objectos que hallamos\nconectado.\n\n\nPor ejemplo, si queremos que un personaje se mueva\nen pantalla siguiendo la posici\u00f3n del puntero\ndel mouse, tendr\u00edamos que escribir algo como\nesto:\n\n\nimport pilasengine\n\npilas = pilasengine.iniciar()\n\nmono = pilas.actores.Mono()\n\ndef mover_mono_a_la_posicion_del_mouse(evento):\n    mono.x = evento.x\n    mono.y = evento.y\n\npilas.eventos.mueve_mouse.conectar(mover_mono_a_la_posicion_del_mouse)\n\n# O puedes utilizar el m\u00e9todo abreviado del actor.\nmono.mueve_mouse(mover_mono_a_la_posicion_del_mouse)\n\npilas.ejecutar()\n\n\n\n\nEs decir, la se\u00f1al de evento que nos interesa es \nmueve_mouse\n (que se emite\ncada vez que el usuario mueve el mouse). Y a esta se\u00f1al le conectamos\nla funci\u00f3n que buscamos ejecutar cada vez que se mueva el mouse.\n\n\nTen en cuenta que pueden existir tantas funciones conectadas a una se\u00f1al como\nquieras.\n\n\nLas coordenadas que reporta el mouse son relativas al escenario y no\nde la ventana. Por lo tanto puedes asignar directamente el valor\nde las coordenadas del mouse a los actores sin efectos colaterales\ncon respecto a la c\u00e1mara.\n\n\nObservando a los eventos para conocerlos mejor\n\n\nComo puedes ver en la funci\u00f3n \nmover_mono_a_la_posicion_del_mouse\n, hemos\ndefinido un par\u00e1metro llamado \nevento\n y accedimos a sus valores\n\nx\n e \ny\n.\n\n\nCada evento tiene dentro un conjunto de valores que nos resultar\u00e1\nde utilidad conocer. En el caso del movimiento de mouse usamos\n\nx\n e \ny\n, pero si el evento es la pulsaci\u00f3n de una tecla, seguramente\nvamos a querer saber exactamente qu\u00e9 tecla se puls\u00f3.\n\n\nEntonces, una forma f\u00e1cil y simple de conocer el estado de un\nobjeto es imprimir directamente su contenido, por ejemplo, en\nla funci\u00f3n de arriba pod\u00edamos escribir:\n\n\ndef mover_mono_a_la_posicion_del_mouse(evento):\n    print(evento)\n\n\n\ny en la ventana de nuestra computadora tendr\u00edamos que ver\nalgo as\u00ed:\n\n\n{'y': 2.0, 'x': -57.0, 'dx': 0.0, 'dy': -1.0}\n\n\n\ndonde claramente podemos ver todos los datos que vienen asociados\nal evento.\n\n\nPor \u00faltimo, ten en cuenta que este argumento \nevento\n, en realidad,\nes un diccionario de python como cualquier otro, solo\nque puedes acceder a sus valores usando sentencias c\u00f3mo\n\ndiccionario.clave\n en lugar de \ndiccionario['clave']\n.\n\n\nDesconectando se\u00f1ales\n\n\nLas se\u00f1ales se desconectan por cuenta propia cuando dejan de existir\nlos objetos que le conectamos. En la mayor\u00eda de los casos podemos\nconectar se\u00f1ales y olvidarnos de desconectarlas, no habr\u00e1 problemas,\nse deconectar\u00e1n solas.\n\n\nDe todas formas, puede que quieras conectar una se\u00f1al, y por\nalg\u00fan motivo desconectarla. Por ejemplo si el juego cambia\nde estado o algo as\u00ed...\n\n\nSi ese es tu caso, simplemente as\u00edgnale un identificador \u00fanico\nal manejador de la se\u00f1al y luego usa la funci\u00f3n \ndesconectar_por_id\n indicando\nel identificador.\n\n\nPor ejemplo, las siguientes sentencias muestran eso:\n\n\npilas.eventos.mueve_mouse.conectar(imprimir_posicion, id='drag')\npilas.eventos.mueve_mouse.desconectar_por_id('drag')\n\n\n\nEn la primera sentencia conect\u00e9 la se\u00f1al del evento a una funci\u00f3n y le di\nun valor al argumento \nid\n. Este valor ser\u00e1 el identificador\nde ese enlace. Y en la siguiente linea se utiliz\u00f3 el identificador\npara desconectarla.\n\n\nListado de todos los eventos existentes\n\n\n\n\n\n\n\n\nEvento\n\n\nParametros\n\n\n\n\n\n\n\n\n\n\nmueve_camara\n\n\nx, y, dx, dy\n\n\n\n\n\n\nmueve_mouse\n\n\nx, y, dx, dy\n\n\n\n\n\n\nclick_de_mouse\n\n\nboton, x, y\n\n\n\n\n\n\ntermina_click\n\n\nboton, x, y\n\n\n\n\n\n\nmueve_rueda\n\n\ndelta\n\n\n\n\n\n\npulsa_tecla\n\n\ncodigo, texto\n\n\n\n\n\n\nsuelta_tecla\n\n\ncodigo, texto\n\n\n\n\n\n\npulsa_tecla_escape\n\n\n\n\n\n\n\n\ncuando_actualiza\n\n\n\n\n\n\n\n\npulsa_boton\n\n\nnumero\n\n\n\n\n\n\nmueve_pad\n\n\nx, y, x1, y1\n\n\n\n\n\n\nluego_de_actualizar\n\n\n\n\n\n\n\n\n\n\nConsultado se\u00f1ales conectadas\n\n\nDurante el desarrollo es \u00fatil poder observar qu\u00e9\neventos se han conectado a funciones.\n\n\nUna forma de observar la conexi\u00f3n de los eventos\nes pulsar la tecla \nF6\n. Eso imprimir\u00e1 sobre\nconsola los nombres de las se\u00f1ales conectadas\njunto a las funciones.\n\n\nCreando tus propios eventos\n\n\nSi tu juego se vuelve mas complejo y hay interacciones entre\nvarios actores, puede ser una buena idea hacer que exista algo\nde comunicaci\u00f3n entre ellos usando eventos.\n\n\nVeamos c\u00f3mo crear un evento:\n\n\nPrimero tienes que crear un objeto que represente a tu evento\ny darle un nombre:\n\n\nevento = pilas.evento.Evento(\"Nombre\")\n\n\n\nluego, este nuevo objeto \nevento\n podr\u00e1 ser utilizado como\ncanal de comunicaci\u00f3n: muchos actores podr\u00e1n \nconectarse\n para\nrecibir alertas y otros podr\u00e1n \nemitir\n alertas:\n\n\ndef ha_ocurrido_un_evento(datos_evento):\n    print(\nHola!!!\n, datos_evento)\n\nevento.conectar(ha_ocurrido_un_evento)\n\n# En otra parte...\nevento.emitir(argumento1=123, argumento2=123)\n\n\n\n\nCuando se emite un evento se pueden pasar muchos argumentos, tantos\ncomo se quiera. Todos estos argumentos llegar\u00e1n a la funci\u00f3n de\nrespuesta en forma de diccionario.\n\n\nPor ejemplo, para este caso, cuando llamamos al m\u00e9todo \nevento.emitir\n,\nel sistema de eventos ir\u00e1 autom\u00e1ticamente a ejecutar la funci\u00f3n \nha_ocurrido_un_evento\n\ny \u00e9sta imprimir\u00e1::\n\n\nHola!!! {argumento1: 123, argumento2: 123}\n\n\n\nReferencias\n\n\nEl concepto que hemos visto en esta secci\u00f3n se utiliza\nen muchos sistemas. Tal vez el mas conocido de estos es\nla biblioteca \nGTK\n, que se utiliza actualmente para construir\nel escritorio \nGNOME\n y \nGimp\n entre otras aplicaciones.\n\n\nEl sistema de se\u00f1ales que se utiliza en pilas es una\nadaptaci\u00f3n del siguiente sistema de eventos:\n\n\nhttp://stackoverflow.com/questions/1092531/event-system-in-python\n\n\nAnteriormente us\u00e1bamos parte del c\u00f3digo del sistema \ndjango\n, pero\nluego de varios meses lo reescribimos para que sea mas sencillo\nde utilizar y no tenga efectos colaterales con los m\u00e9todos y\nel m\u00f3dulo \nweakref\n.\n\n\nSi quieres obtener mas informaci\u00f3n sobre otros sistemas de\neventos te recomendamos los siguientes documentos:\n\n\n\n\nhttp://pydispatcher.sourceforge.net/\n\n\nhttp://www.mercurytide.co.uk/news/article/django-signals/\n\n\nhttp://www.boduch.ca/2009/06/sending-django-dispatch-signals.html\n\n\nhttp://docs.djangoproject.com/en/dev/topics/signals/", 
            "title": "Eventos"
        }, 
        {
            "location": "/eventos/#eventos-conexiones-y-respuestas", 
            "text": "En el desarrollo de videojuegos es muy importante\npoder comunicarse con el usuario. Lograr que los\npersonajes del juego puedan interactuar con \u00e9l y\nexista una fuerte interacci\u00f3n.  En pilas usamos una estrategia llamada  eventos, conexiones\ny respuestas , no solo porque es muy sencilla de usar, sino\ntambi\u00e9n porque es una soluci\u00f3n conocida y muy utilizada\nen otros lugares como en la web.", 
            "title": "Eventos, conexiones y respuestas"
        }, 
        {
            "location": "/eventos/#que-es-un-evento", 
            "text": "Los eventos representan algo que esperamos que ocurra\ndentro de un juego, por ejemplo un  click  del mouse, la pulsaci\u00f3n  de una tecla, el  cierre  de la\nventana o la  colisi\u00f3n  entre un enemigo y nuestro\nprotagonista.  Lo interesante de los eventos, es que pueden ocurrir en\ncualquier momento, y generalmente no lo controlamos, solamente\nlos escuchamos y tomamos alguna respuesta predefinida.  Pilas representa a los eventos como objetos, y nos brinda\nfunciones para ser avisados cuando un evento ocurre e incluso\nemitir y generar eventos nuevos.  Veamos algunos ejemplos:", 
            "title": "\u00bfQue es un Evento?"
        }, 
        {
            "location": "/eventos/#conectando-la-emision-de-eventos-a-funciones", 
            "text": "Los  eventos  no disparan ninguna acci\u00f3n autom\u00e1tica, nosotros\nlos programadores somos los que tenemos que elegir los\neventos importantes y elegir que hacer al respecto.  Para utilizar estas se\u00f1ales, tenemos que vincularlas a funciones, de\nforma que al emitirse la se\u00f1al podamos ejecutar c\u00f3digo.", 
            "title": "Conectando la emisi\u00f3n de eventos a funciones"
        }, 
        {
            "location": "/eventos/#la-funcion-conectar", 
            "text": "La funci\u00f3n  conectar  nos permite conectar una se\u00f1al de\nevento a un m\u00e9todo o una funci\u00f3n.  De esta forma, cada vez que se emita una determinada\nse\u00f1al, se avisar\u00e1 a todos los objectos que hallamos\nconectado.  Por ejemplo, si queremos que un personaje se mueva\nen pantalla siguiendo la posici\u00f3n del puntero\ndel mouse, tendr\u00edamos que escribir algo como\nesto:  import pilasengine\n\npilas = pilasengine.iniciar()\n\nmono = pilas.actores.Mono()\n\ndef mover_mono_a_la_posicion_del_mouse(evento):\n    mono.x = evento.x\n    mono.y = evento.y\n\npilas.eventos.mueve_mouse.conectar(mover_mono_a_la_posicion_del_mouse)\n\n# O puedes utilizar el m\u00e9todo abreviado del actor.\nmono.mueve_mouse(mover_mono_a_la_posicion_del_mouse)\n\npilas.ejecutar()  Es decir, la se\u00f1al de evento que nos interesa es  mueve_mouse  (que se emite\ncada vez que el usuario mueve el mouse). Y a esta se\u00f1al le conectamos\nla funci\u00f3n que buscamos ejecutar cada vez que se mueva el mouse.  Ten en cuenta que pueden existir tantas funciones conectadas a una se\u00f1al como\nquieras.  Las coordenadas que reporta el mouse son relativas al escenario y no\nde la ventana. Por lo tanto puedes asignar directamente el valor\nde las coordenadas del mouse a los actores sin efectos colaterales\ncon respecto a la c\u00e1mara.", 
            "title": "La funci\u00f3n conectar"
        }, 
        {
            "location": "/eventos/#observando-a-los-eventos-para-conocerlos-mejor", 
            "text": "Como puedes ver en la funci\u00f3n  mover_mono_a_la_posicion_del_mouse , hemos\ndefinido un par\u00e1metro llamado  evento  y accedimos a sus valores x  e  y .  Cada evento tiene dentro un conjunto de valores que nos resultar\u00e1\nde utilidad conocer. En el caso del movimiento de mouse usamos x  e  y , pero si el evento es la pulsaci\u00f3n de una tecla, seguramente\nvamos a querer saber exactamente qu\u00e9 tecla se puls\u00f3.  Entonces, una forma f\u00e1cil y simple de conocer el estado de un\nobjeto es imprimir directamente su contenido, por ejemplo, en\nla funci\u00f3n de arriba pod\u00edamos escribir:  def mover_mono_a_la_posicion_del_mouse(evento):\n    print(evento)  y en la ventana de nuestra computadora tendr\u00edamos que ver\nalgo as\u00ed:  {'y': 2.0, 'x': -57.0, 'dx': 0.0, 'dy': -1.0}  donde claramente podemos ver todos los datos que vienen asociados\nal evento.  Por \u00faltimo, ten en cuenta que este argumento  evento , en realidad,\nes un diccionario de python como cualquier otro, solo\nque puedes acceder a sus valores usando sentencias c\u00f3mo diccionario.clave  en lugar de  diccionario['clave'] .", 
            "title": "Observando a los eventos para conocerlos mejor"
        }, 
        {
            "location": "/eventos/#desconectando-senales", 
            "text": "Las se\u00f1ales se desconectan por cuenta propia cuando dejan de existir\nlos objetos que le conectamos. En la mayor\u00eda de los casos podemos\nconectar se\u00f1ales y olvidarnos de desconectarlas, no habr\u00e1 problemas,\nse deconectar\u00e1n solas.  De todas formas, puede que quieras conectar una se\u00f1al, y por\nalg\u00fan motivo desconectarla. Por ejemplo si el juego cambia\nde estado o algo as\u00ed...  Si ese es tu caso, simplemente as\u00edgnale un identificador \u00fanico\nal manejador de la se\u00f1al y luego usa la funci\u00f3n  desconectar_por_id  indicando\nel identificador.  Por ejemplo, las siguientes sentencias muestran eso:  pilas.eventos.mueve_mouse.conectar(imprimir_posicion, id='drag')\npilas.eventos.mueve_mouse.desconectar_por_id('drag')  En la primera sentencia conect\u00e9 la se\u00f1al del evento a una funci\u00f3n y le di\nun valor al argumento  id . Este valor ser\u00e1 el identificador\nde ese enlace. Y en la siguiente linea se utiliz\u00f3 el identificador\npara desconectarla.", 
            "title": "Desconectando se\u00f1ales"
        }, 
        {
            "location": "/eventos/#listado-de-todos-los-eventos-existentes", 
            "text": "Evento  Parametros      mueve_camara  x, y, dx, dy    mueve_mouse  x, y, dx, dy    click_de_mouse  boton, x, y    termina_click  boton, x, y    mueve_rueda  delta    pulsa_tecla  codigo, texto    suelta_tecla  codigo, texto    pulsa_tecla_escape     cuando_actualiza     pulsa_boton  numero    mueve_pad  x, y, x1, y1    luego_de_actualizar", 
            "title": "Listado de todos los eventos existentes"
        }, 
        {
            "location": "/eventos/#consultado-senales-conectadas", 
            "text": "Durante el desarrollo es \u00fatil poder observar qu\u00e9\neventos se han conectado a funciones.  Una forma de observar la conexi\u00f3n de los eventos\nes pulsar la tecla  F6 . Eso imprimir\u00e1 sobre\nconsola los nombres de las se\u00f1ales conectadas\njunto a las funciones.", 
            "title": "Consultado se\u00f1ales conectadas"
        }, 
        {
            "location": "/eventos/#creando-tus-propios-eventos", 
            "text": "Si tu juego se vuelve mas complejo y hay interacciones entre\nvarios actores, puede ser una buena idea hacer que exista algo\nde comunicaci\u00f3n entre ellos usando eventos.  Veamos c\u00f3mo crear un evento:  Primero tienes que crear un objeto que represente a tu evento\ny darle un nombre:  evento = pilas.evento.Evento(\"Nombre\")  luego, este nuevo objeto  evento  podr\u00e1 ser utilizado como\ncanal de comunicaci\u00f3n: muchos actores podr\u00e1n  conectarse  para\nrecibir alertas y otros podr\u00e1n  emitir  alertas:  def ha_ocurrido_un_evento(datos_evento):\n    print( Hola!!! , datos_evento)\n\nevento.conectar(ha_ocurrido_un_evento)\n\n# En otra parte...\nevento.emitir(argumento1=123, argumento2=123)  Cuando se emite un evento se pueden pasar muchos argumentos, tantos\ncomo se quiera. Todos estos argumentos llegar\u00e1n a la funci\u00f3n de\nrespuesta en forma de diccionario.  Por ejemplo, para este caso, cuando llamamos al m\u00e9todo  evento.emitir ,\nel sistema de eventos ir\u00e1 autom\u00e1ticamente a ejecutar la funci\u00f3n  ha_ocurrido_un_evento \ny \u00e9sta imprimir\u00e1::  Hola!!! {argumento1: 123, argumento2: 123}", 
            "title": "Creando tus propios eventos"
        }, 
        {
            "location": "/eventos/#referencias", 
            "text": "El concepto que hemos visto en esta secci\u00f3n se utiliza\nen muchos sistemas. Tal vez el mas conocido de estos es\nla biblioteca  GTK , que se utiliza actualmente para construir\nel escritorio  GNOME  y  Gimp  entre otras aplicaciones.  El sistema de se\u00f1ales que se utiliza en pilas es una\nadaptaci\u00f3n del siguiente sistema de eventos:  http://stackoverflow.com/questions/1092531/event-system-in-python  Anteriormente us\u00e1bamos parte del c\u00f3digo del sistema  django , pero\nluego de varios meses lo reescribimos para que sea mas sencillo\nde utilizar y no tenga efectos colaterales con los m\u00e9todos y\nel m\u00f3dulo  weakref .  Si quieres obtener mas informaci\u00f3n sobre otros sistemas de\neventos te recomendamos los siguientes documentos:   http://pydispatcher.sourceforge.net/  http://www.mercurytide.co.uk/news/article/django-signals/  http://www.boduch.ca/2009/06/sending-django-dispatch-signals.html  http://docs.djangoproject.com/en/dev/topics/signals/", 
            "title": "Referencias"
        }, 
        {
            "location": "/texto/", 
            "text": "Textos\n\n\nLos objetos que muestran texto en pantalla se tratan de manera similar\na los actores. Por lo tanto, si ya sabes usar\nactores, no tendr\u00e1s problemas en usar cadenas\nde texto.\n\n\nCrear cadenas de texto\n\n\nEl objeto que representa texto se llama \nTexto\n y\nest\u00e1 dentro del modulo \nactores\n.\n\n\nPara crear un mensaje tienes que escribir:\n\n\ntexto = pilas.actores.Texto(\nHola, este es mi primer texto.\n)\n\n\n\n\ny tu cadena de texto aparecer\u00e1 en pantalla en color\nnegro y con un tama\u00f1o predeterminado:\n\n\n\n\nSi quieres puedes escribir texto de varias lineas usando el caracter\n\n\\n\n para indicar el salto de linea.\n\n\nPor ejemplo, el siguiente c\u00f3digo escribe el mismo mensaje de\narriba pero en dos lineas:\n\n\ntexto = pilas.actores.Texto(\nHola (en la primer linea)\\n este es mi primer texto.\n)\n\n\n\n\nLos textos son actores\n\n\nAl principio coment\u00e9 que los textos tambi\u00e9n son actores, esto\nsignifica que casi todo lo que puedes hacer con un actor\naqu\u00ed tambi\u00e9n funciona, por ejemplo:\n\n\ntexto.x = 100\ntexto.escala = 2\n\n\n\nincluso tambi\u00e9n funcionar\u00e1n las interpolaciones:\n\n\ntexto.rotacion = pilas.interpolar(360)\n\n\n\nPropiedades exclusivas de los textos\n\n\nExisten varias propiedades que te permitir\u00e1n alterar la\napariencia de los textos.\n\n\nEsta es una lista de los mas importantes.\n\n\n\n\ncolor\n\n\nmagnitud\n\n\ntexto\n\n\n\n\nPor ejemplo, para alterar el texto, color y tama\u00f1o de un\ntexto podr\u00eda escribir algo as\u00ed:\n\n\ntexto.magnitud = 50\ntexto.color = pilas.colores.Color(0, 0, 0)   # Color negro\ntexto.color = pilas.colores.Color(255, 0, 0, 128)   # Color rojo, semi transparente.\ntexto.texto = \nHola, este texto \\n tiene 2 lineas separadas\n\n\n\n\n\nMostrando mensajes en pantalla\n\n\nSi bien podemos crear actores \nTexto\n y manipularlos como\nquedarmos, hay una forma a\u00fan mas sencilla de imprimir mensajes\npara los usuarios.\n\n\nExiste una funci\u00f3n llamada \navisar\n que nos permite mostrar\nen pantalla un texto peque\u00f1o en la esquina izquierda inferior\nde la pantalla.\n\n\npilas.avisar(\nHola, esto es un mensaje.\n)\n\n\n\n\nEsto te facilitar\u00e1 mucho el c\u00f3digo en los programas\npeque\u00f1os como demostraciones o ejemplos.", 
            "title": "Textos"
        }, 
        {
            "location": "/texto/#textos", 
            "text": "Los objetos que muestran texto en pantalla se tratan de manera similar\na los actores. Por lo tanto, si ya sabes usar\nactores, no tendr\u00e1s problemas en usar cadenas\nde texto.", 
            "title": "Textos"
        }, 
        {
            "location": "/texto/#crear-cadenas-de-texto", 
            "text": "El objeto que representa texto se llama  Texto  y\nest\u00e1 dentro del modulo  actores .  Para crear un mensaje tienes que escribir:  texto = pilas.actores.Texto( Hola, este es mi primer texto. )  y tu cadena de texto aparecer\u00e1 en pantalla en color\nnegro y con un tama\u00f1o predeterminado:   Si quieres puedes escribir texto de varias lineas usando el caracter \\n  para indicar el salto de linea.  Por ejemplo, el siguiente c\u00f3digo escribe el mismo mensaje de\narriba pero en dos lineas:  texto = pilas.actores.Texto( Hola (en la primer linea)\\n este es mi primer texto. )", 
            "title": "Crear cadenas de texto"
        }, 
        {
            "location": "/texto/#los-textos-son-actores", 
            "text": "Al principio coment\u00e9 que los textos tambi\u00e9n son actores, esto\nsignifica que casi todo lo que puedes hacer con un actor\naqu\u00ed tambi\u00e9n funciona, por ejemplo:  texto.x = 100\ntexto.escala = 2  incluso tambi\u00e9n funcionar\u00e1n las interpolaciones:  texto.rotacion = pilas.interpolar(360)", 
            "title": "Los textos son actores"
        }, 
        {
            "location": "/texto/#propiedades-exclusivas-de-los-textos", 
            "text": "Existen varias propiedades que te permitir\u00e1n alterar la\napariencia de los textos.  Esta es una lista de los mas importantes.   color  magnitud  texto   Por ejemplo, para alterar el texto, color y tama\u00f1o de un\ntexto podr\u00eda escribir algo as\u00ed:  texto.magnitud = 50\ntexto.color = pilas.colores.Color(0, 0, 0)   # Color negro\ntexto.color = pilas.colores.Color(255, 0, 0, 128)   # Color rojo, semi transparente.\ntexto.texto =  Hola, este texto \\n tiene 2 lineas separadas", 
            "title": "Propiedades exclusivas de los textos"
        }, 
        {
            "location": "/texto/#mostrando-mensajes-en-pantalla", 
            "text": "Si bien podemos crear actores  Texto  y manipularlos como\nquedarmos, hay una forma a\u00fan mas sencilla de imprimir mensajes\npara los usuarios.  Existe una funci\u00f3n llamada  avisar  que nos permite mostrar\nen pantalla un texto peque\u00f1o en la esquina izquierda inferior\nde la pantalla.  pilas.avisar( Hola, esto es un mensaje. )  Esto te facilitar\u00e1 mucho el c\u00f3digo en los programas\npeque\u00f1os como demostraciones o ejemplos.", 
            "title": "Mostrando mensajes en pantalla"
        }, 
        {
            "location": "/habilidades/", 
            "text": "Habilidades\n\n\nPilas permite a\u00f1adir funcionalidad a tus objetos\nde manera sencilla, dado que usamos el concepto\nde habilidades, un enfoque similar a la\nprogramaci\u00f3n orientada a \ncomponentes\n\ny \nmixins\n.\n\n\nUn ejemplo\n\n\nUna habilidad es una funcionalidad que est\u00e1 implementada\nen alguna clase, y que si quieres la puedes vincular\na un actor cualquiera.\n\n\nVeamos un ejemplo, imagina que tienes un actor en\ntu escena y quieres que la rueda del mouse te permita\ncambiarle el tama\u00f1o.\n\n\nPuedes usar la habilidad \nAumentarConRueda\n y vincularla\nal actor f\u00e1cilmente.\n\n\nEl siguiente c\u00f3digo hace eso:\n\n\nimport pilasengine\n\npilas = pilasengine.iniciar()\n\nmono = pilas.actores.Mono()\nmono.aprender(pilas.habilidades.AumentarConRueda)\n\n\n\n\no bien:\n\n\nmono.aprender('AumentarConRueda')\n\n\n\nas\u00ed, cuando uses la rueda del mouse el tama\u00f1o del personaje aumentar\u00e1\no disminuir\u00e1.\n\n\nNota que aqu\u00ed usamos la met\u00e1fora de \"aprender habilidades\", porque\nlas habilidades son algo que duran para toda la vida\ndel actor.\n\n\nUn ejemplo m\u00e1s: hacer que un actor se pueda mover con el mouse\n\n\nAlgo muy com\u00fan en los juegos es que puedas\ntomar piezas con el mouse y moverlas por la pantalla.\n\n\nEsta habilidad llamada \nArrastrable\n representa eso, puedes vincularlo\na cualquier actor y simplemente funciona:\n\n\nimport pilasengine\n\npilas = pilasengine.iniciar()\n\nmono = pilas.actores.Mono()\nmono.aprender(\narrastrable\n)\n\n\n\n\nUna habilidad m\u00e1s compleja: Disparar\n\n\nUna habilidad que tiene m\u00e1s complejidad que las anteriores\nes disparar, una habilidad que te permite hacer que un\npersonaje pueda crear \"disparos\" sean de la clase que sea.\n\n\nPor ejemplo, lo mas sencillo es indicarle a un actor\nque puede disparar, usando una munici\u00f3n por omisi\u00f3n:\n\n\nimport pilasengine\n\npilas = pilasengine.iniciar()\n\nmono = pilas.actores.Mono()\nmono.aprender(\nmoverseComoCoche\n)\nmono.aprender(\ndisparar\n)\n\n\n\n\nY como resultado vamos a conseguir que nuestro\nactor se pueda mover con el teclado y disparar con la tecla\nespacio.\n\n\nY si queremos cambiar la munici\u00f3n de la habilidad\ndisparar, podemos especificarlo con el par\u00e1metro \nmunicion\n:\n\n\nmono.aprender(\ndisparar\n, municion=\naceituna\n)\n\n\n\n\nEsta habilidad tambi\u00e9n es \u00fatil para hacer un enemigo que dispare\nautom\u00e1ticamente cada determinado tiempo, por ejemplo 1 segundo:\n\n\nmono = pilas.actores.Mono()\nmono.aprender(\nDisparar\n, control=None)\n\ndef dispara():\n     mono.disparar()\n     return True\n\npilas.tareas.agregar(1, dispara)\n\n\n\n\nListado de habilidades existentes\n\n\n\n\n\n\n\n\nHabilidad\n\n\nPar\u00e1metros\n\n\n\n\n\n\n\n\n\n\nArrastrable\n\n\n\n\n\n\n\n\nAumentarConRueda\n\n\n\n\n\n\n\n\nDisparar\n\n\nmunicion, grupo_enemigos, cuando_elimina_enemigo, frecuencia_de_disparo, angulo_salida_disparo ...\n\n\n\n\n\n\nEliminarseSiSaleDePantalla\n\n\n\n\n\n\n\n\nImitar\n\n\nobjeto_a_imitar, con_escala, con_rotacion\n\n\n\n\n\n\nLimitadoABordesDePantalla\n\n\n\n\n\n\n\n\nMirarAlActor\n\n\nactor_a_seguir, lado_seguimiento=\"ARRIBA\"\n\n\n\n\n\n\nMoverseComoCoche\n\n\ncontrol, velocidad_maxima, aceleracion, deceleracion, rozamiento, velocidad_rotacion\n\n\n\n\n\n\nMoverseConElTeclado\n\n\ncontrol, direcciones, velocidad_maxima, aceleracion, con_rotacion, velocidad_rotacion, marcha_atras\n\n\n\n\n\n\nPuedeExplotar\n\n\n\n\n\n\n\n\nPuedeExplotarConHumo\n\n\n\n\n\n\n\n\nRebotarComoCaja\n\n\n\n\n\n\n\n\nRebotarComoPelota\n\n\n\n\n\n\n\n\nRotarConMouse\n\n\n\n\n\n\n\n\nSeMantieneEnPantalla\n\n\npermitir_salida\n\n\n\n\n\n\nSeguirAlMouse\n\n\n\n\n\n\n\n\nSeguirClicks\n\n\n\n\n\n\n\n\nSiempreEnElCentro\n\n\n\n\n\n\n\n\n\n\nCrear habilidades personalizadas\n\n\nPara crear una habilidad nueva, tienes que crear una clase\ny vincularla al m\u00f3dulo de habilidades.\n\n\nLa clase tiene que heredar de \npilasengine.habilidades.Habilidad\n y\npuede tener un m\u00e9todo \nactualizar\n, en donde generalmente se\ncoloca la acci\u00f3n a realizar:\n\n\nclass GirarPorSiempre(pilasengine.habilidades.Habilidad):\n\n    def actualizar(self):\n        self.receptor.rotacion += 1\n\npilas.habilidades.vincular(GirarPorSiempre)\n\nactor = pilas.actores.Actor()\nactor.aprender('GirarPorSiempre')\n\n\n\n\nEl m\u00e9todo \nactualizar\n de la habilidad se ejecutar\u00e1 60 veces por segundo, y\nen este caso har\u00e1n que cualquier actor que aprenda la habilidad \nGirarPorSiempre\n\nde vueltas constantemente.\n\n\nNot\u00e1 que dentro de los m\u00e9todos de la habilidad, la variable \nself.receptor\n apunta\nal actor que conoce a esa habilidad.\n\n\nPor \u00faltimo, en este ejemplo, vinculamos la nueva habilidad al m\u00f3dulo de\nhabilidades usando el m\u00e9todo \npilas.habilidades.vincular\n.\n\n\nArgumentos iniciales para las habilidades\n\n\nHay casos en donde queremos que las habilidades pueda recibir argumentos\niniciales, para esos casos necesitamos crear el m\u00e9todo \niniciar\n y configurarlo\ncorrectamente.\n\n\nSiguiendo con nuestro ejemplo, imagin\u00e1 que ahora queremos que esta habilidad\nnos permita hacer girar a los actores pero a diferentes velocidades: en algunos\ncasos queremos ense\u00f1ar a una actor a girar r\u00e1pido y a otro mas lento. \u00bfC\u00f3mo\nser\u00eda en pilas?.\n\n\nLo primero es crear la clase, muy parecida a la anterior, solamente que\nahora creamos el m\u00e9todo iniciar con dos argumentos, el primer es \nreceptor\n, que\nes obligatorio y el segundo es nuestro argumento de velocidad:\n\n\nclass GirarPorSiemprePersonalizado(pilasengine.habilidades.Habilidad):\n\n    def iniciar(self, receptor, velocidad):\n        self.receptor = receptor\n        self.velocidad = velocidad\n\n    def actualizar(self):\n        self.receptor.rotacion += self.velocidad\n\npilas.habilidades.vincular(GirarPorSiemprePersonalizado)\n\n\n\n\nAhora, la nueva habilidad necesita que le especifiquemos la velocidad\nal iniciar, as\u00ed que tenemos que usar algo as\u00ed:\n\n\nactor_lento = pilas.actores.Actor()\nactor_lento.aprender('GirarPorSiemprePersonalizado', 1)\n\nactor_rapido = pilas.actores.Actor(y=100)\nactor_rapido.aprender('GirarPorSiemprePersonalizado', 5)", 
            "title": "Habilidades"
        }, 
        {
            "location": "/habilidades/#habilidades", 
            "text": "Pilas permite a\u00f1adir funcionalidad a tus objetos\nde manera sencilla, dado que usamos el concepto\nde habilidades, un enfoque similar a la\nprogramaci\u00f3n orientada a  componentes \ny  mixins .", 
            "title": "Habilidades"
        }, 
        {
            "location": "/habilidades/#un-ejemplo", 
            "text": "Una habilidad es una funcionalidad que est\u00e1 implementada\nen alguna clase, y que si quieres la puedes vincular\na un actor cualquiera.  Veamos un ejemplo, imagina que tienes un actor en\ntu escena y quieres que la rueda del mouse te permita\ncambiarle el tama\u00f1o.  Puedes usar la habilidad  AumentarConRueda  y vincularla\nal actor f\u00e1cilmente.  El siguiente c\u00f3digo hace eso:  import pilasengine\n\npilas = pilasengine.iniciar()\n\nmono = pilas.actores.Mono()\nmono.aprender(pilas.habilidades.AumentarConRueda)  o bien:  mono.aprender('AumentarConRueda')  as\u00ed, cuando uses la rueda del mouse el tama\u00f1o del personaje aumentar\u00e1\no disminuir\u00e1.  Nota que aqu\u00ed usamos la met\u00e1fora de \"aprender habilidades\", porque\nlas habilidades son algo que duran para toda la vida\ndel actor.", 
            "title": "Un ejemplo"
        }, 
        {
            "location": "/habilidades/#un-ejemplo-mas-hacer-que-un-actor-se-pueda-mover-con-el-mouse", 
            "text": "Algo muy com\u00fan en los juegos es que puedas\ntomar piezas con el mouse y moverlas por la pantalla.  Esta habilidad llamada  Arrastrable  representa eso, puedes vincularlo\na cualquier actor y simplemente funciona:  import pilasengine\n\npilas = pilasengine.iniciar()\n\nmono = pilas.actores.Mono()\nmono.aprender( arrastrable )", 
            "title": "Un ejemplo m\u00e1s: hacer que un actor se pueda mover con el mouse"
        }, 
        {
            "location": "/habilidades/#una-habilidad-mas-compleja-disparar", 
            "text": "Una habilidad que tiene m\u00e1s complejidad que las anteriores\nes disparar, una habilidad que te permite hacer que un\npersonaje pueda crear \"disparos\" sean de la clase que sea.  Por ejemplo, lo mas sencillo es indicarle a un actor\nque puede disparar, usando una munici\u00f3n por omisi\u00f3n:  import pilasengine\n\npilas = pilasengine.iniciar()\n\nmono = pilas.actores.Mono()\nmono.aprender( moverseComoCoche )\nmono.aprender( disparar )  Y como resultado vamos a conseguir que nuestro\nactor se pueda mover con el teclado y disparar con la tecla\nespacio.  Y si queremos cambiar la munici\u00f3n de la habilidad\ndisparar, podemos especificarlo con el par\u00e1metro  municion :  mono.aprender( disparar , municion= aceituna )  Esta habilidad tambi\u00e9n es \u00fatil para hacer un enemigo que dispare\nautom\u00e1ticamente cada determinado tiempo, por ejemplo 1 segundo:  mono = pilas.actores.Mono()\nmono.aprender( Disparar , control=None)\n\ndef dispara():\n     mono.disparar()\n     return True\n\npilas.tareas.agregar(1, dispara)", 
            "title": "Una habilidad m\u00e1s compleja: Disparar"
        }, 
        {
            "location": "/habilidades/#listado-de-habilidades-existentes", 
            "text": "Habilidad  Par\u00e1metros      Arrastrable     AumentarConRueda     Disparar  municion, grupo_enemigos, cuando_elimina_enemigo, frecuencia_de_disparo, angulo_salida_disparo ...    EliminarseSiSaleDePantalla     Imitar  objeto_a_imitar, con_escala, con_rotacion    LimitadoABordesDePantalla     MirarAlActor  actor_a_seguir, lado_seguimiento=\"ARRIBA\"    MoverseComoCoche  control, velocidad_maxima, aceleracion, deceleracion, rozamiento, velocidad_rotacion    MoverseConElTeclado  control, direcciones, velocidad_maxima, aceleracion, con_rotacion, velocidad_rotacion, marcha_atras    PuedeExplotar     PuedeExplotarConHumo     RebotarComoCaja     RebotarComoPelota     RotarConMouse     SeMantieneEnPantalla  permitir_salida    SeguirAlMouse     SeguirClicks     SiempreEnElCentro", 
            "title": "Listado de habilidades existentes"
        }, 
        {
            "location": "/habilidades/#crear-habilidades-personalizadas", 
            "text": "Para crear una habilidad nueva, tienes que crear una clase\ny vincularla al m\u00f3dulo de habilidades.  La clase tiene que heredar de  pilasengine.habilidades.Habilidad  y\npuede tener un m\u00e9todo  actualizar , en donde generalmente se\ncoloca la acci\u00f3n a realizar:  class GirarPorSiempre(pilasengine.habilidades.Habilidad):\n\n    def actualizar(self):\n        self.receptor.rotacion += 1\n\npilas.habilidades.vincular(GirarPorSiempre)\n\nactor = pilas.actores.Actor()\nactor.aprender('GirarPorSiempre')  El m\u00e9todo  actualizar  de la habilidad se ejecutar\u00e1 60 veces por segundo, y\nen este caso har\u00e1n que cualquier actor que aprenda la habilidad  GirarPorSiempre \nde vueltas constantemente.  Not\u00e1 que dentro de los m\u00e9todos de la habilidad, la variable  self.receptor  apunta\nal actor que conoce a esa habilidad.  Por \u00faltimo, en este ejemplo, vinculamos la nueva habilidad al m\u00f3dulo de\nhabilidades usando el m\u00e9todo  pilas.habilidades.vincular .", 
            "title": "Crear habilidades personalizadas"
        }, 
        {
            "location": "/habilidades/#argumentos-iniciales-para-las-habilidades", 
            "text": "Hay casos en donde queremos que las habilidades pueda recibir argumentos\niniciales, para esos casos necesitamos crear el m\u00e9todo  iniciar  y configurarlo\ncorrectamente.  Siguiendo con nuestro ejemplo, imagin\u00e1 que ahora queremos que esta habilidad\nnos permita hacer girar a los actores pero a diferentes velocidades: en algunos\ncasos queremos ense\u00f1ar a una actor a girar r\u00e1pido y a otro mas lento. \u00bfC\u00f3mo\nser\u00eda en pilas?.  Lo primero es crear la clase, muy parecida a la anterior, solamente que\nahora creamos el m\u00e9todo iniciar con dos argumentos, el primer es  receptor , que\nes obligatorio y el segundo es nuestro argumento de velocidad:  class GirarPorSiemprePersonalizado(pilasengine.habilidades.Habilidad):\n\n    def iniciar(self, receptor, velocidad):\n        self.receptor = receptor\n        self.velocidad = velocidad\n\n    def actualizar(self):\n        self.receptor.rotacion += self.velocidad\n\npilas.habilidades.vincular(GirarPorSiemprePersonalizado)  Ahora, la nueva habilidad necesita que le especifiquemos la velocidad\nal iniciar, as\u00ed que tenemos que usar algo as\u00ed:  actor_lento = pilas.actores.Actor()\nactor_lento.aprender('GirarPorSiemprePersonalizado', 1)\n\nactor_rapido = pilas.actores.Actor(y=100)\nactor_rapido.aprender('GirarPorSiemprePersonalizado', 5)", 
            "title": "Argumentos iniciales para las habilidades"
        }, 
        {
            "location": "/depurando/", 
            "text": "Depurando y buscando detalles\n\n\nPilas incluye varios modos de ejecuci\u00f3n que te\npueden resultar de utilidad para ver en detalle\nel funcionamiento de tu juego.\n\n\nLa depuraci\u00f3n dentro de la prograci\u00f3n de juegos permite detectar errores, corregir\ndetalles e incluso comprender algunas interacciones complejas.\n\n\nModo pausa y manejo de tiempo\n\n\nSi pulsas las teclas \nALT + P\n durante la ejecuci\u00f3n de\npilas, el juego completo se detiene. En ese\nmomento puedes pulsar cualquier tecla\npara avanzar un instante de la simulaci\u00f3n o\nla tecla \nflecha derecha\n para avanzar mas r\u00e1pidamente.\n\n\nEsto es muy \u00fatil cuando trabajas con colisiones f\u00edsicas, porque\neste modo de pausa y manejo de tiempo te permite\nver en detalle la interacci\u00f3n de los objetos y detectar\ncualquier inconveniente r\u00e1pidamente.\n\n\nModos depuraci\u00f3n\n\n\nLas teclas \nF6\n, \nF7\n, \nF8\n, \nF9\n, \nF10\n, \nF11\n y \nF12\n te permiten\nhacer visibles los modos de depuraci\u00f3n.\n\n\nCada modo representa un aspecto interno del juego que podr\u00edas ver. Por ejemplo, el\nmodo que se activa con la tecla \nF12\n te permite ver la posici\u00f3n ex\u00e1cta de\ncada actor, mientras que al tecla \nF11\n te permite ver las figuras f\u00edsicas.\n\n\nActivar modos desde c\u00f3digo\n\n\nSi quieres que el juego inicie alguno de los modos, puedes usar la\nfunci\u00f3n \npilas.depurador.definir_modos\n. Por ejemplo, para habilitar el\nmodo depuraci\u00f3n f\u00edsica podr\u00edas escribir:\n\n\npilas.depurador.definir_modos(fisica=True)\n\n\n\nesta funci\u00f3n tiene varios argumentos opcionales, c\u00f3mo \nposicion\n, \nradios\n etc. Mira\nla definici\u00f3n de la funci\u00f3n para obtener mas detalles.\n\n\nActivando los modos para detectar errores\n\n\nTen en cuenta que puedes activar los modos depuraci\u00f3n en cualquier momento,\nincluso en medio de una pausa, ir del modo depuraci\u00f3n al\nmodo pausa y al rev\u00e9s. Los dos modos se pueden\ncombinar f\u00e1cilmente.\n\n\nMi recomendaci\u00f3n es que ante la menor duda, pulses \nalt + p\n para\nir al modo pausa, y luego comiences a pulsar alguna de las teclas para\nactivar los modos depuraci\u00f3n y observar en detalle qu\u00e9 est\u00e1 ocurriendo: \nF6\n , \nF7\n etc.", 
            "title": "Depurando"
        }, 
        {
            "location": "/depurando/#depurando-y-buscando-detalles", 
            "text": "Pilas incluye varios modos de ejecuci\u00f3n que te\npueden resultar de utilidad para ver en detalle\nel funcionamiento de tu juego.  La depuraci\u00f3n dentro de la prograci\u00f3n de juegos permite detectar errores, corregir\ndetalles e incluso comprender algunas interacciones complejas.", 
            "title": "Depurando y buscando detalles"
        }, 
        {
            "location": "/depurando/#modo-pausa-y-manejo-de-tiempo", 
            "text": "Si pulsas las teclas  ALT + P  durante la ejecuci\u00f3n de\npilas, el juego completo se detiene. En ese\nmomento puedes pulsar cualquier tecla\npara avanzar un instante de la simulaci\u00f3n o\nla tecla  flecha derecha  para avanzar mas r\u00e1pidamente.  Esto es muy \u00fatil cuando trabajas con colisiones f\u00edsicas, porque\neste modo de pausa y manejo de tiempo te permite\nver en detalle la interacci\u00f3n de los objetos y detectar\ncualquier inconveniente r\u00e1pidamente.", 
            "title": "Modo pausa y manejo de tiempo"
        }, 
        {
            "location": "/depurando/#modos-depuracion", 
            "text": "Las teclas  F6 ,  F7 ,  F8 ,  F9 ,  F10 ,  F11  y  F12  te permiten\nhacer visibles los modos de depuraci\u00f3n.  Cada modo representa un aspecto interno del juego que podr\u00edas ver. Por ejemplo, el\nmodo que se activa con la tecla  F12  te permite ver la posici\u00f3n ex\u00e1cta de\ncada actor, mientras que al tecla  F11  te permite ver las figuras f\u00edsicas.", 
            "title": "Modos depuraci\u00f3n"
        }, 
        {
            "location": "/depurando/#activar-modos-desde-codigo", 
            "text": "Si quieres que el juego inicie alguno de los modos, puedes usar la\nfunci\u00f3n  pilas.depurador.definir_modos . Por ejemplo, para habilitar el\nmodo depuraci\u00f3n f\u00edsica podr\u00edas escribir:  pilas.depurador.definir_modos(fisica=True)  esta funci\u00f3n tiene varios argumentos opcionales, c\u00f3mo  posicion ,  radios  etc. Mira\nla definici\u00f3n de la funci\u00f3n para obtener mas detalles.", 
            "title": "Activar modos desde c\u00f3digo"
        }, 
        {
            "location": "/depurando/#activando-los-modos-para-detectar-errores", 
            "text": "Ten en cuenta que puedes activar los modos depuraci\u00f3n en cualquier momento,\nincluso en medio de una pausa, ir del modo depuraci\u00f3n al\nmodo pausa y al rev\u00e9s. Los dos modos se pueden\ncombinar f\u00e1cilmente.  Mi recomendaci\u00f3n es que ante la menor duda, pulses  alt + p  para\nir al modo pausa, y luego comiences a pulsar alguna de las teclas para\nactivar los modos depuraci\u00f3n y observar en detalle qu\u00e9 est\u00e1 ocurriendo:  F6  ,  F7  etc.", 
            "title": "Activando los modos para detectar errores"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/", 
            "text": "\u00bfC\u00f3mo funciona pilas por dentro?\n\n\nNOTA: Esta secci\u00f3n describe el funcionamiento interno de la\nversi\u00f3n 0.83 de pilas-engine, que si bien no es la versi\u00f3n m\u00e1s\nreciente, muchas instrucciones son \u00fatiles para entender el funcionamiento\ninterno de la aplicaci\u00f3n.\n\n\nPilas es un proyecto con una arquitectura de objetos\ngrande. Tiene mucha funcionalidad, incluye un\nmotor de f\u00edsica, muchos personaje pre-dise\u00f1ados, eventos, escenas\ny un enlace al motor multimedia Qt.\n\n\nMediante este cap\u00edtulo quisiera explicar a grandes\nrasgos los componentes de pilas. C\u00f3mo est\u00e1n estructurados\nlos m\u00f3dulos, y qu\u00e9 hacen las clases mas importantes.\n\n\nEl objetivo es orientar a los programadores mas\navanzados para que puedan investigar pilas\npor dentro.\n\n\nFilosof\u00eda de desarrollo\n\n\nPilas es un proyecto de software libre, orientado a facilitar\nel desarrollo de videojuegos a personas que generalmente no\nhacen juegos... Por ese motivo que gran parte de las decisiones de\ndesarrollo se tomaron reflexionando sobre c\u00f3mo\ndise\u00f1ar una interfaz de programaci\u00f3n simple y f\u00e1cil\nde utilizar.\n\n\nUn ejemplo de ello, es que elegimos el lenguaje de\nprogramaci\u00f3n python, y tratamos de aprovechar al m\u00e1ximo\nsu modo interactivo.\n\n\nAPI en espa\u00f1ol\n\n\nDado que pilas est\u00e1 orientado a principiantes, docentes y\nprogramadores de habla hispana. Preferimos hacer el motor\nen espa\u00f1ol, permitirle a los mas chicos usar su idioma\npara hacer juegos es alentador, tanto para ellos que\nobservan que el idioma no es una barrera, como\npara los que ense\u00f1amos y queremos entusiasmar.\n\n\nEsta es una decisi\u00f3n de dise\u00f1o importante, porque al\nmismo tiempo que incluye a muchas personas, no coincide\ncon lo que acostumbran muchos programadores (escribir\nen ingl\u00e9s).\n\n\nPosiblemente en el futuro podamos ofrecer una\nversi\u00f3n de pilas alternativa en ingl\u00e9s, pero\nactualmente no es una prioridad.\n\n\nBibliotecas que usa pilas\n\n\nHay tres grandes bibliotecas que se utilizan dentro de pilas:\n\n\n\n\nBox2D\n\n\nQt4\n\n\n\n\nBox2D se utiliza c\u00f3mo motor de f\u00edsica, mientras que Qt es un\nmotor multimedia utilizado para dibujar, reproducir sonidos y\nmanejar eventos.\n\n\nObjetos y m\u00f3dulos\n\n\nPilas incluye muchos objetos y es un sistema complejo. Pero\nhay una forma sencilla de abordarlo, porque hay solamente\n3 componentes que son indispensables, y han\nsido los pilares desde las primeras versiones de pilas\nhasta la fecha:\n\n\n\n\nMundo\n\n\nActor\n\n\nMotor\n\n\n\n\nSi puedes comprender el rol y las caracter\u00edsticas\nde estos 3 componentes el resto del motor es mas\nf\u00e1cil de analizar.\n\n\nVeamos los 3 componentes r\u00e1pidamente:\n\n\nMundo\n es un objeto \nsingleton\n, hay una sola instancia\nde esta clase en todo el sistema y se encarga de\nmantener el juego en funcionamiento e interactuando con\nel usuario.\n\n\nLos actores (clase \nActor\n) representan a los personajes de los\njuegos, la clase se encarga de representar todos sus atributos\ncomo la posici\u00f3n y comportamiento como \"dibujarse en la ventana\". Si\nhas usado otras herramientas para hacer juegos, habr\u00e1s notado\nque se los denomina \nSprites\n.\n\n\nLuego, el \nMotor\n, permite que pilas sea un motor\nmultimedia portable y multiplaforma. B\u00e1sicamente\npilas delega la tarea de dibujar, emitir sonidos y controlar\neventos a una biblioteca externa. Actualmente esa biblioteca\nes Qt, pero en versiones anteriores ha sido implementada en pygame y\nsfml.\n\n\nAhora que lo he mencionado, veamos con un poco mas\nde profundidad lo que hace cada uno.\n\n\nInspeccionando: Mundo\n\n\nEl objeto de la clase Mundo se construye cuando se invoca a la\nfunci\u00f3n \npilas.iniciar\n. Su implementaci\u00f3n est\u00e1 en el\narchivo \nmundo.py\n.\n\n\nSu responsabilidad es inicializar varios componentes de pilas, como\nel sistema de controles, la ventana, etc.\n\n\nUno de sus m\u00e9todos mas importantes es \nejecutar_bucle_principal\n. Un\nm\u00e9todo que se invoca directamente cuando alguien escribe\nla sentencia \npilas.ejecutar()\n.\n\n\nSi observas el c\u00f3digo, notar\u00e1s que es el responsable de mantener a todo\nel motor en funcionamiento.\n\n\nEsta es una versi\u00f3n muy simplificada del\nm\u00e9todo \nejecutar_bucle_principal\n:\n\n\ndef ejecutar_bucle_principal(self, ignorar_errores=False):\n\n    while not self.salir:\n        pilas.motor.procesar_y_emitir_eventos()\n\n        if not self.pausa_habilitada:\n            self._realizar_actualizacion_logica(ignorar_errores)\n\n        self._realizar_actualizacion_grafica()\n\n\n\nLo primero que debemos tener en cuenta es que este m\u00e9todo contiene\nun bucle \nwhile\n que lo mantendr\u00e1 en ejecuci\u00f3n. Este bucle\nsolo se detendr\u00e1 cuando alguien llame al m\u00e9todo \nterminar\n (que\ncambia el valor de la variable \nsalir\n a \nTrue\n).\n\n\nLuego hay tres m\u00e9todos importantes:\n\n\n\n\nprocesar_y_emitir_eventos\n analiza el estado de los controles y avisa al resto del sistema si ocurre algo externo, como el movimiento del mouse..\n\n\n_realizar_actualizacion_logica\n le permite a los personajes realizar una fracci\u00f3n muy peque\u00f1a de movimiento, poder leer el estado de los controles o hacer otro tipo de acciones.\n\n\n_realizar_actualizacion_logica\n simplemente vuelca sobre la pantalla a todos los actores y muestra el resultado del dibujo al usuario.\n\n\n\n\nOtra tarea que sabe hacer el objeto \nMundo\n, es administrar\nescenas. Las escenas son objetos que representan una\nparte individual del juego: un men\u00fa, una pantalla de opciones, el\nmomento de acci\u00f3n del juego etc...\n\n\nModo interactivo\n\n\nPilas soporta dos modos de funcionamiento, que t\u00e9cnicamente son\nmuy similares, pero que a la hora de programar hacen una gran\ndiferencia.\n\n\n\n\n\n\nmodo normal\n: si est\u00e1s haciendo un archivo \n.py\n con el c\u00f3digo de tu juego usar\u00e1s este modo, tu programa comienza con una sentencia como \niniciar\n y la simulaci\u00f3n se inicia cuando llamas a \npilas.ejecutar\n (que se encarga de llamar a \nejecutar_bucle_principal\n del objeto mundo).\n\n\n\n\n\n\nmodo interactivo\n: el modo que generalmente se usa en las demostraciones o cursos es el modo interactivo. Este modo funciona gracias a una estructura de hilos, que se encargan de ejecutar la simulaci\u00f3n pero a la vez no interrumpe al programador y le permite ir escribiendo c\u00f3digo mientras la simulaci\u00f3n est\u00e1 en funcionamiento.\n\n\n\n\n\n\nMotores multimedia\n\n\nAl principio pilas delegaba todo el manejo multimedia a una\nbiblioteca llamada SFML. Pero esta biblioteca requer\u00eda que todos los equipos\nen donde funcionan tengan aceleradoras gr\u00e1ficas (al menos con\nsoporte OpenGL b\u00e1sico).\n\n\nPero como queremos que pilas funcione en la mayor cantidad\nde equipos, incluso en los equipos antiguos de algunas\nescuelas, reemplazamos el soporte multimedia con la biblioteca Qt. Que sabe\nacceder a las funciones de aceleraci\u00f3n de gr\u00e1ficos (si est\u00e1n disponibles), o\nbrinda una capa de compatibilidad con equipos antiguos.\n\n\nLa funci\u00f3n que permite iniciar y seleccionar el motor es \npilas.iniciar\n.\n\n\npilas.iniciar(usar_motor='qt')\n\n\n\nAhora bien, \u00bfc\u00f3mo funciona?. Dado que pilas est\u00e1 realizado\nusando orientaci\u00f3n a objetos, usamos un concepto llamado\npolimorfismo:\n\n\nEl objeto motor sabe que tiene que delegar el manejo multimedia\na una instancia (o derivada) de la clase \nMotor\n (ver directorio\n\npilas/motores/\n.\n\n\nEl motor expone toda la funcionalidad que se necesita para\nhace un juego: sabe crear una ventana, pintar una imagen o\nreproducir sonidos, entre tantas otras cosas.\n\n\nEl objeto mundo no sabe exactamente que motor est\u00e1 utilizando, solo\ntiene una referencia a un motor y delega en \u00e9l todas las\ntareas multimedia.\n\n\nSolo puede haber una instancia de motor en funcionamiento, y\nse define cuando se inicia el motor.\n\n\nSistema de actores\n\n\nLos actores permiten que los juegos cobren atractivo, porque\nun actor puede representarse con una imagen en pantalla.\n\n\nLa implementaci\u00f3n de todos los actores est\u00e1n en\nel directorio \npilas/actores\n.\n\n\nTodos los actores heredan de la clase \nActor\n, que define\nel comportamiento com\u00fan de todos los actores.\n\n\nPor ejemplo, esta ser\u00eda una versi\u00f3n reducida de la\njerarqu\u00eda de clases de los actores Mono, Pingu y Tortuga.\n\n\nHay dos m\u00e9todos en los actores que se invocar\u00e1n en\ntodo momento: el m\u00e9todo \nactualizar\n se invocar\u00e1\ncuando el bucle de juego del mundo llame al m\u00e9todo\n\n_realizar_actualizacion_logica\n, esto ocurre unas\n60 veces por segundo. Y el otro m\u00e9todo es \ndibujar\n, que\nse tambi\u00e9n se invoca desde el objeto mundo, pero esta\nvez en el m\u00e9todo \n_realizar_actualizacion_grafica\n.\n\n\nModo depuraci\u00f3n\n\n\nCuando pulsas teclas como F8, F9, F10, F11 o F12 durante\nla ejecuci\u00f3n de pilas, vas a ver que la pantalla comienza\na mostrar informaci\u00f3n valiosa para los desarrolladores.\n\n\nEsta modalidad de dibujo la llamamos \nmodo depuraci\u00f3n\n, y\nayuda mucho a la hora de encontrar errores o ajustar detalles.\n\n\nEl objeto \nMundo\n, que mantiene en ejecuci\u00f3n al juego, tiene\nuna instancia de objeto \nDepurador\n que se encarga de\nhacer estos dibujos.\n\n\nLas clases mas importantes a la hora de investigar el depurador\nest\u00e1n en el archivo \ndepurador.py\n.\n\n\nEl Depurador tiene dos atributos, tiene una pizarra para dibujar y\nuna lista de modos. Los modos pueden ser cualquiera de los que est\u00e1n\nen la jerarqu\u00eda de ModoDepuracion, por ejemplo, podr\u00eda tener\ninstancias de ModoArea y ModoPuntoDeControl.\n\n\nSistema de eventos\n\n\nHay varios enfoques para resolver el manejo de eventos\nen los videojuegos.\n\n\nPilas usa un modelo conocido y elaborado\nllamado \nObservator\n, un patr\u00f3n de dise\u00f1o. Pero que\nlamentablemente no es muy intuitivo a primera vista.\n\n\nEn esta secci\u00f3n intentar\u00e9 mostrar por qu\u00e9 usamos\nesa soluci\u00f3n y qu\u00e9 problemas nos ayuda a resolver.\n\n\nComenzar\u00e9 explicando sobre el problema de gestionar eventos\ny luego c\u00f3mo el modelo \nObservator\n se volvi\u00f3\nuna buena soluci\u00f3n para el manejo de eventos.\n\n\nEl problema: pooling de eventos\n\n\nOriginalmente, en un modelo muy simple de aplicaci\u00f3n multimedia,\nmanejar eventos de usuario es algo sencillo, pero con el\ntiempo comienza a crecer y se hace cada vez mas dif\u00edcil de\nmantener.\n\n\nResulta que las bibliotecas multimedia suelen entregar un\nobjeto \nevento\n cada vez que ocurre algo y tu responsabilidad\nes consultar sobre ese objeto en b\u00fasqueda de datos.\n\n\nImagina que quieres crear un actor \nBomba\n cada\nvez que el usuario hace click en la pantalla. El\nc\u00f3digo podr\u00eda ser algo as\u00ed:\n\n\nevento = obtener_evento_actual()\n\nif evento.tipo == 'click_de_mouse':\n    crear_bomba(evento.x)\n    crear_bomba(evento.x)\nelse:\n    # el evento de otro tipo (teclado, ventana ...)\n    # lo descartamos.\n\n\n\nA esta soluci\u00f3n podr\u00edamos llamarla \npreguntar\n y \nresponder\n,\nporque efectivamente as\u00ed funciona el c\u00f3digo, primero\nnos aseguramos de que el evento nos importa y luego\nhacemos algo. En algunos sitios suelen llamar a esta\nestrategia \npooling\n.\n\n\nPero este enfoque tiene varios problemas, y cuando hacemos\njuegos o bibliotecas se hace mas evidente. El c\u00f3digo, a medida\nque crece, comienza a mezclar manejo de eventos y l\u00f3gica\ndel juego.\n\n\nPara ver el problema de cerca, imagina que en determinadas\nocasiones quieres deshabilitar la creaci\u00f3n de bombas, \u00bfc\u00f3mo\nhar\u00edas?. \u00bfY si quieres que las bombas creadas se puedan\nmover con el teclado?.\n\n\nOtro enfoque, en pilas usamos 'Observator'\n\n\nHay otro enfoque para el manejo de eventos que me parece\nmas interesante, y lo he seleccionado para el motor\n\npilas\n:\n\n\nEn lugar de administrar los eventos uno a uno por\n\nconsultas\n, delegamos esa tarea a un sistema que nos\npermite \nsuscribir\n y \nser notificado\n.\n\n\nAqu\u00ed no mezclamos nuestro c\u00f3digo con el sistema de eventos, si\nqueremos hacer algo relacionado con un evento, escribimos\nuna funci\u00f3n y le pedimos al evento que llame a nuestra\nfunci\u00f3n cuando sea necesario.\n\n\nVeamos el ejemplo anterior pero usando este enfoque, se\ncrear\u00e1 una \nBomba\n cada vez que el usuario\nhace \nclick\n en la pantalla:\n\n\ndef crear_bomba(evento):\n    pilas.actores.Bomba(x=evento.x, y=evento.y)\n    return true\n\npilas.eventos.click_de_mouse.conectar(crear_bomba)\n\n\n\nSi queremos que el mouse deje de crear bombas, podemos\nejecutar la funci\u00f3n \ndesconectar\n:\n\n\npilas.eventos.click_de_mouse.conectar(crear_bomba)\n\n\n\no simplemente retornar \nFalse\n en la funci\u00f3n \ncrear_bomba\n.\n\n\nNuestro c\u00f3digo tendr\u00e1 \nbajo acoplamiento\n con los eventos\ndel motor, y no se nos mezclar\u00e1n.\n\n\nDe hecho, cada vez que tengas dudas sobre las funciones\nsuscritas a eventos pulsa F7 y se imprimir\u00e1n en pantalla.\n\n\n\u00bfC\u00f3mo funciona?\n\n\nAhora bien, \u00bfc\u00f3mo funciona el sistema de eventos por dentro?:\n\n\nEl sistema de eventos que usamos es una ligera adaptaci\u00f3n\ndel sistema de se\u00f1ales de django (un framework para desarrollo\nde sitios web) d\u00f3nde cada evento es un objeto que puede\nhacer dos cosas:\n\n\n\n\nsuscribir funciones.\n\n\ninvocar a las funciones que se han suscrito.\n\n\n\n\n1 Suscribir\n\n\nPor ejemplo, el evento \nmueve_mouse\n es un objeto, y cuando\ninvocamos la sentencia \npilas.eventos.mueve_mouse.conectar(mi_funcion)\n,\nle estamos diciendo al objeto \"quiero que guardes una referencia\na \nmi_funcion\n\".\n\n\nPuedes imaginar al evento como un objeto contenedor (similar\na una lista), que guarda cada una de las funciones que le enviamos\ncon el m\u00e9todo \nconectar\n.\n\n\n2 Notificar\n\n\nLa segunda tarea del evento es notificar a todas\nlas funciones que se suscribieron.\n\n\nEsto se hace, retomando el ejemplo anterior, cuando el usuario\nhace click con el mouse.\n\n\nLos eventos son objetos \nSignal\n y se inicializan en el\narchivo \neventos.py\n, cada uno con sus respectivos\nargumentos o detalles:\n\n\nclick_de_mouse = Evento(\"click_de_mouse\")\npulsa_tecla = Evento(\"pulsa_tecla\")\n[ etc...]\n\n\n\nLos argumentos indican informaci\u00f3n adicional del evento, en\nel caso del click, observar\u00e1s que los argumentos son el bot\u00f3n pulsado\ny la coordenada del puntero.\n\n\nCuando se quiere notificar a las funciones conectadas a\nun evento simplemente se tiene que invocar al m\u00e9todo \nemitir\n\ndel evento y proveer los argumentos que necesita:\n\n\nclick_de_mouse.emitir(button=1, x=30, y=50)\n\n\n\nEso har\u00e1 que todas las funciones suscritas al evento \nclick_de_mouse\n\nse invoquen con el argumento \nevento\n representando esos detalles:\n\n\ndef crear_bomba(evento):\n\n    print(evento.x)\n    # imprimir\u00e1 30\n\n    print(evento.y)\n    # imprimir\u00e1 50\n\n    [ etc...]\n\n\n\nLa parte de pilas que se encarga de llamar a los m\u00e9todos \nemitir\n\nes el m\u00e9todo \nprocesar_y_emitir_eventos\n del motor.\n\n\nHabilidades\n\n\nLos actores de pilas tienen la cualidad de poder\nir obteniendo comportamiento desde otras clases.\n\n\nEsto te permite lograr resultados de forma r\u00e1pida, y\na la vez, es un modelo tan flexible que podr\u00edas\nhacer muchos juegos distintos combinando los mismos\nactores pero con distintas habilidades.\n\n\nVeamos un ejemplo, un actor sencillo como \nMono\n no\nhace muchas cosas. Pero si escribimos lo siguiente, podremos\ncontrolarlo con el mouse:\n\n\nmono = pilas.actores.Mono()\nmono.aprender(pilas.habilidades.Arrastrable)\n\n\n\nLo que en realidad estamos haciendo, es vincular dos objetos\nen tiempo de ejecuci\u00f3n. \nmono\n es un objeto \nActor\n, y tiene una\nlista de habilidades que puede aumentar usando el m\u00e9todo \naprender\n.\n\n\nEl m\u00e9todo \naprender\n toma la clase que le enviamos como\nargumento, construye un objeto y lo guarda en su lista de habilidades.\n\n\nEste es un modelo de c\u00f3mo se conocen las clases entre\ns\u00ed:\n\n\nEntonces, una vez que invocamos a la sentencia, nuestro actor\ntendr\u00e1 un nuevo objeto en su lista de habilidades, listo para\nejecutarse en cada cuadro de animaci\u00f3n.\n\n\n\u00bfC\u00f3mo se ejecutan las habilidades?\n\n\nRetomando un poco lo que vimos al principio de este cap\u00edtulo, lo\nque mantiene con \nvida\n al juego es el bucle principal, la clase\n\nMundo\n tiene un bucle que recorre la lista de actores en pantalla\ny por cada uno llama al m\u00e9todo actualizar.\n\n\nBien, las habilidades se mantienen en ejecuci\u00f3n desde ah\u00ed tambi\u00e9n. Esta\nes una versi\u00f3n muy simplificada del bucle que encontrar\u00e1s en el\narchivo ``mundo.py```:\n\n\ndef ejecutar_bucle_principal(self, ignorar_errores=False):\n\n    while not self.salir:\n        self.actualizar_actores()\n\n        [ etc ...]\n\ndef actualizar_actores(self):\n    for actor in pilas.actores.todos:\n        actor.actualizar()\n        actor.actualizar_habilidades()\n\n\n\nAqu\u00ed puedes ver dos llamadas a m\u00e9todos del actor, el m\u00e9todo\n\nactualizar\n se cre\u00f3 para que cada programador escriba\nah\u00ed lo que quiera que el personaje haga (leer el teclado,\nhacer validaciones, moverse etc). Y el m\u00e9todo \nactualizar_habilidades\n\nes el encargado de \ndar vida\n a las habilidades.\n\n\nT\u00e9cnicamente hablando, el m\u00e9todo \nactualizar_habilidades\n es\nmuy simple, solamente toma la lista de objetos habilidades y\nlos actualiza, al \nActor\n no le preocupa en lo mas m\u00ednimo\n\"qu\u00e9\" hace cada habilidad, solamente les permite ejecutar c\u00f3digo\n(ver c\u00f3digo \nestudiante.py\n, una superclase de \nActor\n):\n\n\ndef actualizar_habilidades(self):\n    for h in self.habilidades:\n        h.actualizar()\n\n\n\nEntonces, si queremos que un actor haga muchas cosas, podemos\ncrear un objeto habilidad y vincularlo con el actor. Esto\npermite generar \"comportamientos\" re-utilizables, la habilidad\nse codifica una vez, y se puede usar muchas veces.\n\n\nObjetos habilidad\n\n\nLas habilidades interact\u00faan con los actores, y por ese motivo\ntienen que tener una interfaz en com\u00fan, de modo tal que\ndesde cualquier parte de pilas puedas tratar a una habilidad\ncomo a cualquier otra.\n\n\nLa interfaz que toda habilidad debe tener es la que define\nla clase \nHabilidad\n del archivo \nhabilidades.py\n:\n\n\nclass Habilidad:\n\n    def __init__(self, receptor):\n        self.receptor = receptor\n\n    def actualizar(self):\n        pass\n\n    def eliminar(self):\n        pass\n\n\n\nTiene que tener tres m\u00e9todos, uno que se ejecuta al producirle\nla relaci\u00f3n con un actor, un m\u00e9todo que se ejecutar\u00e1 en\ncada iteraci\u00f3n del bucle de juego (\nactualizar\n) y un\n\u00faltimo m\u00e9todo para ejecutar cuando la habilidad se desconecta\ndel actor. Este m\u00e9todo \neliminar\n suele ser el que desconecta\neventos o cualquier otra cosa creada temporalmente.\n\n\nTen en cuenta que el m\u00e9todo \n__init__\n, que construye\nal objeto, lo invoca el propio actor desde su m\u00e9todo \naprender\n. Y\nel argumento \nreceptor\n ser\u00e1 una referencia al actor que\n\naprende\n la habilidad.\n\n\nVeamos un ejemplo muy b\u00e1sico, imagina que quieres hacer\nuna habilidad muy simple, que gire al personaje todo el\ntiempo, c\u00f3mo una aguja de reloj. Podr\u00edas hacer\nalgo as\u00ed:\n\n\nclass GirarPorSiempre(pilas.habilidades.Habilidad):\n\n    def __init__(self, receptor):\n        self.receptor = receptor\n\n    def actualizar(self):\n        self.receptor.rotacion += 1\n\nmono = pilas.actores.Mono()\nmono.aprender(GirarPorSiempre)\n\n\n\nLa sentencia \naprender\n construir\u00e1 un objeto de la\nclase que le indiquemos, y el bucle de pilas (en \nmundo.py\n)\ndar\u00e1 la orden para ejecutar los m\u00e9todos actualizar de\ncada habilidad conocida por los actores.\n\n\nArgumentos de las habilidades\n\n\nEn el ejemplo anterior podr\u00edamos encontrar una\nlimitaci\u00f3n. El actor siempre girar\u00e1 a la misma velocidad.\n\n\nSi queremos que los personajes puedan girar a diferentes\nvelocidades tendr\u00edamos que agregarle argumentos\na la habilidad, esto es simple: solo tienes que llamar\nal m\u00e9todo \naprender\n con los argumentos que quieras\ny asegurarte de que la habilidad los tenga definidos en\nsu m\u00e9todo \n__init__\n.\n\n\nEste es un ejemplo de la habilidad pero que permite\ndefinir la velocidad de giro:\n\n\nclass GirarPorSiempre(pilas.habilidades.Habilidad):\n\n    def __init__(self, receptor, velocidad=1):\n        self.receptor = receptor\n        self.velocidad = velocidad\n\n    def actualizar(self):\n        self.receptor.rotacion += self.velocidad\n\na = pilas.actores.Mono()\na.aprender(GirarPorSiempre, 20)\n\n\n\nListo, es casi id\u00e9ntico al anterior, si llamas a \naprender\n con un\nargumento como \n20\n, el actor girar\u00e1 mucho mas r\u00e1pido que\nantes. Y si no especificas la velocidad, se asumir\u00e1 que la\nvelocidad es \n1\n, porque as\u00ed lo indica el m\u00e9todo \n__init__\n.\n\n\nDocumentaci\u00f3n\n\n\nEl sistema de documentaci\u00f3n que usamos en pilas\nes Sphinx, un sistema muy interesante porque nos\npermite gestionar todo el contenido del manual\nen texto plano, y gracias a varias herramientas\nde conversi\u00f3n c\u00f3mo restructuredText y latex, se\nproducen muchos formatos de salida c\u00f3mo HTML y PDF.\n\n\nToda la documentaci\u00f3n del proyecto est\u00e1 en el\ndirectorio \ndoc\n. El directorio \ndoc/sources\n contiene\ntodos los archivos que modificamos para escribir contenido\nen la documentaci\u00f3n.\n\n\nPara generar los archivos PDF o HTML usamos el comando\n\nmake\n dentro del directorio \ndoc\n. El archivo que\ndispara todas las acciones que sphinx sabe hacer est\u00e1n\ndefinidas en el archivo \nMakefile\n.", 
            "title": "\u00bfC\u00f3mo funciona pilas por dentro?"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#como-funciona-pilas-por-dentro", 
            "text": "NOTA: Esta secci\u00f3n describe el funcionamiento interno de la\nversi\u00f3n 0.83 de pilas-engine, que si bien no es la versi\u00f3n m\u00e1s\nreciente, muchas instrucciones son \u00fatiles para entender el funcionamiento\ninterno de la aplicaci\u00f3n.  Pilas es un proyecto con una arquitectura de objetos\ngrande. Tiene mucha funcionalidad, incluye un\nmotor de f\u00edsica, muchos personaje pre-dise\u00f1ados, eventos, escenas\ny un enlace al motor multimedia Qt.  Mediante este cap\u00edtulo quisiera explicar a grandes\nrasgos los componentes de pilas. C\u00f3mo est\u00e1n estructurados\nlos m\u00f3dulos, y qu\u00e9 hacen las clases mas importantes.  El objetivo es orientar a los programadores mas\navanzados para que puedan investigar pilas\npor dentro.", 
            "title": "\u00bfC\u00f3mo funciona pilas por dentro?"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#filosofia-de-desarrollo", 
            "text": "Pilas es un proyecto de software libre, orientado a facilitar\nel desarrollo de videojuegos a personas que generalmente no\nhacen juegos... Por ese motivo que gran parte de las decisiones de\ndesarrollo se tomaron reflexionando sobre c\u00f3mo\ndise\u00f1ar una interfaz de programaci\u00f3n simple y f\u00e1cil\nde utilizar.  Un ejemplo de ello, es que elegimos el lenguaje de\nprogramaci\u00f3n python, y tratamos de aprovechar al m\u00e1ximo\nsu modo interactivo.", 
            "title": "Filosof\u00eda de desarrollo"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#api-en-espanol", 
            "text": "Dado que pilas est\u00e1 orientado a principiantes, docentes y\nprogramadores de habla hispana. Preferimos hacer el motor\nen espa\u00f1ol, permitirle a los mas chicos usar su idioma\npara hacer juegos es alentador, tanto para ellos que\nobservan que el idioma no es una barrera, como\npara los que ense\u00f1amos y queremos entusiasmar.  Esta es una decisi\u00f3n de dise\u00f1o importante, porque al\nmismo tiempo que incluye a muchas personas, no coincide\ncon lo que acostumbran muchos programadores (escribir\nen ingl\u00e9s).  Posiblemente en el futuro podamos ofrecer una\nversi\u00f3n de pilas alternativa en ingl\u00e9s, pero\nactualmente no es una prioridad.", 
            "title": "API en espa\u00f1ol"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#bibliotecas-que-usa-pilas", 
            "text": "Hay tres grandes bibliotecas que se utilizan dentro de pilas:   Box2D  Qt4   Box2D se utiliza c\u00f3mo motor de f\u00edsica, mientras que Qt es un\nmotor multimedia utilizado para dibujar, reproducir sonidos y\nmanejar eventos.", 
            "title": "Bibliotecas que usa pilas"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#objetos-y-modulos", 
            "text": "Pilas incluye muchos objetos y es un sistema complejo. Pero\nhay una forma sencilla de abordarlo, porque hay solamente\n3 componentes que son indispensables, y han\nsido los pilares desde las primeras versiones de pilas\nhasta la fecha:   Mundo  Actor  Motor   Si puedes comprender el rol y las caracter\u00edsticas\nde estos 3 componentes el resto del motor es mas\nf\u00e1cil de analizar.  Veamos los 3 componentes r\u00e1pidamente:  Mundo  es un objeto  singleton , hay una sola instancia\nde esta clase en todo el sistema y se encarga de\nmantener el juego en funcionamiento e interactuando con\nel usuario.  Los actores (clase  Actor ) representan a los personajes de los\njuegos, la clase se encarga de representar todos sus atributos\ncomo la posici\u00f3n y comportamiento como \"dibujarse en la ventana\". Si\nhas usado otras herramientas para hacer juegos, habr\u00e1s notado\nque se los denomina  Sprites .  Luego, el  Motor , permite que pilas sea un motor\nmultimedia portable y multiplaforma. B\u00e1sicamente\npilas delega la tarea de dibujar, emitir sonidos y controlar\neventos a una biblioteca externa. Actualmente esa biblioteca\nes Qt, pero en versiones anteriores ha sido implementada en pygame y\nsfml.  Ahora que lo he mencionado, veamos con un poco mas\nde profundidad lo que hace cada uno.", 
            "title": "Objetos y m\u00f3dulos"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#inspeccionando-mundo", 
            "text": "El objeto de la clase Mundo se construye cuando se invoca a la\nfunci\u00f3n  pilas.iniciar . Su implementaci\u00f3n est\u00e1 en el\narchivo  mundo.py .  Su responsabilidad es inicializar varios componentes de pilas, como\nel sistema de controles, la ventana, etc.  Uno de sus m\u00e9todos mas importantes es  ejecutar_bucle_principal . Un\nm\u00e9todo que se invoca directamente cuando alguien escribe\nla sentencia  pilas.ejecutar() .  Si observas el c\u00f3digo, notar\u00e1s que es el responsable de mantener a todo\nel motor en funcionamiento.  Esta es una versi\u00f3n muy simplificada del\nm\u00e9todo  ejecutar_bucle_principal :  def ejecutar_bucle_principal(self, ignorar_errores=False):\n\n    while not self.salir:\n        pilas.motor.procesar_y_emitir_eventos()\n\n        if not self.pausa_habilitada:\n            self._realizar_actualizacion_logica(ignorar_errores)\n\n        self._realizar_actualizacion_grafica()  Lo primero que debemos tener en cuenta es que este m\u00e9todo contiene\nun bucle  while  que lo mantendr\u00e1 en ejecuci\u00f3n. Este bucle\nsolo se detendr\u00e1 cuando alguien llame al m\u00e9todo  terminar  (que\ncambia el valor de la variable  salir  a  True ).  Luego hay tres m\u00e9todos importantes:   procesar_y_emitir_eventos  analiza el estado de los controles y avisa al resto del sistema si ocurre algo externo, como el movimiento del mouse..  _realizar_actualizacion_logica  le permite a los personajes realizar una fracci\u00f3n muy peque\u00f1a de movimiento, poder leer el estado de los controles o hacer otro tipo de acciones.  _realizar_actualizacion_logica  simplemente vuelca sobre la pantalla a todos los actores y muestra el resultado del dibujo al usuario.   Otra tarea que sabe hacer el objeto  Mundo , es administrar\nescenas. Las escenas son objetos que representan una\nparte individual del juego: un men\u00fa, una pantalla de opciones, el\nmomento de acci\u00f3n del juego etc...", 
            "title": "Inspeccionando: Mundo"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#modo-interactivo", 
            "text": "Pilas soporta dos modos de funcionamiento, que t\u00e9cnicamente son\nmuy similares, pero que a la hora de programar hacen una gran\ndiferencia.    modo normal : si est\u00e1s haciendo un archivo  .py  con el c\u00f3digo de tu juego usar\u00e1s este modo, tu programa comienza con una sentencia como  iniciar  y la simulaci\u00f3n se inicia cuando llamas a  pilas.ejecutar  (que se encarga de llamar a  ejecutar_bucle_principal  del objeto mundo).    modo interactivo : el modo que generalmente se usa en las demostraciones o cursos es el modo interactivo. Este modo funciona gracias a una estructura de hilos, que se encargan de ejecutar la simulaci\u00f3n pero a la vez no interrumpe al programador y le permite ir escribiendo c\u00f3digo mientras la simulaci\u00f3n est\u00e1 en funcionamiento.", 
            "title": "Modo interactivo"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#motores-multimedia", 
            "text": "Al principio pilas delegaba todo el manejo multimedia a una\nbiblioteca llamada SFML. Pero esta biblioteca requer\u00eda que todos los equipos\nen donde funcionan tengan aceleradoras gr\u00e1ficas (al menos con\nsoporte OpenGL b\u00e1sico).  Pero como queremos que pilas funcione en la mayor cantidad\nde equipos, incluso en los equipos antiguos de algunas\nescuelas, reemplazamos el soporte multimedia con la biblioteca Qt. Que sabe\nacceder a las funciones de aceleraci\u00f3n de gr\u00e1ficos (si est\u00e1n disponibles), o\nbrinda una capa de compatibilidad con equipos antiguos.  La funci\u00f3n que permite iniciar y seleccionar el motor es  pilas.iniciar .  pilas.iniciar(usar_motor='qt')  Ahora bien, \u00bfc\u00f3mo funciona?. Dado que pilas est\u00e1 realizado\nusando orientaci\u00f3n a objetos, usamos un concepto llamado\npolimorfismo:  El objeto motor sabe que tiene que delegar el manejo multimedia\na una instancia (o derivada) de la clase  Motor  (ver directorio pilas/motores/ .  El motor expone toda la funcionalidad que se necesita para\nhace un juego: sabe crear una ventana, pintar una imagen o\nreproducir sonidos, entre tantas otras cosas.  El objeto mundo no sabe exactamente que motor est\u00e1 utilizando, solo\ntiene una referencia a un motor y delega en \u00e9l todas las\ntareas multimedia.  Solo puede haber una instancia de motor en funcionamiento, y\nse define cuando se inicia el motor.", 
            "title": "Motores multimedia"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#sistema-de-actores", 
            "text": "Los actores permiten que los juegos cobren atractivo, porque\nun actor puede representarse con una imagen en pantalla.  La implementaci\u00f3n de todos los actores est\u00e1n en\nel directorio  pilas/actores .  Todos los actores heredan de la clase  Actor , que define\nel comportamiento com\u00fan de todos los actores.  Por ejemplo, esta ser\u00eda una versi\u00f3n reducida de la\njerarqu\u00eda de clases de los actores Mono, Pingu y Tortuga.  Hay dos m\u00e9todos en los actores que se invocar\u00e1n en\ntodo momento: el m\u00e9todo  actualizar  se invocar\u00e1\ncuando el bucle de juego del mundo llame al m\u00e9todo _realizar_actualizacion_logica , esto ocurre unas\n60 veces por segundo. Y el otro m\u00e9todo es  dibujar , que\nse tambi\u00e9n se invoca desde el objeto mundo, pero esta\nvez en el m\u00e9todo  _realizar_actualizacion_grafica .", 
            "title": "Sistema de actores"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#modo-depuracion", 
            "text": "Cuando pulsas teclas como F8, F9, F10, F11 o F12 durante\nla ejecuci\u00f3n de pilas, vas a ver que la pantalla comienza\na mostrar informaci\u00f3n valiosa para los desarrolladores.  Esta modalidad de dibujo la llamamos  modo depuraci\u00f3n , y\nayuda mucho a la hora de encontrar errores o ajustar detalles.  El objeto  Mundo , que mantiene en ejecuci\u00f3n al juego, tiene\nuna instancia de objeto  Depurador  que se encarga de\nhacer estos dibujos.  Las clases mas importantes a la hora de investigar el depurador\nest\u00e1n en el archivo  depurador.py .  El Depurador tiene dos atributos, tiene una pizarra para dibujar y\nuna lista de modos. Los modos pueden ser cualquiera de los que est\u00e1n\nen la jerarqu\u00eda de ModoDepuracion, por ejemplo, podr\u00eda tener\ninstancias de ModoArea y ModoPuntoDeControl.", 
            "title": "Modo depuraci\u00f3n"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#sistema-de-eventos", 
            "text": "Hay varios enfoques para resolver el manejo de eventos\nen los videojuegos.  Pilas usa un modelo conocido y elaborado\nllamado  Observator , un patr\u00f3n de dise\u00f1o. Pero que\nlamentablemente no es muy intuitivo a primera vista.  En esta secci\u00f3n intentar\u00e9 mostrar por qu\u00e9 usamos\nesa soluci\u00f3n y qu\u00e9 problemas nos ayuda a resolver.  Comenzar\u00e9 explicando sobre el problema de gestionar eventos\ny luego c\u00f3mo el modelo  Observator  se volvi\u00f3\nuna buena soluci\u00f3n para el manejo de eventos.", 
            "title": "Sistema de eventos"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#el-problema-pooling-de-eventos", 
            "text": "Originalmente, en un modelo muy simple de aplicaci\u00f3n multimedia,\nmanejar eventos de usuario es algo sencillo, pero con el\ntiempo comienza a crecer y se hace cada vez mas dif\u00edcil de\nmantener.  Resulta que las bibliotecas multimedia suelen entregar un\nobjeto  evento  cada vez que ocurre algo y tu responsabilidad\nes consultar sobre ese objeto en b\u00fasqueda de datos.  Imagina que quieres crear un actor  Bomba  cada\nvez que el usuario hace click en la pantalla. El\nc\u00f3digo podr\u00eda ser algo as\u00ed:  evento = obtener_evento_actual()\n\nif evento.tipo == 'click_de_mouse':\n    crear_bomba(evento.x)\n    crear_bomba(evento.x)\nelse:\n    # el evento de otro tipo (teclado, ventana ...)\n    # lo descartamos.  A esta soluci\u00f3n podr\u00edamos llamarla  preguntar  y  responder ,\nporque efectivamente as\u00ed funciona el c\u00f3digo, primero\nnos aseguramos de que el evento nos importa y luego\nhacemos algo. En algunos sitios suelen llamar a esta\nestrategia  pooling .  Pero este enfoque tiene varios problemas, y cuando hacemos\njuegos o bibliotecas se hace mas evidente. El c\u00f3digo, a medida\nque crece, comienza a mezclar manejo de eventos y l\u00f3gica\ndel juego.  Para ver el problema de cerca, imagina que en determinadas\nocasiones quieres deshabilitar la creaci\u00f3n de bombas, \u00bfc\u00f3mo\nhar\u00edas?. \u00bfY si quieres que las bombas creadas se puedan\nmover con el teclado?.", 
            "title": "El problema: pooling de eventos"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#otro-enfoque-en-pilas-usamos-observator", 
            "text": "Hay otro enfoque para el manejo de eventos que me parece\nmas interesante, y lo he seleccionado para el motor pilas :  En lugar de administrar los eventos uno a uno por consultas , delegamos esa tarea a un sistema que nos\npermite  suscribir  y  ser notificado .  Aqu\u00ed no mezclamos nuestro c\u00f3digo con el sistema de eventos, si\nqueremos hacer algo relacionado con un evento, escribimos\nuna funci\u00f3n y le pedimos al evento que llame a nuestra\nfunci\u00f3n cuando sea necesario.  Veamos el ejemplo anterior pero usando este enfoque, se\ncrear\u00e1 una  Bomba  cada vez que el usuario\nhace  click  en la pantalla:  def crear_bomba(evento):\n    pilas.actores.Bomba(x=evento.x, y=evento.y)\n    return true\n\npilas.eventos.click_de_mouse.conectar(crear_bomba)  Si queremos que el mouse deje de crear bombas, podemos\nejecutar la funci\u00f3n  desconectar :  pilas.eventos.click_de_mouse.conectar(crear_bomba)  o simplemente retornar  False  en la funci\u00f3n  crear_bomba .  Nuestro c\u00f3digo tendr\u00e1  bajo acoplamiento  con los eventos\ndel motor, y no se nos mezclar\u00e1n.  De hecho, cada vez que tengas dudas sobre las funciones\nsuscritas a eventos pulsa F7 y se imprimir\u00e1n en pantalla.", 
            "title": "Otro enfoque, en pilas usamos 'Observator'"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#como-funciona", 
            "text": "Ahora bien, \u00bfc\u00f3mo funciona el sistema de eventos por dentro?:  El sistema de eventos que usamos es una ligera adaptaci\u00f3n\ndel sistema de se\u00f1ales de django (un framework para desarrollo\nde sitios web) d\u00f3nde cada evento es un objeto que puede\nhacer dos cosas:   suscribir funciones.  invocar a las funciones que se han suscrito.   1 Suscribir  Por ejemplo, el evento  mueve_mouse  es un objeto, y cuando\ninvocamos la sentencia  pilas.eventos.mueve_mouse.conectar(mi_funcion) ,\nle estamos diciendo al objeto \"quiero que guardes una referencia\na  mi_funcion \".  Puedes imaginar al evento como un objeto contenedor (similar\na una lista), que guarda cada una de las funciones que le enviamos\ncon el m\u00e9todo  conectar .  2 Notificar  La segunda tarea del evento es notificar a todas\nlas funciones que se suscribieron.  Esto se hace, retomando el ejemplo anterior, cuando el usuario\nhace click con el mouse.  Los eventos son objetos  Signal  y se inicializan en el\narchivo  eventos.py , cada uno con sus respectivos\nargumentos o detalles:  click_de_mouse = Evento(\"click_de_mouse\")\npulsa_tecla = Evento(\"pulsa_tecla\")\n[ etc...]  Los argumentos indican informaci\u00f3n adicional del evento, en\nel caso del click, observar\u00e1s que los argumentos son el bot\u00f3n pulsado\ny la coordenada del puntero.  Cuando se quiere notificar a las funciones conectadas a\nun evento simplemente se tiene que invocar al m\u00e9todo  emitir \ndel evento y proveer los argumentos que necesita:  click_de_mouse.emitir(button=1, x=30, y=50)  Eso har\u00e1 que todas las funciones suscritas al evento  click_de_mouse \nse invoquen con el argumento  evento  representando esos detalles:  def crear_bomba(evento):\n\n    print(evento.x)\n    # imprimir\u00e1 30\n\n    print(evento.y)\n    # imprimir\u00e1 50\n\n    [ etc...]  La parte de pilas que se encarga de llamar a los m\u00e9todos  emitir \nes el m\u00e9todo  procesar_y_emitir_eventos  del motor.", 
            "title": "\u00bfC\u00f3mo funciona?"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#habilidades", 
            "text": "Los actores de pilas tienen la cualidad de poder\nir obteniendo comportamiento desde otras clases.  Esto te permite lograr resultados de forma r\u00e1pida, y\na la vez, es un modelo tan flexible que podr\u00edas\nhacer muchos juegos distintos combinando los mismos\nactores pero con distintas habilidades.  Veamos un ejemplo, un actor sencillo como  Mono  no\nhace muchas cosas. Pero si escribimos lo siguiente, podremos\ncontrolarlo con el mouse:  mono = pilas.actores.Mono()\nmono.aprender(pilas.habilidades.Arrastrable)  Lo que en realidad estamos haciendo, es vincular dos objetos\nen tiempo de ejecuci\u00f3n.  mono  es un objeto  Actor , y tiene una\nlista de habilidades que puede aumentar usando el m\u00e9todo  aprender .  El m\u00e9todo  aprender  toma la clase que le enviamos como\nargumento, construye un objeto y lo guarda en su lista de habilidades.  Este es un modelo de c\u00f3mo se conocen las clases entre\ns\u00ed:  Entonces, una vez que invocamos a la sentencia, nuestro actor\ntendr\u00e1 un nuevo objeto en su lista de habilidades, listo para\nejecutarse en cada cuadro de animaci\u00f3n.", 
            "title": "Habilidades"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#como-se-ejecutan-las-habilidades", 
            "text": "Retomando un poco lo que vimos al principio de este cap\u00edtulo, lo\nque mantiene con  vida  al juego es el bucle principal, la clase Mundo  tiene un bucle que recorre la lista de actores en pantalla\ny por cada uno llama al m\u00e9todo actualizar.  Bien, las habilidades se mantienen en ejecuci\u00f3n desde ah\u00ed tambi\u00e9n. Esta\nes una versi\u00f3n muy simplificada del bucle que encontrar\u00e1s en el\narchivo ``mundo.py```:  def ejecutar_bucle_principal(self, ignorar_errores=False):\n\n    while not self.salir:\n        self.actualizar_actores()\n\n        [ etc ...]\n\ndef actualizar_actores(self):\n    for actor in pilas.actores.todos:\n        actor.actualizar()\n        actor.actualizar_habilidades()  Aqu\u00ed puedes ver dos llamadas a m\u00e9todos del actor, el m\u00e9todo actualizar  se cre\u00f3 para que cada programador escriba\nah\u00ed lo que quiera que el personaje haga (leer el teclado,\nhacer validaciones, moverse etc). Y el m\u00e9todo  actualizar_habilidades \nes el encargado de  dar vida  a las habilidades.  T\u00e9cnicamente hablando, el m\u00e9todo  actualizar_habilidades  es\nmuy simple, solamente toma la lista de objetos habilidades y\nlos actualiza, al  Actor  no le preocupa en lo mas m\u00ednimo\n\"qu\u00e9\" hace cada habilidad, solamente les permite ejecutar c\u00f3digo\n(ver c\u00f3digo  estudiante.py , una superclase de  Actor ):  def actualizar_habilidades(self):\n    for h in self.habilidades:\n        h.actualizar()  Entonces, si queremos que un actor haga muchas cosas, podemos\ncrear un objeto habilidad y vincularlo con el actor. Esto\npermite generar \"comportamientos\" re-utilizables, la habilidad\nse codifica una vez, y se puede usar muchas veces.", 
            "title": "\u00bfC\u00f3mo se ejecutan las habilidades?"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#objetos-habilidad", 
            "text": "Las habilidades interact\u00faan con los actores, y por ese motivo\ntienen que tener una interfaz en com\u00fan, de modo tal que\ndesde cualquier parte de pilas puedas tratar a una habilidad\ncomo a cualquier otra.  La interfaz que toda habilidad debe tener es la que define\nla clase  Habilidad  del archivo  habilidades.py :  class Habilidad:\n\n    def __init__(self, receptor):\n        self.receptor = receptor\n\n    def actualizar(self):\n        pass\n\n    def eliminar(self):\n        pass  Tiene que tener tres m\u00e9todos, uno que se ejecuta al producirle\nla relaci\u00f3n con un actor, un m\u00e9todo que se ejecutar\u00e1 en\ncada iteraci\u00f3n del bucle de juego ( actualizar ) y un\n\u00faltimo m\u00e9todo para ejecutar cuando la habilidad se desconecta\ndel actor. Este m\u00e9todo  eliminar  suele ser el que desconecta\neventos o cualquier otra cosa creada temporalmente.  Ten en cuenta que el m\u00e9todo  __init__ , que construye\nal objeto, lo invoca el propio actor desde su m\u00e9todo  aprender . Y\nel argumento  receptor  ser\u00e1 una referencia al actor que aprende  la habilidad.  Veamos un ejemplo muy b\u00e1sico, imagina que quieres hacer\nuna habilidad muy simple, que gire al personaje todo el\ntiempo, c\u00f3mo una aguja de reloj. Podr\u00edas hacer\nalgo as\u00ed:  class GirarPorSiempre(pilas.habilidades.Habilidad):\n\n    def __init__(self, receptor):\n        self.receptor = receptor\n\n    def actualizar(self):\n        self.receptor.rotacion += 1\n\nmono = pilas.actores.Mono()\nmono.aprender(GirarPorSiempre)  La sentencia  aprender  construir\u00e1 un objeto de la\nclase que le indiquemos, y el bucle de pilas (en  mundo.py )\ndar\u00e1 la orden para ejecutar los m\u00e9todos actualizar de\ncada habilidad conocida por los actores.", 
            "title": "Objetos habilidad"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#argumentos-de-las-habilidades", 
            "text": "En el ejemplo anterior podr\u00edamos encontrar una\nlimitaci\u00f3n. El actor siempre girar\u00e1 a la misma velocidad.  Si queremos que los personajes puedan girar a diferentes\nvelocidades tendr\u00edamos que agregarle argumentos\na la habilidad, esto es simple: solo tienes que llamar\nal m\u00e9todo  aprender  con los argumentos que quieras\ny asegurarte de que la habilidad los tenga definidos en\nsu m\u00e9todo  __init__ .  Este es un ejemplo de la habilidad pero que permite\ndefinir la velocidad de giro:  class GirarPorSiempre(pilas.habilidades.Habilidad):\n\n    def __init__(self, receptor, velocidad=1):\n        self.receptor = receptor\n        self.velocidad = velocidad\n\n    def actualizar(self):\n        self.receptor.rotacion += self.velocidad\n\na = pilas.actores.Mono()\na.aprender(GirarPorSiempre, 20)  Listo, es casi id\u00e9ntico al anterior, si llamas a  aprender  con un\nargumento como  20 , el actor girar\u00e1 mucho mas r\u00e1pido que\nantes. Y si no especificas la velocidad, se asumir\u00e1 que la\nvelocidad es  1 , porque as\u00ed lo indica el m\u00e9todo  __init__ .", 
            "title": "Argumentos de las habilidades"
        }, 
        {
            "location": "/como_funciona_pilas_por_dentro/#documentacion", 
            "text": "El sistema de documentaci\u00f3n que usamos en pilas\nes Sphinx, un sistema muy interesante porque nos\npermite gestionar todo el contenido del manual\nen texto plano, y gracias a varias herramientas\nde conversi\u00f3n c\u00f3mo restructuredText y latex, se\nproducen muchos formatos de salida c\u00f3mo HTML y PDF.  Toda la documentaci\u00f3n del proyecto est\u00e1 en el\ndirectorio  doc . El directorio  doc/sources  contiene\ntodos los archivos que modificamos para escribir contenido\nen la documentaci\u00f3n.  Para generar los archivos PDF o HTML usamos el comando make  dentro del directorio  doc . El archivo que\ndispara todas las acciones que sphinx sabe hacer est\u00e1n\ndefinidas en el archivo  Makefile .", 
            "title": "Documentaci\u00f3n"
        }, 
        {
            "location": "/complementos/", 
            "text": "Complementos (Plugins)\n\n\nPilas incorpora un sistema de complementos para que se pueda\npersonalizar el entorno completo usando c\u00f3digo auto-incluido.\n\n\nEsta es una funcionalidad avanzada, que se suele utilizar en\ntalleres o cursos especializados. La idea general es que pilas\nse puede modificar a\u00f1adiendo c\u00f3digo en un directorio especial y\nsin necesidad de tocar le c\u00f3digo fuente de pilas en s\u00ed.\n\n\n\u00bfQue son los complementos?\n\n\nLos complementos, o plugins, son simplemente archivos de c\u00f3digo\npython que pilas leer\u00e1 al momento de iniciar.\n\n\nCada c\u00f3digo python podr\u00e1 definir clases que luego se podr\u00e1n utilizar\ndirectamente desde el motor.\n\n\nTodos los complementos tienen que existir en un directorio\nespecial del sistema. Estos son los lugares en donde se buscar\u00e1n los\ncomplementos:\n\n\n\n\nEn linux: $USERDIR/.pilas-engine/complementos/\n\n\nEn OSX: $USERDIR/.pilas-engine/complementos/\n\n\n\n\nInicializando los complementos\n\n\nLos complementos no se buscar\u00e1n a menos que se iniciale pilas-engine\nespecificando que queremos complementos.\n\n\nPara inicializar pilas-engine con soporte para completos tenemos\nque usar el par\u00e1metro \"cargar_plugins\" as\u00ed:\n\n\nimport pilasengine\n\npilas = pilasengine.iniciar(cargar_plugins=True)\n\n\n\n\nY en la consola tendr\u00e1 que aparecer un texto indicando la cantidad de\ncomplementos encontrada.\n\n\nCreando un plugin de ejemplo\n\n\nPara probar esta funcionalidad, vamos a hacer un complemento muy\nsimple que solamente muestre un mensaje cuando pilas se inicializa.\n\n\nPrimero tenemos que crear el archivo para el complemento, en este\ncaso \n$HOMEDIR/.pilas-engine/plugins/saludar.py\n\n\nclass Saludar(object):\n\n    def __init__(self, pilas):\n      pilas.avisar(\nBienvenido, pilas se inicio correctamente.\n)\n\n\n\n\nLuego, para iniciarle a pilas que queremos cargar los complementos\ntenemos que iniciar pilas as\u00ed:\n\n\nimport pilasengine\n\npilas = pilasengine.iniciar(cargar_plugins=True)\n\n\n\n\ntendr\u00edamos que ver en consola el mensaje \nSe encontro un plugin\n. Luego,\npara inicializar el complemento:\n\n\npilas.complementos.Saludar(pilas)\n\n\n\n\nEs decir, en el nombre de cualquier clase definida en nuestros complementos\nestar\u00e1 accesible a trav\u00e9s del acceso \npilas.complementos...\n\n\nNo olvides pasar el objeto \"pilas\"...\n\n\nTen en cuenta que a partir de la versi\u00f3n 0.90 de pilas-engine, para\nacceder a la funcionalidad de pilas tenemos que usar la variable \"pilas\", y\nque esta no el global. As\u00ed que te recomendamos hacer complementos\ntal y como lo sugeremos aqu\u00ed en el ejemplo, declarando \"pilas\" como un arguemento\nen el inicializador:\n\n\ndef NombreComplemento(object):\n\n    def __init__(self, pilas):\n      # [etc...]\n\n\n\n\ne inicializ\u00e1ndolo especificando el objeto pilas:\n\n\npilas.complementos.NombreComplemento(pilas)", 
            "title": "Complementos"
        }, 
        {
            "location": "/complementos/#complementos-plugins", 
            "text": "Pilas incorpora un sistema de complementos para que se pueda\npersonalizar el entorno completo usando c\u00f3digo auto-incluido.  Esta es una funcionalidad avanzada, que se suele utilizar en\ntalleres o cursos especializados. La idea general es que pilas\nse puede modificar a\u00f1adiendo c\u00f3digo en un directorio especial y\nsin necesidad de tocar le c\u00f3digo fuente de pilas en s\u00ed.", 
            "title": "Complementos (Plugins)"
        }, 
        {
            "location": "/complementos/#que-son-los-complementos", 
            "text": "Los complementos, o plugins, son simplemente archivos de c\u00f3digo\npython que pilas leer\u00e1 al momento de iniciar.  Cada c\u00f3digo python podr\u00e1 definir clases que luego se podr\u00e1n utilizar\ndirectamente desde el motor.  Todos los complementos tienen que existir en un directorio\nespecial del sistema. Estos son los lugares en donde se buscar\u00e1n los\ncomplementos:   En linux: $USERDIR/.pilas-engine/complementos/  En OSX: $USERDIR/.pilas-engine/complementos/", 
            "title": "\u00bfQue son los complementos?"
        }, 
        {
            "location": "/complementos/#inicializando-los-complementos", 
            "text": "Los complementos no se buscar\u00e1n a menos que se iniciale pilas-engine\nespecificando que queremos complementos.  Para inicializar pilas-engine con soporte para completos tenemos\nque usar el par\u00e1metro \"cargar_plugins\" as\u00ed:  import pilasengine\n\npilas = pilasengine.iniciar(cargar_plugins=True)  Y en la consola tendr\u00e1 que aparecer un texto indicando la cantidad de\ncomplementos encontrada.", 
            "title": "Inicializando los complementos"
        }, 
        {
            "location": "/complementos/#creando-un-plugin-de-ejemplo", 
            "text": "Para probar esta funcionalidad, vamos a hacer un complemento muy\nsimple que solamente muestre un mensaje cuando pilas se inicializa.  Primero tenemos que crear el archivo para el complemento, en este\ncaso  $HOMEDIR/.pilas-engine/plugins/saludar.py  class Saludar(object):\n\n    def __init__(self, pilas):\n      pilas.avisar( Bienvenido, pilas se inicio correctamente. )  Luego, para iniciarle a pilas que queremos cargar los complementos\ntenemos que iniciar pilas as\u00ed:  import pilasengine\n\npilas = pilasengine.iniciar(cargar_plugins=True)  tendr\u00edamos que ver en consola el mensaje  Se encontro un plugin . Luego,\npara inicializar el complemento:  pilas.complementos.Saludar(pilas)  Es decir, en el nombre de cualquier clase definida en nuestros complementos\nestar\u00e1 accesible a trav\u00e9s del acceso  pilas.complementos...", 
            "title": "Creando un plugin de ejemplo"
        }, 
        {
            "location": "/complementos/#no-olvides-pasar-el-objeto-pilas", 
            "text": "Ten en cuenta que a partir de la versi\u00f3n 0.90 de pilas-engine, para\nacceder a la funcionalidad de pilas tenemos que usar la variable \"pilas\", y\nque esta no el global. As\u00ed que te recomendamos hacer complementos\ntal y como lo sugeremos aqu\u00ed en el ejemplo, declarando \"pilas\" como un arguemento\nen el inicializador:  def NombreComplemento(object):\n\n    def __init__(self, pilas):\n      # [etc...]  e inicializ\u00e1ndolo especificando el objeto pilas:  pilas.complementos.NombreComplemento(pilas)", 
            "title": "No olvides pasar el objeto \"pilas\"..."
        }, 
        {
            "location": "/desarrolladores/", 
            "text": "Gu\u00eda para desarrolladores\n\n\nEn esta secci\u00f3n veremos como contribuir en el desarrollo de pilas, mostrando las herramientas de desarrollo y dando algunas recomendaciones.\n\n\nActualmente utilizamos Git junto a los servicios de github.\n\n\nRepositorio\n\n\nPara contribuir en el desarrollo de pilas necesitas una cuenta de usuario en\n\ngithub\n, nuestros proveedores del servicio de repositorios.\n\n\nLa direcci\u00f3n de acceso web al repositorio es:\n\n\n\n\nhttp://github.com/hugoruscitti/pilas\n\n\n\n\nTen en cuenta que el servicio \ngithub\n es gratuito, y solo lleva unos minutos registrarse.\n\n\nObteniendo la \u00faltima versi\u00f3n del repositorio\n\n\nPara obtener la \u00faltima versi\u00f3n tienes que ejecutar el siguiente comando desde un terminal:\n\n\ngit clone http://github.com/hugoruscitti/pilas\n\n\n\nLuego aparecer\u00e1 un directorio llamado pilas, con el contenido completo del repositorio.\n\n\nPrimer prueba\n\n\nIngresa en el directorio pilas, ejecuta el comando:\n\n\npython bin/pilas\n\n\n\ndeber\u00eda aparecer en pantalla el asistente de primer inicio.\n\n\nInstalaci\u00f3n en modo desarrollo\n\n\nSi sos desarrollador, la forma de instalaci\u00f3n mas recomendable es mediante el\ncomando develop. Esta opci\u00f3n es \u00fatil porque te permite mantener actualizada\nla biblioteca en todo momento.\n\n\nPara usar esta opci\u00f3n de instalaci\u00f3n tienes que ejecutar el siguiente comando:\n\n\nsudo python setup.py develop\n\n\n\nTen en cuenta que a partir de ahora, cuando uses pilas en el sistema, se\nleer\u00e1 el c\u00f3digo directamente desde ese directorio en donde has clonado\nla biblioteca.\n\n\nMantenerse actualizado, siempre...\n\n\nDado que \npilas\n est\u00e1 creciendo, es una buena idea mantener tu copia del motor actualizada.\n\n\nPara ello tienes que ingresar en el directorio pilas y ejecutar el siguiente\ncomando de manera peri\u00f3dica:\n\n\ngit pull\n\n\n\nMas detalles\n\n\nUsamos el modelo de trabajo de github, haciendo forks y pull requests.\n\n\nSi quieres obtener mas detalles te recomiendo ver el siguiente art\u00edculo:\n\n\n\n\nhttp://www.cocoanetics.com/2012/01/github-fork-fix-pull-request/", 
            "title": "Gu\u00eda para desarrolladores"
        }, 
        {
            "location": "/desarrolladores/#guia-para-desarrolladores", 
            "text": "En esta secci\u00f3n veremos como contribuir en el desarrollo de pilas, mostrando las herramientas de desarrollo y dando algunas recomendaciones.  Actualmente utilizamos Git junto a los servicios de github.", 
            "title": "Gu\u00eda para desarrolladores"
        }, 
        {
            "location": "/desarrolladores/#repositorio", 
            "text": "Para contribuir en el desarrollo de pilas necesitas una cuenta de usuario en github , nuestros proveedores del servicio de repositorios.  La direcci\u00f3n de acceso web al repositorio es:   http://github.com/hugoruscitti/pilas   Ten en cuenta que el servicio  github  es gratuito, y solo lleva unos minutos registrarse.", 
            "title": "Repositorio"
        }, 
        {
            "location": "/desarrolladores/#obteniendo-la-ultima-version-del-repositorio", 
            "text": "Para obtener la \u00faltima versi\u00f3n tienes que ejecutar el siguiente comando desde un terminal:  git clone http://github.com/hugoruscitti/pilas  Luego aparecer\u00e1 un directorio llamado pilas, con el contenido completo del repositorio.", 
            "title": "Obteniendo la \u00faltima versi\u00f3n del repositorio"
        }, 
        {
            "location": "/desarrolladores/#primer-prueba", 
            "text": "Ingresa en el directorio pilas, ejecuta el comando:  python bin/pilas  deber\u00eda aparecer en pantalla el asistente de primer inicio.", 
            "title": "Primer prueba"
        }, 
        {
            "location": "/desarrolladores/#instalacion-en-modo-desarrollo", 
            "text": "Si sos desarrollador, la forma de instalaci\u00f3n mas recomendable es mediante el\ncomando develop. Esta opci\u00f3n es \u00fatil porque te permite mantener actualizada\nla biblioteca en todo momento.  Para usar esta opci\u00f3n de instalaci\u00f3n tienes que ejecutar el siguiente comando:  sudo python setup.py develop  Ten en cuenta que a partir de ahora, cuando uses pilas en el sistema, se\nleer\u00e1 el c\u00f3digo directamente desde ese directorio en donde has clonado\nla biblioteca.", 
            "title": "Instalaci\u00f3n en modo desarrollo"
        }, 
        {
            "location": "/desarrolladores/#mantenerse-actualizado-siempre", 
            "text": "Dado que  pilas  est\u00e1 creciendo, es una buena idea mantener tu copia del motor actualizada.  Para ello tienes que ingresar en el directorio pilas y ejecutar el siguiente\ncomando de manera peri\u00f3dica:  git pull", 
            "title": "Mantenerse actualizado, siempre..."
        }, 
        {
            "location": "/desarrolladores/#mas-detalles", 
            "text": "Usamos el modelo de trabajo de github, haciendo forks y pull requests.  Si quieres obtener mas detalles te recomiendo ver el siguiente art\u00edculo:   http://www.cocoanetics.com/2012/01/github-fork-fix-pull-request/", 
            "title": "Mas detalles"
        }
    ]
}