Reglas y estados
Las reglas dan vida a una sala sin escribir código: «cuando el jugador toca una moneda, suma un punto, suena una nota y la moneda desaparece». Cada regla es un evento, lo que tiene que pasar, y una lista de acciones, lo que se hace entonces.
Las máquinas de estados son de un objeto. Cada estado dice qué comportamientos del objeto están encendidos y qué lo hace cambiar de estado: un guardia patrulla, persigue al jugador cuando se acerca y descansa cuando lo pierde.
Las reglas se editan en la ventana Room logic, y las máquinas, en States. Son ventanas aparte que se quedan abiertas mientras trabajas en el lienzo. Si es la primera vez que haces un juego con salas, empieza por Tu primer juego con salas.
Las reglas
Pulsa Logic en la barra del editor de escenas, o Room logic... en la pestaña Room (apartado MORE). Se abre Room logic con las reglas de la sala activa. Si cambias de sala, la ventana pasa a la nueva.
Tiene tres columnas:
- WHEN: las reglas de la sala. Cada fila dice el evento y los ajustes que le has cambiado, como las dos etiquetas de «When two things touch: player coin». A la derecha, cuántas acciones tiene.
- DO: las acciones de la regla elegida, numeradas. Se hacen en ese orden, de arriba abajo.
- SETTINGS: los ajustes de la regla elegida y, debajo, los de la acción elegida. Al pie, la ayuda de las dos y, al elegir una fila, la de ese ajuste si la tiene.
Añadir una regla
- Pulsa + Rule... y elige el evento.
- Con la regla elegida, pulsa + Action... y elige una acción. Repite para añadir más.
- Ajusta la regla y cada acción en SETTINGS.
En una regla When two things touch, la acción Destroy nace con What en other: lo normal es quitar lo que se toca (la moneda), no al que lo toca.
+ Rule... y + Action... abren un selector. A la izquierda está la lista; a la derecha, qué hace lo elegido y sus ajustes con el valor de serie. Escribe para filtrar por nombre. Las flechas mueven la lista sin salir del buscador, Intro añade lo elegido y Esc cierra sin añadir. El doble clic también añade.
Los ajustes
Cada ajuste es una fila de la tabla. Lo que escribes se guarda al salir de la celda, o al elegir en el desplegable.
Los ajustes que nombran algo —una etiqueta, una zona, una variable, una plantilla, un control, una música o una sala— despliegan lo que hay. También admiten un nombre que todavía no existe: puedes escribir la regla antes de colocar el objeto. Si al final no existe, lo avisa el panel de problemas.
Los números admiten coma o punto decimal.
Ordenar, borrar y deshacer
- Up y Down mueven la acción elegida dentro de su regla.
- Las reglas no se reordenan. En cada fotograma se comprueban en el orden de la lista, de arriba abajo.
- Delete borra la acción elegida y, si la regla no tiene ninguna, la regla. Para borrar una regla con acciones, mira los problemas conocidos.
- La ventana no tiene interruptor para apagar una regla sin borrarla. Si la quieres para después, cópiala antes con
Ctrl+C. - Cada cambio es un paso de deshacer del editor de escenas: se deshace con
Ctrl+Zen el editor. - Close esconde la ventana. Lo hecho ya está en la sala, y se guarda con ella.
Copiar reglas entre salas
Haz clic en la lista WHEN. Ctrl+C copia la regla elegida, con sus acciones, y Ctrl+V la pega al final de la lista.
Lo copiado vale para cualquier sala del proyecto: cambia de sala en el editor de escenas y pega en su Room logic. Se guarda una sola regla, hasta que copias otra o cierras el IDE.
La regla pegada nombra lo mismo que en la sala de origen. Si en esta no hay esa etiqueta, esa zona, esa variable de la sala o esa plantilla, lo avisa el panel de problemas. Las variables y los controles del juego son de todas las salas.
Cuándo se comprueban
La línea de arriba de la ventana lo recuerda: en cada fotograma, dentro de la función Update de la sala. Allí van, por este orden, las máquinas de estados, los comportamientos y las reglas.
When the room starts va una sola vez, al final de la carga de la sala: con todos los objetos ya creados y después del código de creación. El código que genera cuenta dónde acaba cada cosa.
Eventos
| Evento | Cuándo salta | Ajustes (valor de serie) |
|---|---|---|
| When the room starts | Una vez, al acabar de cargar la sala. | — |
| Every so often | Cada tantos segundos, contados desde que empieza la sala. | Every (s) (2). Only once (false): solo la primera vez. |
| When two things touch | Mientras un objeto con la etiqueta A toca a uno con la B, por sus colliders: en cada fotograma. | Tag A y Tag B: pueden ser la misma. Not again for (s) (0): cuánto espera antes de volver a saltar. |
| When it enters a zone | Cuando un objeto con la etiqueta toca una zona o un marcador. | Tag. Zone. Fires: enter (al entrar, de serie) o while inside (en cada fotograma que está dentro). |
| When it leaves the room | Cuando un objeto con la etiqueta sale entero de la sala, por cualquier lado. Salta una vez cada vez que sale. | Tag. |
| When a control is pressed | Cuando se pulsa un control del juego (Game › Controls). | Control. Fires: when pressed (al pulsarlo, de serie) o while held (mientras se mantiene). For every object with tag: vacío, salta una vez para la sala; con una etiqueta, una vez por cada objeto que la lleva. Not again for (s) (0): la cadencia mientras se mantiene; con 0, en cada fotograma. |
| When a variable... | Cuando una variable de la sala o del juego cumple la condición. Se mira en cada fotograma. | Variable. Is: == (de serie), !=, <, <=, > o >=. Than (0). Only once (true): una vez cada vez que se carga la sala. |
- When two things touch con Not again for (s) en 0 salta en cada fotograma mientras los dos se tocan. Va bien para recoger cosas, pero no para quitar vidas: se llevaría varias seguidas.
- La espera de Not again for (s) es de la regla entera: después de saltar con una pareja, no salta con ninguna otra hasta que pase.
- Con la misma etiqueta a los dos lados, cada pareja cuenta una vez.
- Con física, When two things touch puede perder algún choque: mira los problemas conocidos.
- Las zonas se miran contra el collider del objeto. Un marcador sin tamaño cuenta como una zona de un píxel.
- When a variable... con Only once en
falsesalta en cada fotograma mientras se cumpla la condición. Con una variable del juego y Only once entrue, puede volver a saltar en la sala siguiente, o al repetir esta.
El sujeto y el otro
Las acciones que eligen a quién tocan (What) y la función propia hablan de dos objetos. El sujeto (subject) es el objeto del que trata la regla, y el otro (other), el que ha tocado. No todos los eventos los tienen:
| Evento | subject (en la función, spr) | other |
|---|---|---|
| When two things touch | el objeto con la Tag A | el objeto con la Tag B |
| When it enters a zone | el que entra | no hay |
| When it leaves the room | el que sale | no hay |
| When a control is pressed, con etiqueta | cada objeto con la etiqueta | no hay |
| Acciones al entrar en un estado | el objeto de la máquina | no hay |
| Los demás | no hay | no hay |
Una acción que pide uno que no hay no se genera, y el panel de problemas lo avisa. Usa entonces every object with tag. La función propia recibe nil en su lugar.
Acciones
| Acción | Qué hace | Ajustes (valor de serie) |
|---|---|---|
| Change a variable | Cambia una variable de la sala o del juego (game.<nombre>). Las del juego pasan de una sala a otra. | Variable. Operation: set le da el valor; add (de serie), subtract y multiply la cambian en ese valor. Value (1). |
| Create from a template | Pone en el juego una copia de una plantilla de la sala. | Template. Where: a zone or a position (de serie), at the subject o at the other. Inside zone: en un punto al azar de esa zona; vacía, en X e Y (0). Con at the subject o at the other, X e Y son un desplazamiento desde ese objeto. Face like it (no): si ese objeto mira a la izquierda, refleja el desplazamiento, la copia y su Linear motion; like it, drawn facing left es para el arte dibujado mirando a la izquierda. |
| Destroy | Saca el objeto del juego: deja de pintarse, de moverse y de tocar nada. | What (subject). Tag. |
| Take health away | Quita vida a un objeto que lleva el comportamiento Health. | What (other). Tag. How much (1). |
| Turn a behaviour on or off | Apaga o enciende un comportamiento. | Behaviour. Turn it: off (de serie) u on. What (every object with tag). Tag. |
| Play an animation | Reproduce un tramo de la hoja de fotogramas del sprite. | What (subject). Tag. First frame y Last frame (0). Frames per second (8). Plays: loop (de serie), once (se queda en el último) o pingpong. |
| Play a note | Un pitido de onda cuadrada, con Sound.tone. | Channel (0). Frequency (Hz) (440). Volume (160). Length (ms) (120). |
| Play a sound effect | Un efecto sintetizado: jump, shoot, coin, hit, explosion, powerup, blip o fall. | Effect (shoot). Channel (1). Volume (180). Pitch (%) (100): con 200 suena una octava más agudo. |
| Play or stop music | Pone o detiene una música del proyecto. Solo suena una a la vez. | Music. Do: play looping (de serie), play once o stop. |
| Lose a life | Resta una a la variable del juego lives y devuelve health a su valor inicial. | — |
| Start a new game | Devuelve todas las variables del juego a su valor inicial. | — |
| Ask for another room | Pide otra sala: escribe su nombre en room.nextScene. | Room: una sala del proyecto, o (this room) para repetir esta. |
| Call a function of yours | Llama a una función tuya: la función propia. | Function: su nombre. |
- What elige a quién toca la acción: el
subject, elotheroevery object with tag, todos los que llevan la Tag de debajo. La Tag solo cuenta con esta última. - Turn a behaviour on or off tiene además
every object in the room: todos los que llevan ese comportamiento, también un Spawner puesto en un marcador, que no tiene etiqueta. - Turn a behaviour on or off ofrece los comportamientos que hacen algo en cada fotograma: todos menos Show a variable y Animation. Apagado, un comportamiento guarda sus ajustes y sigue donde lo dejó. Con física, al apagarlo se le quita al cuerpo la velocidad que le daba, para que no siga resbalando (a Platform control, solo la horizontal). Health apagado no recibe daño.
- Change a variable sobre
healthomaxHealthdel juego deja despuéshealthentre 0 ymaxHealth. - Play an animation detiene la animación propia del sprite: desde ahí, el fotograma lo pone el tramo. Un sprite reproduce un tramo cada vez: uno nuevo sustituye al que sonaba, y el mismo que ya suena no vuelve a empezar. Así, una regla que salta en cada fotograma no lo atasca en el primer fotograma.
- Play a note y Play a sound effect usan los canales 0 a 3. La música ocupa primero los bajos: el 3 es el más seguro para efectos.
explosionsuena por el canal de ruido. - Si alguna regla o algún estado de la sala pone o detiene música, la música de la sala (Room › Music) ya no suena sola al empezar: mandan ellos.
- Lose a life no repite la sala. Para empezarla otra vez, añade Ask for another room con
(this room). - Ask for another room no cambia de sala por sí sola: el bucle del juego lee
room.nextSceney decide cuándo, como cuenta Tu primer juego con salas. En el Play, la vista previa carga la sala pedida si tiene Generate .aru encendido. - Una copia de Create from a template lleva los comportamientos, el código y la máquina de estados de la plantilla (Objetos).
La función propia
Call a function of yours llama a una función tuya, para lo que las acciones no saben hacer. La llamada es la misma en todas las reglas:
Nombre(spr, other, room)
spr: el sujeto de la regla, onilsi no tiene (El sujeto y el otro).other: el otro, que solo existe en When two things touch. En las demás reglas,nil.room: la sala. Desde ella llegas a sus variables (room.vars.<nombre>), a las del juego (room.game.<nombre>), a los objetos por su nombre (room.named["nombre"]) y a la sala que se pide (room.nextScene).
Escríbela en el código del juego: en el fichero principal o en otro .aru que este importe. No la pongas en el código de creación de la sala ni en el de un objeto: ahí solo existe dentro de la sala, y la regla no la encuentra.
En Function escribe su nombre tal cual, solo con letras, cifras y _.
Si el panel de problemas no encuentra func Nombre( al principio de una línea en los .aru del proyecto, lo avisa: el juego compilaría y fallaría al saltar la regla. El panel mira los ficheros guardados; lo que tengas sin guardar en el editor de código todavía no cuenta.
En el Play, la función no se llama, porque la vista previa no compila tu juego. El Output lo dice una vez («Play: Nombre is a function of your game...») y la sala sigue.
Un ejemplo: pisar a un enemigo. La regla es When two things touch, con Tag A player, Tag B enemy y la acción Call a function of yours con Function Pisoton:
// Code/Reglas.aru, importado desde el fichero principal: import "Reglas.aru"
func Pisoton(spr, other, room)
// spr es el jugador (Tag A); other, el enemigo que toca (Tag B)
if (spr.y < other.y) then
other.active = false // le cae encima: fuera el enemigo
room.game.score = room.game.score + 100
end
end
score es una de las cuatro variables del juego que siempre están. Quitar un objeto es poner su active a false, que es lo que hace la acción Destroy.
Máquinas de estados
Una máquina de estados es de un objeto. Cada estado dice:
- qué comportamientos del objeto están encendidos mientras dura;
- con qué valores, si cambia alguno;
- qué se hace al entrar en él;
- qué lo saca de ahí: sus transiciones.
El primer estado de la lista es en el que empieza el objeto.
La ventana States
Elige un objeto y pulsa Edit states... en la pestaña Object, apartado INSTANCE, bajo STATES. Debajo del botón se lee cuántos estados tiene y en cuál empieza.
Se abre States, con el nombre del objeto en el título. Si la dejas abierta y eliges otro objeto, pasa a ser la de ese objeto.
Tiene tres columnas:
- STATES: los estados. + State añade uno (
state 1,state 2…), Remove borra el elegido, y Up y Down lo mueven. El primero lleva(start). A la derecha de cada uno, un resumen: cuántos comportamientos enciende, cuántos valores cambia y cuántas salidas tiene (1 on, 1 set / 2 out). Debajo, Name le cambia el nombre. - IN THIS STATE: lo que hace el estado elegido, en BEHAVIOURS ON, VALUES IN THIS STATE y ON ENTRY.
- WHEN IT LEAVES: sus transiciones.
Al renombrar un estado, las transiciones que iban a él lo siguen. Dos estados no pueden llamarse igual: si escribes un nombre que ya está, la caja vuelve al anterior.
Como en Room logic, cada cambio se deshace con Ctrl+Z en el editor de escenas, y Close esconde la ventana.
Los comportamientos encendidos
BEHAVIOURS ON lista los comportamientos del objeto que hacen algo en cada fotograma: todos menos Show a variable y Animation. Ponlos a true o a false en cada estado.
La máquina solo manda en los que están a true en algún estado. Al entrar en un estado, enciende los suyos y apaga los demás de esa lista. Los que no están a true en ningún estado, como un Health, siguen a lo suyo.
Si el objeto todavía no tiene comportamientos, la tabla lo dice: (this object has none yet). Pónselos antes en el inspector (Comportamientos).
Values in this state
VALUES IN THIS STATE cambia ajustes de los comportamientos mientras dura el estado: el mismo Patrol puede ir despacio en un estado y deprisa en otro.
Cada fila es un ajuste, con el valor del objeto entre corchetes: Patrol · Speed (px/s) [40]. Pon en Here el valor de este estado; vacío, vale el del objeto. Al pasar a un estado que no lo cambia, el ajuste vuelve solo al valor del objeto.
Solo salen los ajustes que el comportamiento lee en cada fotograma. Los que lee una vez al empezar, como el recorrido de Patrol, no:
| Comportamiento | Ajustes que puede cambiar un estado |
|---|---|
| Linear motion | Speed X, Speed Y |
| Patrol | Speed (px/s), Face |
| Follow route | Speed (px/s), At the end |
| Follow / flee | Speed (px/s), Mode, Stop within (px) |
| Sine wave | Amplitude (px), Period (s) |
| Platform control | Speed (px/s), Jump (px/s), Control left, Control right, Control jump, Face |
| Top-down control | Speed (px/s), Directions, Control left, Control right, Control up, Control down, Face |
| Health | When it runs out |
| Destroy when it leaves | Margin (px) |
| Spawner | Every (s), How many each time, Max at once |
En VALUES IN THIS STATE los decimales van con punto. Lo que no vale no entra: con un número fuera de rango, o una opción que no está en la lista, la celda vuelve a lo que tenía. Si ningún comportamiento del objeto tiene ajustes de estos, la tabla dice (no behaviour to change).
Las acciones al entrar
ON ENTRY son las acciones que se hacen al entrar en el estado, una vez y de arriba abajo. Son las mismas que las de las reglas (Acciones). + Action... abre el selector, Remove borra la elegida, y Up y Down la mueven. Sus ajustes salen debajo.
El sujeto es el propio objeto, y no hay other. Las acciones van después de encender y apagar los comportamientos y de poner los valores del estado, así que ya los encuentran puestos. Al cargar la sala se hacen también las del primer estado.
Las transiciones
WHEN IT LEAVES son las salidas del estado. + Transition... añade una, Remove borra la elegida, y Up y Down la mueven: se miran en orden, y manda la primera que se cumple.
To state dice a qué estado va. Una transición nueva va al primer estado que no es este. Un estado sin transiciones es un final: el objeto se queda en él.
| Transición | Sale cuando | Ajustes (valor de serie) |
|---|---|---|
| After a while | Han pasado esos segundos desde que entró en el estado. | After (s) (2). |
| Distance to an object | Otro objeto de la sala, que se elige por su nombre, está más cerca o más lejos que esa distancia. | Object. Is: closer than (de serie) o farther than. Distance (px) (64). |
| Touches a tag | Toca a algún objeto vivo con esa etiqueta. | Tag. |
| When a variable... | Una variable de la sala o del juego cumple la condición. | Variable. Is (==). Than (0). |
La distancia va de la posición de un objeto a la del otro (sus x e y), no de collider a collider. Si el otro objeto ya no está, Distance to an object no salta.
Cómo funciona en el juego
- En cada fotograma, antes que los comportamientos, la máquina de cada objeto cuenta el tiempo y mira las transiciones de su estado. Si una se cumple, cambia de estado, y lo nuevo vale ya en ese mismo fotograma.
- Al entrar en un estado, por este orden: enciende y apaga los comportamientos, pone los valores del estado y hace sus acciones de entrada.
- Al cargar la sala, cada objeto entra en su primer estado cuando ya están creados todos los objetos.
- Los objetos con la misma máquina comparten el código generado: diez guardias iguales dan un solo juego de funciones.
En qué objetos funcionan
Edit states... está a mano en cualquier objeto de una capa de objetos, salvo las rutas y los objetos de una capa Decor. Pero en el juego la máquina solo funciona en los sprites y las imágenes de la sala, y en las copias de una plantilla de sprite, porque mira las distancias y los contactos del sprite del objeto. En una forma o un marcador se edita y no se genera: mira los problemas conocidos.
Una plantilla se lleva la máquina del objeto del que sale. Cada copia que crean un Spawner o Create from a template tiene la suya, y empieza en el primer estado al nacer.
En el lienzo
Con View › What the behaviours do encendido, que es como viene, el lienzo dibuja lo que mira cada máquina:
- un círculo por cada transición Distance to an object, del color del estado del que sale: relleno si salta al acercarse y discontinuo si salta al alejarse;
- debajo de cada objeto con máquina, un punto por estado; el del primer estado lleva anillo.
Del objeto elegido dibuja además a quién mide cada círculo, a quién tiene que tocar, at start si una transición del primer estado ya se cumple al cargar la sala, y la máquina entera en una ficha a su lado.
Lo que avisa el panel de problemas
El panel de problemas revisa las reglas, las acciones al entrar y las transiciones. Una regla sale por su puesto en la lista WHEN, como en Rule 2 (When two things touch) > Tag B: nothing in the room carries the tag "coin". Avisa, entre otras cosas, de:
- un ajuste vacío, o que nombra algo que no hay: un objeto, una zona, una etiqueta que no lleva nadie, una variable, una plantilla, una música, un control del juego o un estado;
- una acción con
subjectuotheren una regla que no lo tiene (El sujeto y el otro); - Call a function of yours sin nombre, o con una función que no encuentra en el código del proyecto;
- Ask for another room sin sala;
- un número que no lo es: entonces se usa el valor de serie;
- Change a variable sobre una variable del juego en When the room starts: la pisa cada vez que se carga la sala, también al repetirla después de perder una vida;
- un objeto con Continuous collision que mira una regla When two things touch o una transición Touches a tag: el cuerpo se para justo en la superficie, sin solaparse, y la regla no ve ese choque.
Si una regla nombra un control que el juego no tiene, el botón Create missing controls del panel lo crea en Game › Controls.
Con el código
- Las reglas acaban en la función
<Sala>Events(room)del.gen.arude la sala (las de When the room starts, al final de<Sala>Load), y cada máquina distinta, en<Sala>Fsm0,<Sala>Fsm1… Lo cuenta El código que genera. - Las máquinas en marcha están en
room.fsm0,room.fsm1…, una por objeto. En cada una,m.spres el sprite del objeto,m.stel número del estado en el que está (el primero es el 0) ym.tlos segundos que lleva en él. En el.gen.aru, encima de cada máquina se lee qué objetos la usan. - When two things touch y Touches a tag preguntan con
sprite.hits. Para reaccionar a un choque físico desde el código de un objeto, usasprite.onCollision.
Problemas conocidos
- Delete borra siempre una acción mientras la regla tenga alguna, porque al elegir una regla su primera acción queda elegida. Para borrar una regla, pulsa Delete una vez por cada acción y otra más para la regla.
- Si agrandas Room logic hacia abajo, las dos tablas de SETTINGS crecen a la vez y la de arriba tapa a la de abajo. La ventana recuerda su tamaño. Hazla más baja hasta que se vean las dos; el ancho no les afecta.
- El panel de problemas nombra las reglas por su puesto («Rule 3»), pero la lista WHEN no las numera, y el doble clic en el aviso abre Room logic en la primera regla. Cuéntalas desde arriba: «Rule 3» es la tercera.
- El selector corta las descripciones largas, como la de Change a variable. Las tablas de esta página las cuentan enteras, y la ayuda de SETTINGS también, una vez añadida.
- En States, si pulsas + Action... o + Transition... justo después de escribir en una celda, esa celda puede escribir un valor vacío en otra fila con el siguiente clic. Haz clic antes en la lista de estados y, después de añadir, repasa los valores.
- Una acción Turn a behaviour on or off al entrar en un estado no apaga el comportamiento si nada más en la sala lo enciende o lo apaga: ni una regla, ni la lista BEHAVIOURS ON de una máquina, ni un objeto que lo lleve apagado de salida (Enabled en
false). El comportamiento sigue funcionando. Haz el cambio con una regla: que la acción al entrar cambie una variable, y que una regla When a variable... apague el comportamiento. - Edit states... también se puede pulsar con una forma o un marcador elegidos, pero esa máquina no llega al juego y el panel de problemas no lo avisa. Pon las máquinas en sprites o imágenes.
- El panel de problemas da por buena una etiqueta o un nombre si lo lleva cualquier objeto de la sala, pero en el juego solo los tienen los sprites, las imágenes y las copias de una plantilla. Una regla When two things touch con un marcador, o una transición Distance to an object hacia un marcador, no salta nunca: para un marcador, usa When it enters a zone. El juego distingue además mayúsculas y el panel no:
enemyyEnemyson dos etiquetas, y cambiar solo las mayúsculas de una etiqueta no la cambia en las reglas. Escríbelas siempre igual. - Al panel de problemas le faltan avisos. No dice nada de Take health away sobre un objeto sin Health, ni de Turn a behaviour on or off de un comportamiento que no lleva nadie de la sala: los dos no hacen nada. Tampoco avisa de Ask for another room hacia una sala que no existe o que has renombrado, ni de Create from a template con una plantilla cuyo sprite se ha borrado, que no crea nada. Revisa esos casos tú.
- Change a variable con una variable
boolostring: usa soloset. Conadd, que es la operación de serie, unboolhace un «o»: sumarlefalseno lo apaga. Con unstring,subtractymultiplyparan el juego con un error. - Con física, When two things touch y Touches a tag pueden perder choques entre dos cuerpos que la física separa, como dos Dynamic: el solape dura un solo paso de física, y con la sala a 60 pasos por segundo y el juego a 30 fps cada fotograma da dos pasos. En una prueba en Windows, a 30 fps la regla vio 4 choques de 6. Si uno de los dos es Visual, la física no los separa y no pasa. Para los golpes entre cuerpos, reacciona en el código del objeto con
sprite.onCollision.
Todos los problemas conocidos de JARU, juntos, están en Problemas conocidos.