This skill should be used when the user asks to "create a game", "make a game", "game development", "dragonruby", "drgtk", "game loop", "tick method", "sprite rendering", "game state", or mentions args.outputs, args.state, args.inputs, coordinate system, collision detection, animation frames, or scene management. Should also be used when editing DragonRuby game files, working on 2D game logic, or discussing game performance optimization.
Provides DragonRuby Game Toolkit guidance for building 2D games. Use when user mentions game loop, sprite rendering, args.state/inputs/outputs, collision detection, or asks to create a game.
/plugin marketplace add hoblin/claude-ruby-marketplace/plugin install dragonruby@claude-ruby-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
examples/audio/audio_events.rbexamples/audio/background_music.rbexamples/audio/crossfade.rbexamples/audio/music_controls.rbexamples/audio/sound_effects.rbexamples/core/coordinate_system.rbexamples/core/hello_world.rbexamples/core/labels.rbexamples/core/sprites.rbexamples/core/state_management.rbexamples/distribution/background_pause.rbexamples/distribution/build_workflow.shexamples/distribution/cvars_production.txtexamples/distribution/game_metadata_hd.txtexamples/distribution/game_metadata_minimal.txtexamples/distribution/game_metadata_mobile.txtexamples/distribution/platform_detection.rbexamples/distribution/steam_metadata.txtexamples/entities/collision_detection.rbexamples/entities/entity_lifecycle.rbThis skill provides comprehensive guidance for building 2D games with DragonRuby Game Toolkit (DRGTK). Use for game loop implementation, sprite rendering, input handling, collision detection, animation, and scene management.
def boot args
args.state = {}
end
def tick args
# Called 60 times per second
args.state.player ||= { x: 640, y: 360, w: 50, h: 50, path: 'player.png' }
# Handle input
args.state.player.x += 5 if args.inputs.right
args.state.player.x -= 5 if args.inputs.left
# Render
args.outputs.sprites << args.state.player
end
| Concept | Purpose |
|---|---|
def tick(args) | Main game loop (60 FPS) |
args.outputs | Render sprites, labels, primitives |
args.state | Persistent game data storage |
args.inputs | Keyboard, mouse, controller input |
args.grid | Screen dimensions (1280x720) |
Geometry | Collision detection helpers |
(0, 720) ─────────────── (1280, 720)
│ │
│ 1280 × 720 │
│ │
(0, 0) ─────────────── (1280, 0)
Use args.outputs.primitives for FIFO (first-in, first-out) render order control.
args.outputs.primitives << {
x: 100, y: 100, w: 64, h: 64,
path: 'sprites/player.png',
angle: 45,
anchor_x: 0.5, anchor_y: 0.5,
r: 255, g: 255, b: 255, a: 255,
flip_horizontally: false
}
args.outputs.primitives << {
x: 640, y: 360,
text: "Score: #{args.state.score}",
size_px: 22,
anchor_x: 0.5, anchor_y: 0.5,
r: 255, g: 255, b: 255
}
# Filled rectangle (use primitive_marker: :solid)
args.outputs.primitives << {
x: 0, y: 0, w: 100, h: 100,
r: 255, g: 0, b: 0,
primitive_marker: :solid
}
# For many rectangles, use path: :solid for better performance
args.outputs.primitives << { x: 0, y: 0, w: 100, h: 100, path: :solid, r: 255, g: 0, b: 0 }
# Outline rectangle
args.outputs.primitives << { x: 0, y: 0, w: 100, h: 100, r: 0, g: 0, b: 0, primitive_marker: :border }
Use args.state with ||= for lazy initialization:
def tick args
args.state.player ||= { x: 640, y: 360 }
args.state.enemies ||= []
args.state.score ||= 0
args.state.scene ||= :title
end
# Directional (arrows, WASD, gamepad)
args.inputs.up / down / left / right
# Magnitude values
args.inputs.left_right # -1, 0, or 1
args.inputs.up_down # -1, 0, or 1
args.inputs.keyboard.key_down.space # Pressed this frame
args.inputs.keyboard.key_held.space # Held down
args.inputs.keyboard.key_up.space # Released this frame
args.inputs.mouse.click # Any button clicked
args.inputs.mouse.x / .y # Position
args.inputs.mouse.inside_rect?(rect) # Collision check
if Geometry.intersect_rect?(player, enemy)
enemy.dead = true
args.state.score += 1
end
# Clean up dead entities
args.state.enemies.reject! { |e| e.dead }
# Frame-based animation
sprite_index = 0.frame_index(count: 6, hold_for: 8, repeat: true)
args.state.player.path = "sprites/player-#{sprite_index}.png"
def tick args
args.state.scene ||= :title
send("#{args.state.scene}_tick", args)
end
def title_tick args
args.outputs.labels << { x: 640, y: 400, text: "Press SPACE", anchor_x: 0.5 }
args.state.scene = :gameplay if args.inputs.keyboard.key_down.space
end
def gameplay_tick args
# Game logic here
end
||= for state initialization$gtk.reset during development to reset stateargs.outputs.primitives for FIFO render order controlprimitive_marker: :solid or :border for rectangle typesFPS = 60)For detailed API documentation and patterns:
references/core.md - Game loop, args object, rendering, coordinatesreferences/input.md - Keyboard, mouse, controller input patternsreferences/entities.md - Entity spawning, collision, lifecyclereferences/game-logic/state.md - Timers, scoring, scene transitionsreferences/game-logic/persistence.md - Save/load, file I/O patternsreferences/audio.md - Sound effects, music playback, audio controlsreferences/rendering/primitives.md - Sprites, labels, solids, borders, layeringreferences/rendering/animation.md - frame_index, spritesheets, easing functionsWorking code in examples/:
examples/core/ - Hello world, sprites, labels, state, coordinatesexamples/input/ - Directional, keyboard, mouse, movementexamples/entities/ - Storage, factories, collision, lifecycleexamples/game-logic/ - Timers, scoring, save/load, state transitionsexamples/audio/ - Sound effects, background music, pause/resumeexamples/rendering/ - Sprites, labels, animation, layeringdef tick args
# Game logic
end
$gtk.reset # Add at end during development
$gtk.reset # Immediate reset
$gtk.reset_next_tick # Reset before next tick (safer)
args.outputs.debug << "Frame: #{Kernel.tick_count}"
args.outputs.debug.watch args.state.player
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.