Para cambiar de ritmo, me gustaría hacer un pequeño registro de desarrollo. Hace algún tiempo, participé en un game jam e hice este juego, Of Mice and Bad Choices , un juego de rompecabezas corto en el que colocas queso alrededor del laberinto para atraer a los ratones. Fue divertido, pero evidentemente hubo algunas deficiencias.
Uno de los principales es que el comportamiento de los ratones no es intuitivo. Los jugadores mencionaron que esperarían que los ratones se sintieran repelidos por un queso que no les gusta, no solo por congelarse. Además, implementar esta mecánica permitiría un diseño de rompecabezas mucho más rico.
Entonces, creo que esta es una buena oportunidad para realizar pruebas automatizadas en Godot.
Hay algunos marcos de prueba disponibles para Godot 4, pero el que me llamó la atención es Godot Unit Test (GUT) . GUT es bastante simple:
test_
y escriba algunas afirmaciones (estructura típica de prueba unitaria).
Para este caso particular, quería tener una forma de definir escenarios complejos, de la misma manera que defino los niveles para el juego: en el editor del motor en lugar de en el código (de esta manera, las pruebas estarían más cerca de la realidad). Por eso quiero hacer estas cosas:
Entonces, desenvolvamos esto.
Definamos una nueva clase `MouseTestCase. Queremos que herede Node2D
(ya que queremos colocarlo en una escena. Y queremos que encuentre uno de sus hijos (que nosotros mismos colocaremos en una escena): un mouse y su posición final esperada (como Marcador)
extends Node2D class_name MouseTestCase @export var steps_left = 0 # How many steps to simulate @export var done = false @onready var mouse: Mouse = $Mouse @onready var expected_position = SnapUtils.get_tile_map_position($TestMarker.position)
Ahora podemos ponerlo en escena y ¡estamos bien! Sabemos dónde comienza un mouse, sabemos dónde debe terminar y en cuántos pasos.
Ahora, hagamos muchos más y hagamos un mapa para probar nuestro comportamiento repelente.
Este comportamiento es algo complejo, por lo que queremos cubrir muchos casos ligeramente diferentes:
El mapa resultante que define 12 casos de prueba para cubrir este comportamiento se muestra arriba (imagínese lo tedioso que podría ser codificar todas esas coordenadas en código).
Lo único que queda por hacer es la función de ejecución de pruebas. La función necesita:
El código es bastante simple.
func run_level_with_mouse_test_cases(map_path: String): var level = load(map_path) map.load_level(level) var cases = MouseTestCase.cast_all_cases(get_tree().get_nodes_in_group(MouseTestCase.MTC_GROUP_NAME)) while (cases.any(func(case): return not case.done)): map.move_mice() for case in cases: if not case.done: case.steps_left -= 1 if case.steps_left == 0: case.done = true assert_eq(case.get_mouse_position(), case.expected_position, case.get_parent().name+"/"+case.name)
Me imagino que esto evolucionará, pero la implementación actual es lo suficientemente buena por ahora. ¡Escribí las pruebas, implementé la mecánica y las pruebas realmente confirman que la mecánica está implementada correctamente!
Aquí, he mostrado una forma de abordar las pruebas en los juegos. Obviamente, hay muchas más cosas que mejorar aquí, y animo a los lectores a tomar el código y el marco y adaptarlos a sus necesidades.
Como siempre, el código está disponible en GitHub: https://github.com/d-lowl/of-mice-and-bad-choices También puede echar un vistazo al PR específico que presenta las pruebas. Para obtener puntos de bonificación, sería genial si alguien pudiera hacerlos funcionar en CI. Salud.