viernes, 21 de diciembre de 2012

GameMaker: Acciones básicas III

Main actions, set 2

Acciones relacionadas con el tiempo, dar mensajes al usuario y tratar con el juego.

Set Alarm: Con esta acción puedes configurar una de las doce alarmas para la instancia. Selecciona el número de pasos y el reloj de alarma. Despues de indicar el número de pasos (fotogramas), la instancia recibirá el evento de alarma correspondiente. Puedes ademas incrementar o decrementar el valor marcando la casilla relative. Si defines el reloj de alarma a un valor menor o igual que cero lo apagaras, por lo que el evento no será ejecutado. Una vez configures una alarma podrás usar el evento Alarm para ejecutar acciones dentro del mismo.

Sleep: Con esta accion puedes congelar la escena por un tiempo. Esto se usa al inicio o al final del nivel o cuando le muestras al jugador algun mensaje. Puedes especificar el número de milisegundos de congelación. Ademas puedes indicar cuando la pantalla debería ser dibujada primero para reflejar la situación más reciente.

Display Message: Con esta accion puedes mostrar un mensaje en una ventana de dialogo. Simplemente escribe el mensaje. Si usas el simbolo # en la caja de texto, será interpretado como el carácter de nueva linea. (Usa \# para escapar el simbolo). El juego será pausado mientras se muestra el mensaje.

Show Info: Con esta acción puedes lanzar una ventana con la información del juego.

Restart Game: Con esta acción se reinicia el juego desde el principio.

End Game: Con esta acción termina el juego.

Save Game: Con esta accion puedes salvar estado de juego actual. Especificas un archivo de salvado (El archivo se crea en el directorio de trabajo del juego). Mas tarde el puedes cargarlo usando Load game. Solo el estado básico de juego es salvado. Cosas como por ejemplo el sonido actual que suena o aspectos avanzados como contenidos de estructuras de datos o particulas no se guardan.

No suele ocurrir ninguna acción durante el uso de save Game, por lo que puede que el jugador no se este dando cuenta de que ha salvado el juego, por lo que recomiendo mostrarle algun mensaje confirmando que todo hay ido bien.

Load Game: Carga el estado de un juego de un fichero. Especificas el nombre de archivo y ya está. Asegurate que el juego salvado es el mismo juego y que se ha creado con la misma versión de GameMaker. De lo contrario un dará error.



(Recordemos que todo esto se explica (en inglés) en la ayuda de GameMaker, pero lo estoy probando para ver como funciona todo, así que se podría decir que este “manual intensivo” es una traducción adaptada.)
 

jueves, 20 de diciembre de 2012

GameMaker: Acciones básicas II

Main Actions: Set 1

Relacionadas con crear cambiar y destruir instancias de objetos, con sonidos y con habitaciones.

Create Instante: Con esta acción puedes crear una instancia de un objeto. Especificas que objeto crear y la posición de la nueva instancia. Si marcas relative, la posición es relativa a la posición de la instancia actual. Crear instancias durante el juego es extremadamente útil. Una nave espacial disparar un láser, una bomba puede crear una explosión, etc. En muchos juegos puedes tener algunos objetos controladores que de vez en cuando crean monstruos u otros objetos. Para la nueva instancia creada, el evento de create será ejecutado.

Create Moving: Esta acción trabaja igual que la anterior pero con dos campos adicionales. Puedes especificar la velocidad y dirección de la nueva instancia. Destacar que si marcas la casilla relative, solamente la posición será relativa, no la velocidad ni la dirección. Por ejemplo, para hacer una bala en movimiento en la dirección del objeto que esta disparando, como posición usa x=0 e y=0 marcando relativo. Como dirección necesitamos la dirección actual de la instancia. Puedes obtenerla escribiendo la palabra “direction” (es una variable que indica la dirección actual en la que la instancia se esta moviendo).

Create Random: Esta acción te permite crear una instancia aleatoria entre cuatro objetos. Tú especificas los cuatro objetos y la posición, y una instancia de uno de estos objetos es creada en la posición dada. Si marcas la casilla relativa, la posición es relativa a la posición de la instancia actual. Si necesitas una elección de menos de cuatro objetos puedes usar “No Object” para alguno de ellos. Esto es útil, por ejemplo, para generar enemigos aleatorios en una posición.

Change Instance: Con esta acción puedes cambiar la actual instancia en una instancia de otro objeto. Por ejemplo, puedes cambiar una instancia de una bomba en una explosión. Todos los parámetros, como el movimiento y el valor de las variables son las del otro objeto. Además puedes indicar si se lanzará el evento destroy cuando el actual objeto desaparezca y el evento create para el nuevo objeto.

Destroy Instance: Con esta acción puedes destruir la instancia actual. El evento destroy será ejecutado en la misma.

Destroy at Position: Con esta acción destruyes todas las instancias que estén dentro de un rectángulo que contiene la posición dada. Es útil, por ejemplo, cuando usas una explosión que quieres que afecte un espacio determinado de la pantalla. Si marcas la casilla relative, la posición es tomada como relativa a la posición de la instancia actual.

Change Sprite: Usa esta acción para cambiar el sprite de la instancia. Puedes indicar cual es el nuevo sprite y, además, los fotogramas que deben mostrarse. Normalmente puedes usar 0 (para el primer fotograma) a no ser que quieras ver un fotograma particular. Usa -1 si no quieres cambiar el fotograma actual a mostrar. Finalmente puedes cambiar la velocidad de la animación de los fotogramas. Si solo quieres ver un fotograma particular, configura su velocidad a 0. Si la velocidad es mayor que uno, algunos fotogramas pueden saltarse. Si es menor que 1, pueden mostrarse varias veces. Es mejor que no uses velocidades negativas.

Esta es una acción importante. Por ejemplo, cuando quieres cambiar un sprite de un personaje dependiendo de la dirección en la que anda. Puedes usar esta acción con sprites para cada una de las direcciones posibles. Con los eventos de keyboard para las teclas puedes definir la dirección de movimiento del sprite. También es el útil para controlar las animaciones.

Transform Sprite: Usa esta acción para cambiar el tamaño y orientación del sprite de la instancia. Usa los factores de escala para hacerlos mayores o mas pequeños. El Angulo se cuenta en sentido contrario a las agujas del reloj. Por ejemplo, para poner el sprite orientado a la dirección del movimiento usa como valor “direction”. Por ejemplo, esto es útil para un coche. Puedes además indicar cuando el sprite debería espejarse horizontalmente o verticalmente. Esta acción esta solo disponible en la versión Standard.

Color Sprite: Normalmente el sprite es dibujado como esta definido. Usando esta acción puedes cambiar el color del sprite. Este color se fusionará con el del sprite, es decir, será combinado con los colores del sprite. Gracias a esto podrías pintar un sprite en blanco y negro y usar la fusión de color para definir el color actual. Puedes además indicar un canal alpha de transparencia. Con este valor a 1 el sprite es opaco. Con este valor a 0 es completamente transparente. Con este valor en un número intermedio es, evidentemente, semitransparente. Es genial para hacer explosiones. Esta acción esta solo disponible en la edición Standard.

Play sound: Con esta acción puedes ejecutar uno de los sonidos que añadiste a los recursos de tu juego. Puedes seleccionar el sonido que quieres ejecutar y elegir si debería sonar solo una vez (por defecto) o continuamente. Aunque pueden ejecutarse varios sonidos a la vez, en el caso del midi, solo puede haber uno sonando. Por ello si inicias un midi el que tenías sondando se parará.

Stop Sound: Esta acción para el sonido indicado. Si las múltiples instancias de este sonido están sonando se paran todas.

Check Sound: Si el sonido indicado esta sonando la próxima acción se ejecuta. En otro caso se salta. Puedes seleccionar Not para indicar que la próxima acción debería ejecutarse si el sonido indicado no esta sonando. Por ejemplo, puedes comprobar si hay música de fondo sonando.

Previous Room: Salta al nivel habitación. Puedes indicar si el tipo de transición entre las habitaciones. Cuando las habitaciones no tienen el mismo tamaño, no es recomendable usar transiciones. Si estas en la primera habitación obtendrás un error.

Next Room: Te mueve a la siguiente habitación. Puedes indicar la transición.

Restart Room: La habitación actual se reinicia. Puedes indicar el efecto de transición.

Different Room: Con esta acción puedes ir a una habitación concreta, indicando la habitación y el efecto de transición.

Check Previous: Con esta acción comprobamos si la próxima habitación existe. Si es así. La próxima acción es ejecutada. Normalmente necesitas esta acción de tipo test antes de moverte a la habitación anterior.

Check Next: Esta acción testea si la próxima habitación existe. Si es así, la próxima acción es ejecutada. Igual que con la acción anterior deberías testear si existe antes de ir a la próxima habitación.

De nuevo la información sale del manual del software, yo solo me dedico a probarlo, aprender y explicar. (Y en la sombra pensar en mi juego para el concurso del Blog de Toodaim, muahahahahaha).

miércoles, 19 de diciembre de 2012

GameMaker: Acciones básicas I

Continuando con el repaso de GameMaker vamos a hablar ahora de las acciones básicas del programa e ir profundizando en ellas poco a poco. Recordemos, eso si, antes, que las acciones son la respuesta a los eventos que mencionaba en el post anterior. Primero hay un evento (ocurre algo en el juego) y como consecuencia se ejecutan una o varias acciones.


Move Actions   

Move Fixed: Usa esta accion para iniciar el movimiento de una instancia en una direccion particular. Puedes indicar la direccion usando los botones con las flechas. Usa el boton central para detener el movimiento. Necesitas especificar la velocidad del movimiento que se mide en pixels por fotograma, y preferiblemente usar valores positivos. Puedes especificar direcciones múltiples. En este caso se realiza una elección aleatoria. De esta forma puedes hacer que un enemigo se empiece a mover a la derecha o a la izquierda, por poner un ejemplo.

Move Free: Segunda forma de especificar movimiento. Puedes indicar una dirección precisa con un angulo entre 0 y 360, siempre teniendo en cuenta que el 0 apunta a la derecha y aa direccion gira en sentido contrario de las agujas del reloj. Por ejemplo 90 es arriba. Si quieres una direcció arbitraria puedes escribir “random(360)”, por que la funcion random devuelve un número aleatorio menor que el valor indicado.

Hay un checkbox Relative. Si lo marcas, el nuevo movimiento se añade al que había. Por ejemplo, si la instancia se mueve hacia arriba y añades movimiento a la derecha el nuevo movimiento es arriba a la derecha.

Move Towards: Esta accion nos proporciona un tercer modo de movimiento. Indica la posicion y una velocidad y la instancia empieza a moverse con la velocidad hacia la posición, teniendo en cuenta que no parará en la posición. Por eemplo, si quieres que una bala vaya hacia la posicion de una nave puedes usar spaceship.x, spaceship.y. Si chequeas la casilla Relative, especificas una posicion relativa a la posicion de la instancia actual. (La velocidad no es tomada como relativa).

Speed Horizontal: La velocidad de una instancia consiste en una parte horizontal y una vertical. Con esta accion puedes cambiar su parte horizontal. Un valor positivo significa movimiento a la derecha mientras que negativo es a la izquierda. Usa relativo para incrementar o decrementar la velocidad cada vez en vez de usar una fija.

Speed Vertical: Similar al horizontal pero en vertical.

Set Gravity: Con esta accion puedes especificar gravedad para un objeto particular. Especificas la direccion (angulo entre 0 y 360) y velocidad. En cada fotograma es añadida al movimiento actual de la instancia, esta cantidad de velocidad en la direccion dada. Normalmente necesitas un valor pequeño como 0.1 en una dirección hacia abajo (270 grados). Si marcas la casilla relativa se incremente la gravedad y la dirección. Notese que contrario a la vida real, se pueden poner diferentes direcciones y fuerzas de gravedad a diferentes objetos.

Reverse Horizontal: Con esta accion inviertes el movimiento horizontal de la instancia. Esto puede por ejemplo usarse cuando el objeto choca con una pared vertical.

Reverse Vertical: Con esto inviertes el movimiento vertical de la instancia.

Set Friction: La fricción decrementa la velocidad de una instancia cuando se mueve. Especificando la cantidad de friccion, en cada salto esta cantidad se resta de la velocidad, hasta que la velocidad se convierta en 0. Normalmente queremos valores muy pequeños como 0.01.

Jump to position: Usa esta accion si quieres situar una instancia en una posicion particular. Simplemente especificas las coordenadas x e y para que la instancia se coloque con su punto de referencia en esa posicion. Si marcas Relative, la posicion es relativa a la posicion actual de la instancia. Esta opción es a menudo usada para mover continuamente una instanca en cada salto, incrementando su posicion un poco.

Jump to Start: Esta accion hace que la instancia vuelva a la posición donde fue creada.

Jump to Random: Esta acción mueve la instancia a una posición aleatoria de la habitación. Solo se eligen posiciones donde la instancia no interseca con otra instancia solida. Puedes especificar ademas, el ajuste usado. Puedes especificar un valor horizontal de ajuste separado del vertical.

Align to Grid: Con esta accion puedes redondear a la posición de la instancia en una rejilla. Puedes indicar ambos, el ajuste vertical y el horizontal (El tamaño de las celdas de la rejilla). Esto puede ser util para asegurarte de que las instancias se desplazan en casillas de una medida concreta.

Wrap Screen: Con esta accion puedes hacer que una instancia reaparezca por el otro lado de la habitación si sale por uno de los lados. Esta acción se usa normalmente con el evento Outside. Notese que la instancia debe tener una velocidad para trasladarse y asi funcionar, por que la direccion del “teletransporte” depende de la del movimiento. Puedes indicar si transportarse solo horizontalmente, solo vertical o en ambas direcciones.

Hay que destacar que si estamos desplazando nuestra instancia de objeto con el metodo Jump to position, no funcionará el wrap, ya que este debe llevar alguna velocidad.

Move to Contact: Con esta accion puedes mover la instancia en una dirección dada, mientras entre en contacto con un objeto. Si hay una colision en la posición actual la instancia no se moverá. Sin embargo, la instancia es colocada justo antes de que la colisión ocurra. Puedes especificar la direccion y además, una distancia maxima a mover. Por ejemplo cuando la instancia esta cayendo puedes moverla una distancia maxima mientras un objeto se encuente. Puedes ademas indicar si consideras objetos solidos o todos los objetos. Tipicamente pon esta accion en un evento de colision para asegurarte de que la instancia se para en contacto con la otra instancia envuelta en la colisión. El problema de esta acción es que la instancia solo para si va en la dirección indicada. (En otras ocasiones a mi me hace una especie de wrap y no lo acabo de entender).

Bounce: Cuando pones esta acción en el evento de colision con otro objeto, la instancia rebota desde este objeto de modo natural. Si defines el parámetro preciso como false, solo los muros verticales y horizontales son tradados correctamente. Cuando marcas precise a true, además muros ladeados (incluso curvados) son tratados correctamente. Esto sin embargo es más lento, evidentemente. Además, puedes indicar cuando el bote solo se haga sobre objetos solidos o sobre todos los objetos. Notese que el bote no es completamente real por que depende de muchas propiedades, pero en la mayoría de situaciones el efecto da el pego.

(Por cierto, que estoy sacando todos estos datos de la ayuda del programa y probandolo personalmente a ver si voy aprendiendo :P)

domingo, 16 de diciembre de 2012

Aprendizaje: GameMaker

Estos días, con motivo del concurso de videojuegos organizado por el Blog de Toodaim, estoy repasando el funcionamiento de GameMaker, por lo que he pensasdo en hacerme un mini-manual de lo más importante de programa, sus eventos y sus acciones. Podría haber hecho un manual completo, pero el software ya viene con un par de tutoriales con los que aprender la parte más básica, así que me voy directo al grano.

Cosas importantes en GameMaker:

(objects): Objetos que se instanciaran en los juegos y tendrán unas propiedades y comportamientos.

(rooms): Habitaciones, es decir los niveles o pantallas donde colocaremos los objetos.

(sprites): Imágenes o animaciones que representan visualmente los objetos.

(sounds): sonidos que se usan en el juego, ya sean música o efectos de sonido.

(backgounds): fondos o imágenes que sse usan como fondos para nuestras habitaciones o pantallas.


Eventos:

El sistema comprueba un monton de eventos según interactuamos con él y Gamemaker recoge unos cuantos para poder reaccionar ante ellos. Un evento puede ser pulsar una tecla, pero también sera otro soltarla y otro más mantenerla pulsada (son 3 eventos distintos). Veamos algunos eventos de GameMaker:

Create: Sucede cuando la instancia de un objeto es creada. Es decir, cuando se crea una copia del objeto. Puede usarse, por ejemplo, para preparar variables de juego que deben definirse cuando aparece un objeto o se está iniciando algo en nuestro proyecto.

Destroy: Sucede cuando la instancia es destruida. La instancia del objeto ya no existira cuando este evento sea llamado. Se puede usar, por ejemplo para actualizar puntuaciones al destruir (matar) algún enemigo.

Alarm: Cada instancia tiene 12 alarmas de reloj. Se pueden configurar estas para realizar acciones cada cierto tiempo. Por ejemplo, que un enemigo cambie su estado cada 20 segundos.

Step: Ocurre cada salto en el juego (o fotograma). Aquí se pueden poner acciones que necesites que se ejecuten constantemente. Es un evento con el que hay que tener cuidado por que si ponemos demasiadas cosas en él afectará al rendimiento y se producirán ralentizaciones. Hay 3 eventos step difetentes: begin step, end step y simplemente step, que se ejecutan al inicio del fotograma actual, durante el mismo y cuando termina.

Collision: Ocurre siempre que dos instancias chocan, o más bien cuando se superponen. En este caso dos eventos de colisión se activan, uno para cada instancia. Podemos seleccionar cual nos interesa y añadirle acciones.

Hay diferencias entre colisiones con objetos solidos y no-solidos. Cuando el otro objeto es solido, la instancia vuelve a su posición previa (la que tenía antes de que la colisión sucediera), y luego se ejecuta el evento.

Si el otro objeto no es solido, la instancia no se coloca donde estaba. El evento simplemente se ejecuta en su actual posición. Puedes moverte sobre el objeto si lo deseas y el evento solo te indica una vez que ha habido “choque”.

Keyboard: Cuando el jugador mantiene pulsada una tecla. Puedes elegir para que tecla se capturará el evento o elegir para cosas que ocurran si no se pulsa ninguna tecla, o que comprueba la pulsación de cualquier tecla. Si se pulsan varias teclas a la vez, se activan los eventos para todas las teclas pulsadas.

Mouse: Se puede activar cuando ocurren eventos de raton como que el cursor se situe sobre el sprite que represente la instancia de un objeto, que se pulse uno de los botones del ratón, o no se pulse ninguno, se mantenga pulsado, se suelte, etc.

Dentro de esta sección de eventos se incluyen también eventos para joysticks, por si tenemos conectado alguno.

Otros: Que suelen ser eventos específicos para juegos como por ejemplo

- Ourside room: Que la instancia se salga por completo del nivel actual

- Intersect boundary: Cuando la instancia sale parcialmente de los límites de la habitación.

- Views: Para el uso de vistas en las habitaciones.

- Game start: Inicio del juego.

- Game end: Termina el juego.

- Room start: Se inicia el nivel actual.

- Room end: El nivel termina.

- No more lives: Se han acabado las vidas del jugador.

- No more health: La resistencia del jugador se agotó.

- Animation end: Una animación ha finalizado su ciclo.

- End of path: Si una instancia ha seguido un camino y este ha llegado al final del mismo.

- Close button: Cuando el jugador pulsa el botón cerrar de la ventana de juego.

User defined: Tenemos 16 eventos para personalizar algo que se nos ocurra. Pero para esto hay que saber programar en el lenguaje que usa GameMaker.

Draw: Cuando una instancia es visible, dibuja su sprite cada fotograma en la pantalla. Cuando especificas acciones en el evento de dibujo, el sprite no se dibuja (no lo he comprobado, pero es lo que dice el manual) pero pueden ejecutarse acciones en su lugar. Puede usarse esto para dibujar algo en vez del sprite, o hacer algunos cambios en los parámetros del sprite. Hay un número de acciones de dibujo, pero estas solo se ejecutan si el objeto esta definido como visible. Independientemente de se si dibuja o no, los eventos de colisión se asocian al sprite asociado a la instancia.

Key Press: Suceden cuando se presiona una tecla, pero no de forma continua, es decir, solo se activan una vez aunque después mantengamos pulsado.

Key Release:
Cuando dejamos de pulsar la tecla.

Orden de ejecución de eventos en Gamemaker.

Es importante conocer el orden en el que el programa interpreta los eventos para decidir que acciones colocar en cada uno. El orden es el siguiente:

Begin step 

Alarm 
Keyboard, Key press y Key release 
Mouse 
Step 
Collision
End Step 
Draw

Ahora que ya sabeis como lo hace GameMaker, si os gusta programar o quereis aprender, podeis imaginar como hacerlo vosotros mismos de forma similar. En la programación de un juego hay que tomar distintos eventos que no son otra cosa que acciones del sistema o interacciones del usuario con el mismo o con el ordenador, ante los que hay que decidir que hacer. Solo nos falta hablar de las consecuencias a los eventos o que hacer cuando suceden, es decir, las acciones. Pero eso, por espacio, lo dejamos para la próxima.

jueves, 13 de diciembre de 2012

Código y aprendizaje

Actualmente sigo cursando el Ciclo Formativo de Desarrollo de Aplicaciones Web (voy por el segundo año) y, aunque todavia no soy buen programador, parece que con el tiempo voy mejorando en muchas cosas en las que fallaba antes o que simplemente no sabía como funcionaban. El hecho de crearme juegos muy sencillos o simplemente resolver retos de programación, me irá ayudando a conseguir el hábito que necesito de enfrentarme a la resolución de problemas, a lo que por otro lado, le estoy cogiendo el gustillo y a veces me divierte. (Y eso que nunca he sido muy amigo de esta parte del desarrollo).

En cuanto a los lenguajes, ya he probado muchos y a veces se mezclan en mi cabeza, pero en el fondo todos funcionan de un modo muy similar y basta con tener claro la sintaxis correspondiente en el momento de ponerse a escribir código.

Desde mis inicios con DIV, he escrito programas en BASIC, C, Fenix, PHP, SQL (para bases de datos, las cuales odio), Java, JavaScript (el cual estoy aprendiendo ahora y va muy bien para HTML5 y Unity 3D), ActionScript (Al que no pienso perder la pista ahora que empiezo a dominarlo un poco) y… no se, quizás me deje alguno más. La Programación Orientada a Objetos poco a poco me va quedando más clara y, algunos problemillas que tengo a la hora de planear mis programas, paso previo a enfrentarme al código definitivo, lo iré solucionando con la práctica y el tiempo.

Además, aunque no sean lenguajes de programación en el mismo sentido que los anteriores (son lenguajes de marcas), otros como HTML, CSS o XML orientados a la Web, también me van a ayudar en la parte online, tanto del desarrollo de juegos como su presentación al mundo a través de la red. Me gusta además el “efecto Matrix” que se produce cuando empiezas a tener conocimientos y la curiosidad te lleva a leer código de otras personas para tratar de entenderlo. Por fin veo como funcionan algunas cosas en mis páginas favoritas.

Por cierto, los examenes del curso son el motivo por el que he estado algunos días sin publicar.

domingo, 2 de diciembre de 2012

Concurso GameMaker: Por amor al arte

Después de la iniciativa del Blog de Toodaim, donde dos amiguetes se jugaban quien hacia el mejor juego, con una invitación del perdedor al ganador, de un bocadillo y una Coca Cola (Parece que Asensio va a merendar gratis, por que fue el ganador), la nueva idea, es un concurso abierto a todo el mundo y por eso lo pongo en mi Blog.

Si alguien quiere participar, las bases se pueden leer en el Blog de Toodaim, en el post dedicado a este concurso. ¿El premio? El honor de derrotar al resto de participantes. No hay nada de pasta, ni medallas, ni yates, ni viajes al Caribe (no seais materialistas), solo el orgullo de hacer un juego interesante con las limitaciones que imponen las normas y, sobretodo, aunque no ganemos, tener un minijuego terminado por nosotros, que eso si que es un logro para cualquiera.

Por mi parte, la participación al concurso depende del factor estudio. Intentaré hacer un juego que me pueda gustar, pero tal vez no lo acabe, dado que tengo mucho que estudiar últimamente, y volver ahora a GameMaker me supone reaprender muchas cosas que he olvidado. Si las ideas que me surgen son buenas, quizá esto se pueda convertir en un proyecto o aplicarselas a algo que ya tenga entre manos.

En fin, ahora vuelvo a PHP, JavaScript, HTML y Java que es lo que tengo que estudiar estos dias para seguir con el Curso de Desarrollo de Aplicaciones Web que estoy realizando durante este año. A ver si termino los examenes y tengo algo de tiempo libre.

Participad, disfrutad de crear un juego sencillo en poco tiempo. Aprended mucho de la experiencia, pero eso si, intentemos llevarnos bien, no vale machacar a este pobre Blogger, ni siquiera por amor al arte.