Laboratorio (plantilla) de minijuegos para Chimera Party, un Party Game colaborativo de la comunidad de desarrollo de videojuegos de la Universidad de Chile.
Instalación • Diseño • Setup • Desarrollo • Ejemplo • Exportación • Importación • Créditos
- Instala Godot 4.2.x.
- Clona este repositorio.
- Abre Godot e importa el proyecto.
Al desarrollar tu minijuego, tienes libertad total en cuanto a la temática y las mecánicas de juego, la creatividad se valora mucho aquí! Sin embargo, debes adherirte a las siguientes restricciones para asegurar la jugabilidad y el equilibrio:
- 🔢 Número de jugadores: El juego debe estar diseñado para ser jugado por entre 2 y 8 participantes. Puedes enfocarte en un número (o rango) específico de jugadores, siempre y cuando se mantenga dentro de este límite.
- 🎨 Representación de jugadores: Es crucial que las representaciones en el juego de los jugadores sean claras y correspondan fielmente al color que cada uno elija al inicio del juego.
- 💯 Puntaje: Tu minijuego debe incluir un elemento competitivo, asignando puntajes a los jugadores por su desempeño. Importante: el puntaje máximo que un jugador puede obtener no debe exceder los 100 puntos, ni ser menor a los -100 puntos.
- ⌚ Tiempo: Se sugiere no superar un tiempo de ronda de 1 minuto. La idea es que el juego progrese rápido para alcanzar a jugar una gran variedad de minijuegos.
Una vez instalado, cambia el nombre de la carpeta res://games/my_game
al nombre de tu juego. Por ejemplo, si tu minijuego se llama "Super Gaming" la carpeta debería quedar como res://games/super_gaming
.
La carpeta my_game
ya viene con un boilerplate de juego que puedes usar de referencia. Este código se explica en la sección de ejemplo.
Warning
Todo el contenido de tu juego debe estar dentro de la carpeta creada a base de "my_game". Esto incluye código, escenas, sprites, etc.
En el recurso info.tres
se define el nombre, la descripción y la portada de tu juego:
También se definen los inputs que usa tu juego. Estos se muestran como iconos al partir la ronda. Estos consisten en un arreglo de grupos de botones con una descripción. Por ejemplo, Left, Right, Up y Down descritos como Walk.
Tip
Puedes ver un preview de tu pantalla de información corriendo la escena game_info.tscn en la carpeta ui_lab.
En el nodo Game
de game.tscn
en autoload_lab
se definen parametros de testeo, que no serán aplicados en la versión exportada del minijuego.
El número de jugadores que deseas tener al testear tu juego, con sus colores correspondientes.
La ruta del main.tscn
de tu minijuego, luego de que le hayas cambiado el nombre a la carpeta.
El recurso info.tres
mencionado en Datos del minijuego.
Ponle play al proyecto. Deberías ver la pantalla de inicio con la información que ingresaste.
Luego presiona espacio
o enter
para comenzar la ronda de prueba.
A continuación, se explica cómo usar las interfaces y características de Chimera Party para crear tu minijuego. El ejemplo que viene con el proyecto se explica en la siguiente sección.
Se puede conseguir la lista de jugadores con:
Game.players: List[PlayerData]
Un objeto PlayerData
consiste en:
Nombre | Tipo | Descripción |
---|---|---|
input |
int |
ID del layout y dispositivo de este jugador. Ver input |
primary_color |
Color |
Color principal del jugador. Ver colores |
secondary_color |
Color |
Color secundario del jugador. Experimental |
score |
int |
Puntaje total del jugador en la partida. Ver puntaje |
local_score |
int |
Puntaje del jugador en este minijuego. Ver puntaje |
ID | Dispositio | Direccional | Acción |
---|---|---|---|
0 | Teclado | W, A, S, D | Z, X |
1 | Teclado | T, F, G, H | V, B |
2 | Teclado | I, J, K, L | N, M |
3 | Teclado | ↑, ←, ↓, → | RShift, RCtrl |
4 | Gamepad 0 | ↑, ←, ↓, → | A, B |
5 | Gamepad 1 | ↑, ←, ↓, → | A, B |
6 | Gamepad 2 | ↑, ←, ↓, → | A, B |
7 | Gamepad 3 | ↑, ←, ↓, → | A, B |
Donde x
es el ID del input del jugador, las acciones de input en el proyecto tienen los siguientes nombres move_up_x
, move_left_x
, move_down_x
, move_right_x
, action_a_x
, action_b_x
.
Estas se pueden llamar como cualquier input de godot ya sea con eventos:
func _input(event):
if event.is_action_pressed("move_up_" % player_data.input):
jump()
O con polling:
func _physics_process(delta):
if Input.is_action_pressed("move_right_" % player_data.input):
position.x += speed * delta
Si usas de base la clase CharacterPlayer, esto se simplifica. Se puede llamar directamente a move_up
, move_left
, move_down
, move_right
, action_a
y action_b
. Por ejemplo:
func _physics_process(delta: float) -> void:
var move_input = Input.get_vector(
move_left,
move_right,
move_up,
move_down
)
El color del jugador se puede conseguir con
player_data.color
Si usas de base la clase CharacterPlayer, puedes hacerle override a la función update_color
para definir qué hacer con el color del jugador. Por ejemplo:
func update_color() -> void:
body_sprite.self_modulate = data.primary_color
Important
Pendiente: incluir explicación de los shaders
Los puntajes se manejan en el objeto PlayerData
de cada jugador. Si en tu juego se consigue puntaje continuamente, se puede actualizar el puntaje correspondiente de cada jugador con el valor de:
player_data.local_score: int
Si por algún motivo se necesita el puntaje total que lleva cada jugador, se puede acceder a:
player_data.score
Cuando se haya concluido la ronda de tu minijuego, debes llamar:
Game.end_game()
Si en el minijuego el puntaje solo se otorga al final, debe actualizarse antes de llamar a Game.end_game()
.
Se puede mostrar un mensaje en pantalla con:
Debug.log("message")
En el proyecto existe esta clase que se puede usar como base para un personaje controlado por un jugador. Extiende CharacterBody2D, y abstrae algunas de las funcionalidades del multiplayer para hacer más sencillo todo. En particular:
- Crea accesos directos a los inputs del jugador. (Ver input)
- Define el objeto
PlayerData
del jugador comodata
- Provee una función
update_color
que se llama al correr el setup, para hacerle override.
El código de esta clase se puede encontrar en scripts/character_player.gd
.
El juego de ejemplo que viene incluido en el proyecto consiste en un juego 2D con personajes instanciados que extienden la clase CharacterPlayer. Cada jugador acumula puntaje simplemente por existir, y el juego se termina luego de 15 segundos.
El nodo principal de main.tscn
(recordar que main.tscn
es la escena del minijuego que se instancia al iniciar una ronda).
En el evento _ready
se encarga de:
- Instanciar los personajes, acorde al número de jugadores
- Instanciar los contadores de puntaje
En la señal _on_score_timeout
se encarga de sumarle puntaje a cada jugador.
Este nodo existe para ser padre de todos los personajes que se instancien. Tiene dos nodos marcados como placeholder
(se eliminan al ejecutar el juego).
En este nodo se muestra un ejemplo de cómo se podría definir donde aparecen los personajes, usando nodos Marker2D
, que luego en MyGame se usan de referencia.
El canvas layer tiene nodos para contener los puntajes, que se instancian como hijos de ScoreContainer
.
Esta escena es instanciado como hijo de ScoreContainer
por MyGame. En su código:
- Es asignado un jugador en el
setup
lamado porMyGame
- Actualiza el texto del label con el puntaje local actual del jugador
La escena chimerin_lab/chimerin.tscn
extiende la clase CharacterPlayer, y es instanciado por MyGame como hijo de Players
Tip
Los nodos BodySprite
y EyeSprite
son separados para poder aplicar el color solo al cuerpo.
A continuación se explica lo que agrega por sobre la base
En el evento _physics_process
, se consigue el input usando los valores directos definidos por el CharacterPlayer
:
var move_input = Input.get_vector(
move_left,
move_right,
move_up,
move_down)
Y se aplican de forma típica para Godot:
var target_velocity = speed * move_input
velocity = velocity.move_toward(target_velocity, acceleration * delta)
move_and_slide()
Según la dirección y magnitud de movimiento, se usa el nodo de AnimationTree
para animar el chimerín:
if direction.length() > 0.01:
animation_tree.set("parameters/idle/blend_position", direction)
animation_tree.set("parameters/walk/blend_position", direction)
if velocity.length() > 50 or (playback.get_current_node() == "walk" and target_velocity.length() > 50):
playback.travel("walk")
else:
playback.travel("idle")
En el setup, se modula directamente el color del BodySprite
según el color del PlayerData
correspondiente:
func update_color() -> void:
body_sprite.self_modulate = data.primary_color
Los chimerines se pueden empujar entre sí. Esto se maneja antes del movimiento en el _physics_process
:
var direction = move_input
push_direction = move_input
for pusher in _pushers:
var is_pushing = pusher.to_local(global_position).dot(pusher.push_direction) > 0
if is_pushing:
move_input += pusher.push_direction.project(global_position - pusher.global_position)
Este comportamiento es gatillado con las siguientes señales:
func _on_body_entered(body: Node) -> void:
if body != self and body.is_in_group("chimerin"):
body.start_pushing(self)
func _on_body_exited(body: Node) -> void:
if body != self and body.is_in_group("chimerin"):
body.stop_pushing(self)
# ^ Invocan los siguientes métodos:
func start_pushing(pusher: CharacterBody2D) -> void:
_pushers.append(pusher)
func stop_pushing(pusher: CharacterBody2D) -> void:
_pushers.erase(pusher)
Una vez tengas listo tu juego, debes exportarlo para que se pueda instalar en el Chimera Party.
- Ir al menú
Project
>Export
del proyecto en Godot. - Elegir la plataforma. Por defecto Chimera Party está pensado para Windows.
- Seleccionar la opción
PCK/Zip
. - Nombrar el archivo resultante con el mismo nombre que la carpeta de tu juego.
- Guardar como
Godot Project Pack .PCK
.
Para agregar un minijuego a la rotación del Chimera Party:
- Descargar el último ejecutable de Chimera Party.
- Crear una carpeta
games
como hermano del ejecutable. - Dejar el
.pck
del minijuego en la carpetagames
.
.
├── games/
│ ├── chimerin_quest.pck
│ └── beyond_them.pck
└── Chimera_Party.exe
Note
En una partida normal cuando sale un minijuego una vez, su probabilidad de salir nuevamente en la misma partida se reduce a un 10%.
- Proyecto de la Comunidad VGDEV UCHILE.
- Creado por: Elías Zelada
- Contribuciones: