anima-core 0.3.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.reek.yml +27 -1
- data/CHANGELOG.md +4 -0
- data/README.md +219 -25
- data/agents/codebase-analyzer.md +88 -0
- data/agents/codebase-pattern-finder.md +83 -0
- data/agents/documentation-researcher.md +59 -0
- data/agents/thoughts-analyzer.md +102 -0
- data/agents/web-search-researcher.md +71 -0
- data/anima-core.gemspec +3 -0
- data/app/channels/session_channel.rb +76 -28
- data/app/jobs/agent_request_job.rb +24 -0
- data/app/jobs/analytical_brain_job.rb +33 -0
- data/app/jobs/count_event_tokens_job.rb +1 -1
- data/app/models/concerns/event/broadcasting.rb +20 -2
- data/app/models/event.rb +1 -1
- data/app/models/goal.rb +91 -0
- data/app/models/session.rb +347 -22
- data/config/application.rb +2 -0
- data/db/migrate/20260314075248_add_subagent_support_to_sessions.rb +6 -0
- data/db/migrate/20260314112417_add_granted_tools_to_sessions.rb +5 -0
- data/db/migrate/20260314140000_add_name_to_sessions.rb +7 -0
- data/db/migrate/20260314150000_add_viewport_event_ids_to_sessions.rb +7 -0
- data/db/migrate/20260315100000_add_active_skills_to_sessions.rb +7 -0
- data/db/migrate/20260315140843_create_goals.rb +16 -0
- data/db/migrate/20260315144837_add_completed_at_to_goals.rb +5 -0
- data/db/migrate/20260315191105_add_active_workflow_to_sessions.rb +5 -0
- data/lib/agent_loop.rb +65 -9
- data/lib/agents/definition.rb +116 -0
- data/lib/agents/registry.rb +106 -0
- data/lib/analytical_brain/runner.rb +276 -0
- data/lib/analytical_brain/tools/activate_skill.rb +52 -0
- data/lib/analytical_brain/tools/deactivate_skill.rb +43 -0
- data/lib/analytical_brain/tools/deactivate_workflow.rb +34 -0
- data/lib/analytical_brain/tools/everything_is_ready.rb +28 -0
- data/lib/analytical_brain/tools/finish_goal.rb +62 -0
- data/lib/analytical_brain/tools/read_workflow.rb +58 -0
- data/lib/analytical_brain/tools/rename_session.rb +63 -0
- data/lib/analytical_brain/tools/set_goal.rb +60 -0
- data/lib/analytical_brain/tools/update_goal.rb +60 -0
- data/lib/analytical_brain.rb +23 -0
- data/lib/anima/cli/mcp/secrets.rb +76 -0
- data/lib/anima/cli/mcp.rb +197 -0
- data/lib/anima/cli.rb +4 -0
- data/lib/anima/installer.rb +168 -0
- data/lib/anima/settings.rb +226 -0
- data/lib/anima/version.rb +1 -1
- data/lib/anima.rb +9 -0
- data/lib/credential_store.rb +103 -0
- data/lib/environment_probe.rb +232 -0
- data/lib/llm/client.rb +29 -10
- data/lib/mcp/client_manager.rb +86 -0
- data/lib/mcp/config.rb +213 -0
- data/lib/mcp/health_check.rb +77 -0
- data/lib/mcp/secrets.rb +73 -0
- data/lib/mcp/stdio_transport.rb +206 -0
- data/lib/providers/anthropic.rb +8 -7
- data/lib/shell_session.rb +11 -10
- data/lib/skills/definition.rb +97 -0
- data/lib/skills/registry.rb +105 -0
- data/lib/tools/edit.rb +3 -4
- data/lib/tools/mcp_tool.rb +114 -0
- data/lib/tools/read.rb +15 -16
- data/lib/tools/registry.rb +14 -12
- data/lib/tools/request_feature.rb +121 -0
- data/lib/tools/return_result.rb +81 -0
- data/lib/tools/spawn_specialist.rb +109 -0
- data/lib/tools/spawn_subagent.rb +111 -0
- data/lib/tools/subagent_prompts.rb +12 -0
- data/lib/tools/web_get.rb +8 -9
- data/lib/tui/app.rb +332 -43
- data/lib/tui/message_store.rb +20 -0
- data/lib/tui/screens/chat.rb +207 -20
- data/lib/workflows/definition.rb +97 -0
- data/lib/workflows/registry.rb +89 -0
- data/skills/activerecord/SKILL.md +255 -0
- data/skills/activerecord/examples/associations/association_extensions.rb +298 -0
- data/skills/activerecord/examples/associations/basic_associations.rb +118 -0
- data/skills/activerecord/examples/associations/counter_caches.rb +215 -0
- data/skills/activerecord/examples/associations/polymorphic_associations.rb +217 -0
- data/skills/activerecord/examples/associations/self_referential.rb +302 -0
- data/skills/activerecord/examples/associations/through_associations.rb +203 -0
- data/skills/activerecord/examples/basics/crud_operations.rb +209 -0
- data/skills/activerecord/examples/basics/dirty_tracking.rb +218 -0
- data/skills/activerecord/examples/basics/inheritance.rb +377 -0
- data/skills/activerecord/examples/basics/type_casting.rb +317 -0
- data/skills/activerecord/examples/callbacks/alternatives_to_callbacks.rb +447 -0
- data/skills/activerecord/examples/callbacks/conditional_callbacks.rb +353 -0
- data/skills/activerecord/examples/callbacks/lifecycle_callbacks.rb +280 -0
- data/skills/activerecord/examples/callbacks/transaction_callbacks.rb +340 -0
- data/skills/activerecord/examples/migrations/indexes_and_constraints.rb +337 -0
- data/skills/activerecord/examples/migrations/reversible_patterns.rb +403 -0
- data/skills/activerecord/examples/migrations/safe_patterns.rb +420 -0
- data/skills/activerecord/examples/migrations/schema_changes.rb +277 -0
- data/skills/activerecord/examples/querying/batch_processing.rb +226 -0
- data/skills/activerecord/examples/querying/eager_loading.rb +259 -0
- data/skills/activerecord/examples/querying/finder_methods.rb +170 -0
- data/skills/activerecord/examples/querying/optimization.rb +275 -0
- data/skills/activerecord/examples/querying/scopes.rb +260 -0
- data/skills/activerecord/examples/validations/built_in_validators.rb +277 -0
- data/skills/activerecord/examples/validations/conditional_validations.rb +288 -0
- data/skills/activerecord/examples/validations/custom_validators.rb +381 -0
- data/skills/activerecord/examples/validations/database_constraints.rb +432 -0
- data/skills/activerecord/examples/validations/validation_contexts.rb +367 -0
- data/skills/activerecord/references/associations.md +709 -0
- data/skills/activerecord/references/basics.md +622 -0
- data/skills/activerecord/references/callbacks.md +738 -0
- data/skills/activerecord/references/migrations.md +657 -0
- data/skills/activerecord/references/querying.md +655 -0
- data/skills/activerecord/references/validations.md +596 -0
- data/skills/dragonruby/SKILL.md +250 -0
- data/skills/dragonruby/examples/audio/audio_events.rb +55 -0
- data/skills/dragonruby/examples/audio/background_music.rb +29 -0
- data/skills/dragonruby/examples/audio/crossfade.rb +51 -0
- data/skills/dragonruby/examples/audio/music_controls.rb +51 -0
- data/skills/dragonruby/examples/audio/sound_effects.rb +30 -0
- data/skills/dragonruby/examples/core/coordinate_system.rb +27 -0
- data/skills/dragonruby/examples/core/hello_world.rb +24 -0
- data/skills/dragonruby/examples/core/labels.rb +22 -0
- data/skills/dragonruby/examples/core/sprites.rb +35 -0
- data/skills/dragonruby/examples/core/state_management.rb +29 -0
- data/skills/dragonruby/examples/distribution/background_pause.rb +42 -0
- data/skills/dragonruby/examples/distribution/build_workflow.sh +26 -0
- data/skills/dragonruby/examples/distribution/cvars_production.txt +16 -0
- data/skills/dragonruby/examples/distribution/game_metadata_hd.txt +23 -0
- data/skills/dragonruby/examples/distribution/game_metadata_minimal.txt +9 -0
- data/skills/dragonruby/examples/distribution/game_metadata_mobile.txt +31 -0
- data/skills/dragonruby/examples/distribution/platform_detection.rb +36 -0
- data/skills/dragonruby/examples/distribution/steam_metadata.txt +19 -0
- data/skills/dragonruby/examples/entities/collision_detection.rb +43 -0
- data/skills/dragonruby/examples/entities/entity_lifecycle.rb +68 -0
- data/skills/dragonruby/examples/entities/entity_storage.rb +38 -0
- data/skills/dragonruby/examples/entities/factory_methods.rb +45 -0
- data/skills/dragonruby/examples/entities/random_spawning.rb +50 -0
- data/skills/dragonruby/examples/game-logic/reset_patterns.rb +98 -0
- data/skills/dragonruby/examples/game-logic/save_load.rb +101 -0
- data/skills/dragonruby/examples/game-logic/scoring.rb +104 -0
- data/skills/dragonruby/examples/game-logic/state_transitions.rb +103 -0
- data/skills/dragonruby/examples/game-logic/timers.rb +87 -0
- data/skills/dragonruby/examples/input/action_triggers.rb +36 -0
- data/skills/dragonruby/examples/input/analog_movement.rb +28 -0
- data/skills/dragonruby/examples/input/controller_input.rb +28 -0
- data/skills/dragonruby/examples/input/directional_input.rb +24 -0
- data/skills/dragonruby/examples/input/keyboard_input.rb +28 -0
- data/skills/dragonruby/examples/input/mouse_click.rb +26 -0
- data/skills/dragonruby/examples/input/movement_with_bounds.rb +22 -0
- data/skills/dragonruby/examples/input/normalized_movement.rb +32 -0
- data/skills/dragonruby/examples/rendering/frame_animation.rb +32 -0
- data/skills/dragonruby/examples/rendering/labels.rb +32 -0
- data/skills/dragonruby/examples/rendering/layering.rb +51 -0
- data/skills/dragonruby/examples/rendering/solids.rb +61 -0
- data/skills/dragonruby/examples/rendering/sprites.rb +33 -0
- data/skills/dragonruby/examples/rendering/spritesheet_animation.rb +39 -0
- data/skills/dragonruby/examples/scenes/case_dispatch.rb +60 -0
- data/skills/dragonruby/examples/scenes/class_based.rb +150 -0
- data/skills/dragonruby/examples/scenes/pause_overlay.rb +100 -0
- data/skills/dragonruby/examples/scenes/safe_transitions.rb +68 -0
- data/skills/dragonruby/examples/scenes/scene_transitions.rb +98 -0
- data/skills/dragonruby/examples/scenes/send_dispatch.rb +88 -0
- data/skills/dragonruby/references/audio.md +396 -0
- data/skills/dragonruby/references/core.md +385 -0
- data/skills/dragonruby/references/distribution.md +434 -0
- data/skills/dragonruby/references/entities.md +516 -0
- data/skills/dragonruby/references/game-logic/persistence.md +386 -0
- data/skills/dragonruby/references/game-logic/state.md +389 -0
- data/skills/dragonruby/references/input.md +414 -0
- data/skills/dragonruby/references/rendering/animation.md +467 -0
- data/skills/dragonruby/references/rendering/primitives.md +403 -0
- data/skills/dragonruby/references/scenes.md +443 -0
- data/skills/draper-decorators/SKILL.md +344 -0
- data/skills/draper-decorators/examples/application_decorator.rb +61 -0
- data/skills/draper-decorators/examples/decorator_spec.rb +253 -0
- data/skills/draper-decorators/examples/model_decorator.rb +152 -0
- data/skills/draper-decorators/references/anti-patterns.md +640 -0
- data/skills/draper-decorators/references/patterns.md +507 -0
- data/skills/draper-decorators/references/testing.md +559 -0
- data/skills/gh-issue.md +182 -0
- data/skills/mcp-server/SKILL.md +177 -0
- data/skills/mcp-server/examples/dynamic_tools.rb +36 -0
- data/skills/mcp-server/examples/file_manager_tool.rb +85 -0
- data/skills/mcp-server/examples/http_client.rb +48 -0
- data/skills/mcp-server/examples/http_server.rb +97 -0
- data/skills/mcp-server/examples/rails_integration.rb +88 -0
- data/skills/mcp-server/examples/stdio_server.rb +108 -0
- data/skills/mcp-server/examples/streaming_client.rb +95 -0
- data/skills/mcp-server/references/gotchas.md +183 -0
- data/skills/mcp-server/references/prompts.md +98 -0
- data/skills/mcp-server/references/resources.md +53 -0
- data/skills/mcp-server/references/server.md +140 -0
- data/skills/mcp-server/references/tools.md +146 -0
- data/skills/mcp-server/references/transport.md +104 -0
- data/skills/ratatui-ruby/SKILL.md +315 -0
- data/skills/ratatui-ruby/references/core-concepts.md +340 -0
- data/skills/ratatui-ruby/references/events.md +387 -0
- data/skills/ratatui-ruby/references/frameworks.md +522 -0
- data/skills/ratatui-ruby/references/layout.md +423 -0
- data/skills/ratatui-ruby/references/styling.md +268 -0
- data/skills/ratatui-ruby/references/testing.md +433 -0
- data/skills/ratatui-ruby/references/widgets.md +532 -0
- data/skills/rspec/SKILL.md +340 -0
- data/skills/rspec/examples/core/basic_structure.rb +69 -0
- data/skills/rspec/examples/core/configuration.rb +126 -0
- data/skills/rspec/examples/core/hooks.rb +126 -0
- data/skills/rspec/examples/core/memoized_helpers.rb +139 -0
- data/skills/rspec/examples/core/metadata_filtering.rb +144 -0
- data/skills/rspec/examples/core/shared_examples.rb +145 -0
- data/skills/rspec/examples/factory_bot/associations.rb +314 -0
- data/skills/rspec/examples/factory_bot/build_strategies.rb +272 -0
- data/skills/rspec/examples/factory_bot/callbacks.rb +320 -0
- data/skills/rspec/examples/factory_bot/custom_construction.rb +328 -0
- data/skills/rspec/examples/factory_bot/factory_definition.rb +191 -0
- data/skills/rspec/examples/factory_bot/inheritance.rb +314 -0
- data/skills/rspec/examples/factory_bot/traits.rb +293 -0
- data/skills/rspec/examples/factory_bot/transients.rb +229 -0
- data/skills/rspec/examples/matchers/change.rb +115 -0
- data/skills/rspec/examples/matchers/collections.rb +154 -0
- data/skills/rspec/examples/matchers/comparisons.rb +79 -0
- data/skills/rspec/examples/matchers/composing.rb +155 -0
- data/skills/rspec/examples/matchers/custom_matchers.rb +197 -0
- data/skills/rspec/examples/matchers/equality.rb +58 -0
- data/skills/rspec/examples/matchers/errors.rb +136 -0
- data/skills/rspec/examples/matchers/output.rb +103 -0
- data/skills/rspec/examples/matchers/predicates.rb +87 -0
- data/skills/rspec/examples/matchers/truthiness.rb +101 -0
- data/skills/rspec/examples/matchers/types.rb +82 -0
- data/skills/rspec/examples/matchers/yield.rb +147 -0
- data/skills/rspec/examples/mocks/any_instance.rb +172 -0
- data/skills/rspec/examples/mocks/argument_matchers.rb +206 -0
- data/skills/rspec/examples/mocks/constants.rb +177 -0
- data/skills/rspec/examples/mocks/doubles.rb +139 -0
- data/skills/rspec/examples/mocks/expectations.rb +137 -0
- data/skills/rspec/examples/mocks/message_chains.rb +173 -0
- data/skills/rspec/examples/mocks/ordering.rb +144 -0
- data/skills/rspec/examples/mocks/receive_counts.rb +181 -0
- data/skills/rspec/examples/mocks/responses.rb +223 -0
- data/skills/rspec/examples/mocks/spies.rb +149 -0
- data/skills/rspec/examples/mocks/stubbing.rb +133 -0
- data/skills/rspec/examples/rails/channels.rb +250 -0
- data/skills/rspec/examples/rails/controller_specs.rb +302 -0
- data/skills/rspec/examples/rails/helper_specs.rb +245 -0
- data/skills/rspec/examples/rails/job_specs.rb +256 -0
- data/skills/rspec/examples/rails/mailer_specs.rb +228 -0
- data/skills/rspec/examples/rails/matchers.rb +374 -0
- data/skills/rspec/examples/rails/model_specs.rb +193 -0
- data/skills/rspec/examples/rails/request_specs.rb +275 -0
- data/skills/rspec/examples/rails/routing_specs.rb +276 -0
- data/skills/rspec/examples/rails/system_specs.rb +294 -0
- data/skills/rspec/examples/rails/transactions.rb +254 -0
- data/skills/rspec/examples/rails/view_specs.rb +252 -0
- data/skills/rspec/references/core.md +816 -0
- data/skills/rspec/references/factory_bot.md +641 -0
- data/skills/rspec/references/matchers.md +516 -0
- data/skills/rspec/references/mocks.md +381 -0
- data/skills/rspec/references/rails.md +528 -0
- data/templates/soul.md +40 -0
- data/workflows/commit.md +45 -0
- data/workflows/create_handoff.md +98 -0
- data/workflows/create_note.md +82 -0
- data/workflows/create_plan.md +457 -0
- data/workflows/decompose_ticket.md +109 -0
- data/workflows/feature.md +91 -0
- data/workflows/implement_plan.md +87 -0
- data/workflows/iterate_plan.md +247 -0
- data/workflows/research_codebase.md +210 -0
- data/workflows/resume_handoff.md +217 -0
- data/workflows/review_pr.md +320 -0
- data/workflows/thoughts_init.md +71 -0
- data/workflows/validate_plan.md +166 -0
- metadata +284 -1
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
# DragonRuby Rendering Primitives
|
|
2
|
+
|
|
3
|
+
Quick reference for `args.outputs` primitives. Screen: 1280x720, origin bottom-left.
|
|
4
|
+
|
|
5
|
+
## Render Order
|
|
6
|
+
|
|
7
|
+
### Recommended: FIFO with `args.outputs.primitives`
|
|
8
|
+
|
|
9
|
+
Use `args.outputs.primitives` for full control over render order. Items render first-in, first-out (FIFO) regardless of type:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
args.outputs.primitives << { x: 0, y: 0, w: 100, h: 100, r: 255, primitive_marker: :solid }
|
|
13
|
+
args.outputs.primitives << { x: 50, y: 50, w: 64, h: 64, path: 'player.png' } # renders ON TOP of solid
|
|
14
|
+
args.outputs.primitives << { x: 60, y: 120, text: "Score: 100" } # renders ON TOP of sprite
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Fixed Layer Order (Typed Outputs)
|
|
18
|
+
|
|
19
|
+
When using typed outputs, DragonRuby renders in fixed order (bottom to top):
|
|
20
|
+
|
|
21
|
+
1. `args.outputs.solids`
|
|
22
|
+
2. `args.outputs.sprites`
|
|
23
|
+
3. `args.outputs.primitives`
|
|
24
|
+
4. `args.outputs.labels`
|
|
25
|
+
5. `args.outputs.lines`
|
|
26
|
+
6. `args.outputs.borders`
|
|
27
|
+
7. `args.outputs.debug` (dev only)
|
|
28
|
+
|
|
29
|
+
**Limitation**: A solid will always render behind a sprite, even if added later. Use `args.outputs.primitives` to bypass this constraint.
|
|
30
|
+
|
|
31
|
+
## Sprites
|
|
32
|
+
|
|
33
|
+
Most common primitive. Use hash syntax.
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
args.outputs.sprites << {
|
|
37
|
+
# Position & size (required)
|
|
38
|
+
x: 100, y: 100, w: 64, h: 64,
|
|
39
|
+
path: 'sprites/player.png',
|
|
40
|
+
|
|
41
|
+
# Anchors (0.0-1.0, default: 0)
|
|
42
|
+
anchor_x: 0.5, # 0=left, 0.5=center, 1=right
|
|
43
|
+
anchor_y: 0.5, # 0=bottom, 0.5=center, 1=top
|
|
44
|
+
|
|
45
|
+
# Rotation
|
|
46
|
+
angle: 45, # degrees clockwise
|
|
47
|
+
angle_anchor_x: 0.5, # rotation pivot (default: 0.5)
|
|
48
|
+
angle_anchor_y: 0.5,
|
|
49
|
+
|
|
50
|
+
# Flipping
|
|
51
|
+
flip_horizontally: false,
|
|
52
|
+
flip_vertically: false,
|
|
53
|
+
|
|
54
|
+
# Color tinting (0-255)
|
|
55
|
+
r: 255, g: 255, b: 255, # saturation
|
|
56
|
+
a: 255, # transparency
|
|
57
|
+
|
|
58
|
+
# Blending
|
|
59
|
+
blendmode_enum: 1 # 0=none, 1=alpha, 2=additive, 3=mod, 4=multiply
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Centering a Sprite
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
# Manual offset (avoid)
|
|
67
|
+
{ x: 640 - 40, y: 360 - 40, w: 80, h: 80, path: 'sprite.png' }
|
|
68
|
+
|
|
69
|
+
# With anchors (preferred)
|
|
70
|
+
{ x: 640, y: 360, w: 80, h: 80, path: 'sprite.png', anchor_x: 0.5, anchor_y: 0.5 }
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Cropping (Spritesheets)
|
|
74
|
+
|
|
75
|
+
Two coordinate systems:
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
# tile_* - top-left origin (common for texture atlases)
|
|
79
|
+
{ tile_x: 0, tile_y: 0, tile_w: 64, tile_h: 64 }
|
|
80
|
+
|
|
81
|
+
# source_* - bottom-left origin
|
|
82
|
+
{ source_x: 0, source_y: 0, source_w: 64, source_h: 64 }
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Sprite as Solid (Performance)
|
|
86
|
+
|
|
87
|
+
Prefer over `args.outputs.solids` for many rectangles:
|
|
88
|
+
|
|
89
|
+
```ruby
|
|
90
|
+
args.outputs.sprites << {
|
|
91
|
+
x: 0, y: 0, w: 100, h: 100,
|
|
92
|
+
path: :solid,
|
|
93
|
+
r: 255, g: 0, b: 0, a: 128
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Solids
|
|
98
|
+
|
|
99
|
+
Filled rectangles. **Use sparingly** - textures not cached.
|
|
100
|
+
|
|
101
|
+
```ruby
|
|
102
|
+
args.outputs.solids << {
|
|
103
|
+
x: 0, y: 0,
|
|
104
|
+
w: args.grid.w, h: args.grid.h, # full screen
|
|
105
|
+
r: 92, g: 120, b: 230, # RGB (0-255)
|
|
106
|
+
a: 255 # alpha (optional)
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
For many solids, use sprites with `path: :solid` instead.
|
|
111
|
+
|
|
112
|
+
## Labels
|
|
113
|
+
|
|
114
|
+
Text rendering. **Note**: Default anchor is TOP-LEFT (unlike other primitives).
|
|
115
|
+
|
|
116
|
+
```ruby
|
|
117
|
+
args.outputs.labels << {
|
|
118
|
+
x: 640, y: 360,
|
|
119
|
+
text: "Score: #{args.state.score}",
|
|
120
|
+
|
|
121
|
+
# Size (choose one)
|
|
122
|
+
size_enum: 0, # -2=18px, -1=20px, 0=22px, 1=24px, 2=26px
|
|
123
|
+
size_px: 22, # explicit pixels (overrides size_enum)
|
|
124
|
+
|
|
125
|
+
# Alignment (legacy)
|
|
126
|
+
alignment_enum: 1, # 0=left, 1=center, 2=right
|
|
127
|
+
vertical_alignment_enum: 1, # 0=bottom, 1=center, 2=top
|
|
128
|
+
|
|
129
|
+
# Anchors (preferred over alignment_enum)
|
|
130
|
+
anchor_x: 0.5, # overrides alignment_enum
|
|
131
|
+
anchor_y: 0.5, # default: 1.0 (top)
|
|
132
|
+
|
|
133
|
+
# Color
|
|
134
|
+
r: 0, g: 0, b: 0, a: 255,
|
|
135
|
+
|
|
136
|
+
# Font
|
|
137
|
+
font: 'fonts/manaspc.ttf'
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Common Label Patterns
|
|
142
|
+
|
|
143
|
+
```ruby
|
|
144
|
+
# Top-left score
|
|
145
|
+
{ x: 40, y: args.grid.h - 40, text: "Score: #{score}", size_enum: 4 }
|
|
146
|
+
|
|
147
|
+
# Top-right timer
|
|
148
|
+
{ x: args.grid.w - 40, y: args.grid.h - 40, text: "Time: #{time}",
|
|
149
|
+
alignment_enum: 2 }
|
|
150
|
+
|
|
151
|
+
# Centered title
|
|
152
|
+
{ x: 640, y: 400, text: "GAME OVER", size_px: 48,
|
|
153
|
+
anchor_x: 0.5, anchor_y: 0.5 }
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Borders
|
|
157
|
+
|
|
158
|
+
Unfilled rectangles (outlines). Same properties as solids.
|
|
159
|
+
|
|
160
|
+
```ruby
|
|
161
|
+
args.outputs.borders << {
|
|
162
|
+
x: 100, y: 100, w: 200, h: 150,
|
|
163
|
+
r: 255, g: 0, b: 0, a: 255
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Lines
|
|
168
|
+
|
|
169
|
+
Line segments between two points.
|
|
170
|
+
|
|
171
|
+
```ruby
|
|
172
|
+
args.outputs.lines << {
|
|
173
|
+
x: 100, y: 100, # start
|
|
174
|
+
x2: 300, y2: 300, # end
|
|
175
|
+
r: 255, g: 0, b: 0, a: 255
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
# Alternative: relative with w/h
|
|
179
|
+
{ x: 100, y: 100, w: 200, h: 200 } # equivalent to x2: 300, y2: 300
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Mixed Primitives (Recommended)
|
|
183
|
+
|
|
184
|
+
Use `args.outputs.primitives` for FIFO render order control. Requires `primitive_marker` for solids and borders:
|
|
185
|
+
|
|
186
|
+
```ruby
|
|
187
|
+
def tick args
|
|
188
|
+
# All primitives render in insertion order (FIFO)
|
|
189
|
+
args.outputs.primitives << { x: 0, y: 0, w: 1280, h: 720, r: 30, g: 30, b: 50, primitive_marker: :solid } # background
|
|
190
|
+
args.outputs.primitives << { x: 100, y: 100, w: 64, h: 64, path: 'player.png' } # sprite (auto-detected via path)
|
|
191
|
+
args.outputs.primitives << { x: 100, y: 170, text: "Player 1" } # label (auto-detected via text)
|
|
192
|
+
args.outputs.primitives << { x: 90, y: 90, w: 84, h: 100, r: 255, g: 255, b: 0, primitive_marker: :border } # border ON TOP
|
|
193
|
+
end
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### primitive_marker Values
|
|
197
|
+
|
|
198
|
+
| Type | primitive_marker | Auto-detected by |
|
|
199
|
+
|------|------------------|------------------|
|
|
200
|
+
| Solid | `:solid` | Required |
|
|
201
|
+
| Border | `:border` | Required |
|
|
202
|
+
| Sprite | `:sprite` | `path` property |
|
|
203
|
+
| Label | `:label` | `text` property |
|
|
204
|
+
| Line | `:line` | `x2`/`y2` properties |
|
|
205
|
+
|
|
206
|
+
## Static Outputs (Performance)
|
|
207
|
+
|
|
208
|
+
Cache primitives that don't change:
|
|
209
|
+
|
|
210
|
+
```ruby
|
|
211
|
+
# First frame only
|
|
212
|
+
if args.state.tick_count == 0
|
|
213
|
+
args.outputs.static_sprites << {
|
|
214
|
+
x: 0, y: 0, w: 1280, h: 720,
|
|
215
|
+
path: 'backgrounds/level1.png'
|
|
216
|
+
}
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Clear when needed
|
|
220
|
+
args.outputs.static_sprites.clear
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Available: `static_solids`, `static_sprites`, `static_labels`, `static_lines`, `static_borders`, `static_primitives`
|
|
224
|
+
|
|
225
|
+
## Debug Output
|
|
226
|
+
|
|
227
|
+
Rendered only in development, hidden in production builds:
|
|
228
|
+
|
|
229
|
+
```ruby
|
|
230
|
+
args.outputs.debug << { x: 10, y: 710, text: "FPS: #{args.gtk.current_framerate}" }.label!
|
|
231
|
+
|
|
232
|
+
# Quick watch
|
|
233
|
+
args.outputs.debug.watch args.state.player
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Background Color
|
|
237
|
+
|
|
238
|
+
```ruby
|
|
239
|
+
args.outputs.background_color = [92, 120, 230] # RGB
|
|
240
|
+
args.outputs.background_color = [92, 120, 230, 255] # RGBA
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Class Syntax (Best Performance)
|
|
244
|
+
|
|
245
|
+
```ruby
|
|
246
|
+
class Player
|
|
247
|
+
attr_sprite # adds all sprite properties
|
|
248
|
+
|
|
249
|
+
def initialize
|
|
250
|
+
@x, @y, @w, @h = 100, 100, 64, 64
|
|
251
|
+
@path = 'sprites/player.png'
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
args.outputs.sprites << Player.new
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Also available: `attr_label`, `attr_line`
|
|
259
|
+
|
|
260
|
+
## Best Practices
|
|
261
|
+
|
|
262
|
+
1. **Use hash syntax** - explicit, maintainable
|
|
263
|
+
2. **Use `args.grid.w/h`** - not magic numbers
|
|
264
|
+
3. **Use anchors for centering** - not manual offset calculations
|
|
265
|
+
4. **Use `path: :solid`** - instead of `args.outputs.solids` for many rectangles
|
|
266
|
+
5. **Use static outputs** - for backgrounds and unchanging elements
|
|
267
|
+
6. **Render in order** - backgrounds first, UI last
|
|
268
|
+
7. **Flatten arrays** - DragonRuby handles `sprites << [player, enemies, bullets]`
|
|
269
|
+
8. **Use `args.outputs.primitives`** - for full FIFO control over render order
|
|
270
|
+
|
|
271
|
+
## Common Antipatterns
|
|
272
|
+
|
|
273
|
+
### Magic Numbers
|
|
274
|
+
|
|
275
|
+
```ruby
|
|
276
|
+
# WRONG - hardcoded screen dimensions
|
|
277
|
+
if player.x > 1280
|
|
278
|
+
player.x = 1280
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# CORRECT - use grid constants
|
|
282
|
+
if player.x > args.grid.w
|
|
283
|
+
player.x = args.grid.w
|
|
284
|
+
end
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
**Why:** Screen dimensions may vary; grid constants ensure portability.
|
|
288
|
+
|
|
289
|
+
### Array Syntax
|
|
290
|
+
|
|
291
|
+
```ruby
|
|
292
|
+
# WRONG - positional arguments are hard to read
|
|
293
|
+
args.outputs.labels << [640, 500, 'Hello', 5, 1]
|
|
294
|
+
|
|
295
|
+
# CORRECT - hash syntax is explicit and maintainable
|
|
296
|
+
args.outputs.labels << { x: 640, y: 500, text: 'Hello', size_enum: 5, alignment_enum: 1 }
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Why:** Array syntax is error-prone and difficult to maintain.
|
|
300
|
+
|
|
301
|
+
### Manual Centering
|
|
302
|
+
|
|
303
|
+
```ruby
|
|
304
|
+
# WRONG - manual offset calculation
|
|
305
|
+
{ x: 640 - sprite_w / 2, y: 360 - sprite_h / 2, w: sprite_w, h: sprite_h, path: 'sprite.png' }
|
|
306
|
+
|
|
307
|
+
# CORRECT - use anchors
|
|
308
|
+
{ x: 640, y: 360, w: sprite_w, h: sprite_h, path: 'sprite.png', anchor_x: 0.5, anchor_y: 0.5 }
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
**Why:** Anchors are clearer and automatically handle size changes.
|
|
312
|
+
|
|
313
|
+
### Many Solids
|
|
314
|
+
|
|
315
|
+
```ruby
|
|
316
|
+
# WRONG - solids are not cached, poor performance
|
|
317
|
+
100.times { |i| args.outputs.solids << { x: i * 10, y: 0, w: 8, h: 100 } }
|
|
318
|
+
|
|
319
|
+
# CORRECT - use sprites with path: :solid for many rectangles
|
|
320
|
+
100.times { |i| args.outputs.sprites << { x: i * 10, y: 0, w: 8, h: 100, path: :solid, r: 255 } }
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**Why:** Sprites with `path: :solid` are GPU-cached and much faster for many rectangles.
|
|
324
|
+
|
|
325
|
+
### Recreating Static Content
|
|
326
|
+
|
|
327
|
+
```ruby
|
|
328
|
+
# WRONG - recreates background every frame
|
|
329
|
+
def tick(args)
|
|
330
|
+
args.outputs.sprites << { x: 0, y: 0, w: 1280, h: 720, path: 'background.png' }
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
# CORRECT - use static_sprites (renders once)
|
|
334
|
+
def tick(args)
|
|
335
|
+
if Kernel.tick_count == 0
|
|
336
|
+
args.outputs.static_sprites << { x: 0, y: 0, w: 1280, h: 720, path: 'background.png' }
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
**Why:** Static outputs are only processed once, reducing per-frame overhead.
|
|
342
|
+
|
|
343
|
+
## Property Defaults
|
|
344
|
+
|
|
345
|
+
| Property | Default |
|
|
346
|
+
|----------|---------|
|
|
347
|
+
| `anchor_x`, `anchor_y` | 0 (bottom-left) |
|
|
348
|
+
| `angle` | 0 |
|
|
349
|
+
| `r`, `g`, `b` | 255 (sprites), 0 (others) |
|
|
350
|
+
| `a` | 255 |
|
|
351
|
+
| `blendmode_enum` | 1 (alpha) |
|
|
352
|
+
| `flip_horizontally/vertically` | false |
|
|
353
|
+
|
|
354
|
+
## Decision Tree
|
|
355
|
+
|
|
356
|
+
```
|
|
357
|
+
What do you want to render?
|
|
358
|
+
│
|
|
359
|
+
├─ Image/texture?
|
|
360
|
+
│ └─ Use sprites → examples/rendering/sprites.rb
|
|
361
|
+
│
|
|
362
|
+
├─ Colored rectangle?
|
|
363
|
+
│ ├─ Few rectangles? → Use solids
|
|
364
|
+
│ └─ Many rectangles? → Use sprites with path: :solid → examples/rendering/solids.rb
|
|
365
|
+
│
|
|
366
|
+
├─ Text?
|
|
367
|
+
│ └─ Use labels → examples/rendering/labels.rb
|
|
368
|
+
│
|
|
369
|
+
├─ Outline rectangle?
|
|
370
|
+
│ └─ Use borders → examples/rendering/solids.rb
|
|
371
|
+
│
|
|
372
|
+
├─ Line segment?
|
|
373
|
+
│ └─ Use lines
|
|
374
|
+
│
|
|
375
|
+
├─ Need control over render order?
|
|
376
|
+
│ └─ Use args.outputs.primitives with primitive_marker (recommended for most cases)
|
|
377
|
+
│
|
|
378
|
+
├─ Static content (doesn't change)?
|
|
379
|
+
│ └─ Use static_* outputs → once on first frame
|
|
380
|
+
│
|
|
381
|
+
└─ Debug info only?
|
|
382
|
+
└─ Use args.outputs.debug → hidden in production
|
|
383
|
+
|
|
384
|
+
Performance concern?
|
|
385
|
+
│
|
|
386
|
+
├─ Many similar sprites?
|
|
387
|
+
│ └─ Use class with attr_sprite
|
|
388
|
+
│
|
|
389
|
+
├─ Background never changes?
|
|
390
|
+
│ └─ Use static_sprites
|
|
391
|
+
│
|
|
392
|
+
└─ Rendering many rectangles?
|
|
393
|
+
└─ Use sprites with path: :solid instead of solids
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
## Examples Index
|
|
397
|
+
|
|
398
|
+
| Example | Purpose |
|
|
399
|
+
|---------|---------|
|
|
400
|
+
| `examples/rendering/solids.rb` | Filled rectangles, backgrounds, borders |
|
|
401
|
+
| `examples/rendering/sprites.rb` | Images, anchors, rotation, color tinting |
|
|
402
|
+
| `examples/rendering/labels.rb` | Text alignment, sizing, fonts |
|
|
403
|
+
| `examples/rendering/layering.rb` | Render order, z-index control |
|