"Expert blueprint for party games including minigame resource system (define via .tres files), local multiplayer input (4-player controller management), asymmetric gameplay (1v3 balance), scene management (clean minigame loading/unloading), persistent scoring (track wins across rounds), and split-screen rendering (SubViewport per player). Use for Mario Party-style games or WarioWare collections. Trigger keywords: party_game, minigame_collection, local_multiplayer, asymmetric_gameplay, split_screen, dynamic_input_mapping."
Install
npx skillscat add thedivergentai/gd-agentic-skills/godot-genre-party Install via the SkillsCat registry.
The godot-genre-party skill is a blueprint for local‑multiplayer party games that includes a minigame resource system, 4‑player input handling, asymmetric 1v3 balance, scene management, and persistent scoring. It solves the need to manage multiple controllers, load minigames efficiently, and keep scores across rounds, making it suitable for developers building Mario Party‑style or WarioWare collections.
Genre: Party / Minigame Collection
Expert blueprint for party games balancing accessibility, variety, and social fun.
NEVER Do
- NEVER long tutorials — Players want instant fun. 3-second looping GIF + 1-sentence instruction is ideal.
- NEVER excessive downtime — Loading between 10s minigames kills momentum. Keep assets light, use threaded loading, or persistent board scene.
- NEVER inconsistent controls — Minigame A uses A to jump, B uses B. Standardize: A=Accept/Action, B=Back/Cancel across all minigames.
- NEVER forget dynamic input mapping — Remap InputMap at runtime (InputMap.action_add_event) for "p1_jump", "p2_jump" per controller.
- NEVER ignore accessibility — Color-blind modes, audio cues for visual events, adjustable difficulty. Party games need inclusive design.
Available Scripts
MANDATORY: Read the appropriate script before implementing the corresponding pattern.
party_input_router.gd
4-player device isolation for local multiplayer. Maps device_id to player_id, handles join requests, routes inputs to player-specific signals.
Core Loop
- Lobby: Players join and select characters/colors.
- Meta: Players move on a board or vote for the next game.
- Play: Short, intense minigame (30s - 2m).
- Score: Winners get points/coins.
- Repeat: Cycle continues until a turn limit or score limit.
Skill Chain
| Phase | Skills | Purpose |
|---|---|---|
| 1. Input | input-mapping |
Handling 2-4 local controllers dynamically |
| 2. Scene | godot-scene-management |
Loading/Unloading minigames cleanly |
| 3. Data | godot-resource-data-patterns |
Defining minigames via Resource files |
| 4. UI | godot-ui-containers |
Scoreboards, instructions screens |
| 5. Logic | godot-turn-system |
Managing the "Board Game" phase |
Architecture Overview
1. Minigame Definition
Using Resources to define what a minigame is.
# minigame_data.gd
class_name MinigameData extends Resource
@export var title: String
@export var scene_path: String
@export var instructions: String
@export var is_1v3: bool = false
@export var thumbnail: Texture2D2. The Party Manager
Singleton that persists between minigames.
# party_manager.gd
extends Node
var players: Array[PlayerData] = [] # Tracks score, input_device_id, color
var current_round: int = 1
var max_rounds: int = 10
func start_minigame(minigame: MinigameData) -> void:
# 1. Show instructions scene
await show_instructions(minigame)
# 2. Transition to actual game
get_tree().change_scene_to_file(minigame.scene_path)
# 3. Pass player data to the new scene
# (The minigame scene must look up PartyManager in _ready)3. Minigame Base Class
Every minigame inherits from this to ensure compatibility.
# minigame_base.gd
class_name Minigame extends Node
signal game_ended(results: Dictionary)
func _ready() -> void:
setup_players(PartyManager.players)
start_countdown()
func end_game() -> void:
# Calculate winner
game_ended.emit(results)
PartyManager.handle_minigame_end(results)Key Mechanics Implementation
Local Multiplayer Input
Handling dynamic device assignment.
# player_controller.gd
@export var player_id: int = 0 # 0, 1, 2, 3
func _physics_process(delta: float) -> void:
var device = PartyManager.players[player_id].device_id
# Use the specific device ID for input
var direction = Input.get_vector("p%s_left" % player_id, ...)
# Better approach: Remap InputMap actions at runtime explicitlyAsymmetric Gameplay (1v3)
Balancing the "One" vs the "Many".
- The One: Powerful, high HP, unique abilities (e.g., Bowser suit).
- The Many: Weak individually, must cooperate to survive/win.
Godot-Specific Tips
- SubViewport: Powerful for 4-player split-screen. Each player gets a camera, all rendering the same world (or different worlds!).
- InputEventJoypadButton: Use
Input.get_connected_joypads()to auto-detect controllers on the Lobby screen. - Remapping: Godot's
InputMapsystem can be modified at runtime usingInputMap.action_add_event(). Creating "p1_jump", "p2_jump" dynamically is a common pattern.
Common Pitfalls
- Long Tutorials: Players just want to play. Fix: 3-second looping GIF + 1 sentence instruction overlay before the game starts.
- Downtime: Loading times between 10-second minigames. Fix: Keep minigame assets light. Use a "Board" scene that stays loaded in the background if possible, or use creating
Threadloading. - Confusing Controls: Minigame A uses "A" to jump, Minigame B uses "B". Fix: Standardize. "A" is always Accept/Action. "B" is always Back/Cancel.
Reference
- Master Skill: godot-master