anima-core 0.2.1 → 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 +19 -0
- data/README.md +213 -43
- 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 +195 -45
- data/app/decorators/user_message_decorator.rb +16 -5
- data/app/jobs/agent_request_job.rb +55 -2
- data/app/jobs/analytical_brain_job.rb +33 -0
- data/app/jobs/count_event_tokens_job.rb +15 -4
- data/app/models/concerns/event/broadcasting.rb +81 -0
- data/app/models/event.rb +20 -1
- data/app/models/goal.rb +91 -0
- data/app/models/session.rb +366 -21
- data/config/application.rb +2 -0
- data/config/initializers/event_subscribers.rb +0 -1
- data/config/routes.rb +0 -6
- data/db/migrate/20260313010000_add_status_to_events.rb +8 -0
- data/db/migrate/20260313020000_add_processing_to_sessions.rb +7 -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 -6
- 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 +5 -40
- 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/events/subscribers/persister.rb +1 -0
- data/lib/events/user_message.rb +17 -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 +11 -20
- 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 +226 -0
- data/lib/tools/mcp_tool.rb +114 -0
- data/lib/tools/read.rb +151 -0
- 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/tools/write.rb +86 -0
- data/lib/tui/app.rb +985 -26
- data/lib/tui/cable_client.rb +69 -31
- data/lib/tui/message_store.rb +103 -8
- data/lib/tui/screens/chat.rb +293 -45
- 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 +290 -3
- data/app/controllers/api/sessions_controller.rb +0 -25
- data/lib/events/subscribers/action_cable_bridge.rb +0 -59
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
# Input Handling Reference
|
|
2
|
+
|
|
3
|
+
DragonRuby provides unified input through `args.inputs`, supporting keyboard, mouse, controller (up to 4), and touch devices.
|
|
4
|
+
|
|
5
|
+
## Unified Directional Input
|
|
6
|
+
|
|
7
|
+
Combine keyboard (arrows + WASD) and controller_one automatically:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
# Boolean checks - true if any matching input active
|
|
11
|
+
args.inputs.up # Arrow up, W, dpad up, analog up
|
|
12
|
+
args.inputs.down # Arrow down, S, dpad down, analog down
|
|
13
|
+
args.inputs.left # Arrow left, A, dpad left, analog left
|
|
14
|
+
args.inputs.right # Arrow right, D, dpad right, analog right
|
|
15
|
+
|
|
16
|
+
# Numeric values: -1, 0, or +1
|
|
17
|
+
args.inputs.left_right # Horizontal: -1 left, 0 neutral, +1 right
|
|
18
|
+
args.inputs.up_down # Vertical: -1 down, 0 neutral, +1 up
|
|
19
|
+
|
|
20
|
+
# Float values: -1.0 to +1.0 (analog-aware)
|
|
21
|
+
args.inputs.left_right_perc # Prioritizes analog stick magnitude
|
|
22
|
+
args.inputs.up_down_perc # Prioritizes analog stick magnitude
|
|
23
|
+
|
|
24
|
+
# Normalized vector for diagonal-safe movement
|
|
25
|
+
args.inputs.directional_vector # { x: 0.707, y: 0.707 } or nil
|
|
26
|
+
args.inputs.directional_angle # Degrees 0-360 or nil
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Directional Variants
|
|
30
|
+
|
|
31
|
+
| Method | WASD | Arrows | D-Pad | Analog | Returns |
|
|
32
|
+
|--------|------|--------|-------|--------|---------|
|
|
33
|
+
| `left_right` | ✓ | ✓ | ✓ | ✓ (60%) | -1, 0, +1 |
|
|
34
|
+
| `left_right_perc` | ✓ | ✓ | ✓ | ✓ | -1.0 to +1.0 |
|
|
35
|
+
| `left_right_directional` | ✗ | ✓ | ✓ | ✗ | -1, 0, +1 |
|
|
36
|
+
| `left_right_directional_perc` | ✗ | ✓ | ✓ | ✓ | -1.0 to +1.0 |
|
|
37
|
+
|
|
38
|
+
Same pattern for `up_down*` variants.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Keyboard Input
|
|
43
|
+
|
|
44
|
+
Access via `args.inputs.keyboard`:
|
|
45
|
+
|
|
46
|
+
### Key States
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
args.inputs.keyboard.key_down.space # First frame pressed
|
|
50
|
+
args.inputs.keyboard.key_held.space # Every frame while held
|
|
51
|
+
args.inputs.keyboard.key_up.space # Frame released
|
|
52
|
+
args.inputs.keyboard.space # Down OR held (shorthand)
|
|
53
|
+
args.inputs.keyboard.key_repeat.space # OS key repeat rate
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Dynamic Key Queries
|
|
57
|
+
|
|
58
|
+
```ruby
|
|
59
|
+
args.inputs.keyboard.key_down?(:enter)
|
|
60
|
+
args.inputs.keyboard.key_held?(:enter)
|
|
61
|
+
args.inputs.keyboard.key_up?(:enter)
|
|
62
|
+
args.inputs.keyboard.key_down_or_held?(:enter)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Key Names Reference
|
|
66
|
+
|
|
67
|
+
| Category | Keys |
|
|
68
|
+
|----------|------|
|
|
69
|
+
| Letters | `a` through `z` |
|
|
70
|
+
| Numbers | `zero`, `one`, ... `nine` |
|
|
71
|
+
| Arrows | `left`, `right`, `up`, `down` (aliases for `left_arrow`, etc.) |
|
|
72
|
+
| Modifiers | `shift`, `ctrl`, `alt`, `meta` (+ `_left`, `_right` variants) |
|
|
73
|
+
| Function | `f1` through `f12` |
|
|
74
|
+
| Special | `space`, `enter`, `escape`, `tab`, `backspace`, `delete` |
|
|
75
|
+
| Navigation | `home`, `end`, `page_up`, `page_down`, `insert` |
|
|
76
|
+
| Numpad | `kp_zero` ... `kp_nine`, `kp_plus`, `kp_enter`, etc. |
|
|
77
|
+
| WASD Scancode | `w_scancode`, `a_scancode`, `s_scancode`, `d_scancode` |
|
|
78
|
+
|
|
79
|
+
### Modifier Combinations
|
|
80
|
+
|
|
81
|
+
```ruby
|
|
82
|
+
args.inputs.keyboard.ctrl_s # Ctrl+S
|
|
83
|
+
args.inputs.keyboard.shift_a # Shift+A
|
|
84
|
+
args.inputs.keyboard.alt_enter # Alt+Enter
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Keyboard Helpers
|
|
88
|
+
|
|
89
|
+
```ruby
|
|
90
|
+
args.inputs.keyboard.truthy_keys # Array of currently pressed keys
|
|
91
|
+
args.inputs.keyboard.has_focus # true if game has keyboard focus
|
|
92
|
+
args.inputs.keyboard.active # tick_count if any key pressed
|
|
93
|
+
args.inputs.text # String of last key pressed
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Controller Input
|
|
99
|
+
|
|
100
|
+
Access via `args.inputs.controller_one` (through `controller_four`):
|
|
101
|
+
|
|
102
|
+
### Connection
|
|
103
|
+
|
|
104
|
+
```ruby
|
|
105
|
+
args.inputs.controller_one.connected # true if controller present
|
|
106
|
+
args.inputs.controller_one.name # Controller name string
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Buttons
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
112
|
+
# Same state pattern as keyboard
|
|
113
|
+
args.inputs.controller_one.key_down.a # Just pressed
|
|
114
|
+
args.inputs.controller_one.key_held.a # Being held
|
|
115
|
+
args.inputs.controller_one.key_up.a # Just released
|
|
116
|
+
args.inputs.controller_one.a # Down or held
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
| Category | Buttons |
|
|
120
|
+
|----------|---------|
|
|
121
|
+
| Face | `a`, `b`, `x`, `y` |
|
|
122
|
+
| D-Pad | `dpad_up`, `dpad_down`, `dpad_left`, `dpad_right` |
|
|
123
|
+
| Shoulder | `l1`, `r1`, `l2`, `r2` |
|
|
124
|
+
| Sticks | `l3` (left click), `r3` (right click) |
|
|
125
|
+
| System | `start`, `select`, `home` |
|
|
126
|
+
|
|
127
|
+
### Analog Sticks
|
|
128
|
+
|
|
129
|
+
```ruby
|
|
130
|
+
# Raw values: -32767 to +32767
|
|
131
|
+
args.inputs.controller_one.left_analog_x_raw
|
|
132
|
+
args.inputs.controller_one.left_analog_y_raw
|
|
133
|
+
|
|
134
|
+
# Percentage: -1.0 to +1.0
|
|
135
|
+
args.inputs.controller_one.left_analog_x_perc
|
|
136
|
+
args.inputs.controller_one.left_analog_y_perc
|
|
137
|
+
|
|
138
|
+
# Angle in degrees (nil if centered)
|
|
139
|
+
args.inputs.controller_one.left_analog_angle
|
|
140
|
+
args.inputs.controller_one.right_analog_angle
|
|
141
|
+
|
|
142
|
+
# Active check with threshold
|
|
143
|
+
args.inputs.controller_one.left_analog_active?(threshold_perc: 0.2)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Directional Helpers (Controller-specific)
|
|
147
|
+
|
|
148
|
+
```ruby
|
|
149
|
+
# Combines D-pad + analog
|
|
150
|
+
args.inputs.controller_one.up # D-pad or analog up
|
|
151
|
+
args.inputs.controller_one.left_right # -1, 0, +1
|
|
152
|
+
args.inputs.controller_one.up_down # -1, 0, +1
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Dead Zone
|
|
156
|
+
|
|
157
|
+
```ruby
|
|
158
|
+
args.inputs.controller_one.analog_dead_zone = 3600 # Default raw value
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Mouse Input
|
|
164
|
+
|
|
165
|
+
Access via `args.inputs.mouse`:
|
|
166
|
+
|
|
167
|
+
### Position
|
|
168
|
+
|
|
169
|
+
```ruby
|
|
170
|
+
args.inputs.mouse.x # Current x
|
|
171
|
+
args.inputs.mouse.y # Current y
|
|
172
|
+
args.inputs.mouse.moved # true if moved this frame
|
|
173
|
+
args.inputs.mouse.relative_x # Delta from previous frame
|
|
174
|
+
args.inputs.mouse.relative_y # Delta from previous frame
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Button States
|
|
178
|
+
|
|
179
|
+
```ruby
|
|
180
|
+
# Simple boolean
|
|
181
|
+
args.inputs.mouse.button_left # true if left down
|
|
182
|
+
args.inputs.mouse.button_middle
|
|
183
|
+
args.inputs.mouse.button_right
|
|
184
|
+
|
|
185
|
+
# Key state pattern
|
|
186
|
+
args.inputs.mouse.key_down.left # Just pressed
|
|
187
|
+
args.inputs.mouse.key_held.left # Being held
|
|
188
|
+
args.inputs.mouse.key_up.left # Just released
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Click Events
|
|
192
|
+
|
|
193
|
+
```ruby
|
|
194
|
+
if (click = args.inputs.mouse.click)
|
|
195
|
+
click.x # Click x position
|
|
196
|
+
click.y # Click y position
|
|
197
|
+
click.created_at # Tick when clicked
|
|
198
|
+
end
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Click vs Drag Detection
|
|
202
|
+
|
|
203
|
+
```ruby
|
|
204
|
+
button = args.inputs.mouse.buttons.left
|
|
205
|
+
|
|
206
|
+
button.buffered_click # true if quick click (not drag)
|
|
207
|
+
button.buffered_held # true if held/dragging
|
|
208
|
+
button.click_at # When click started
|
|
209
|
+
button.up_at # When released
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Scroll Wheel
|
|
213
|
+
|
|
214
|
+
```ruby
|
|
215
|
+
if (wheel = args.inputs.mouse.wheel)
|
|
216
|
+
wheel.x # Horizontal scroll
|
|
217
|
+
wheel.y # Vertical scroll (positive = up)
|
|
218
|
+
end
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Collision Helpers
|
|
222
|
+
|
|
223
|
+
```ruby
|
|
224
|
+
args.inputs.mouse.inside_rect?({ x: 100, y: 100, w: 50, h: 50 })
|
|
225
|
+
args.inputs.mouse.inside_circle?({ x: 640, y: 360 }, radius: 100)
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Touch Input
|
|
231
|
+
|
|
232
|
+
For mobile/touch devices:
|
|
233
|
+
|
|
234
|
+
```ruby
|
|
235
|
+
# Simple finger access (nil if not touching)
|
|
236
|
+
args.inputs.finger_one # { x:, y: }
|
|
237
|
+
args.inputs.finger_two # { x:, y: }
|
|
238
|
+
|
|
239
|
+
# Side-based helpers
|
|
240
|
+
args.inputs.finger_left # Touch on left side
|
|
241
|
+
args.inputs.finger_right # Touch on right side
|
|
242
|
+
|
|
243
|
+
# Multi-touch hash
|
|
244
|
+
args.inputs.touch.each do |id, touch|
|
|
245
|
+
touch.x
|
|
246
|
+
touch.y
|
|
247
|
+
touch.touch_order # Order of touch (0-indexed)
|
|
248
|
+
touch.moved # Boolean
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Pinch zoom
|
|
252
|
+
args.inputs.pinch_zoom # Pinch zoom amount
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Grid Boundaries
|
|
258
|
+
|
|
259
|
+
Use `args.grid` for screen boundaries:
|
|
260
|
+
|
|
261
|
+
```ruby
|
|
262
|
+
args.grid.w # 1280 (width)
|
|
263
|
+
args.grid.h # 720 (height)
|
|
264
|
+
args.grid.left # 0
|
|
265
|
+
args.grid.right # 1280
|
|
266
|
+
args.grid.top # 720
|
|
267
|
+
args.grid.bottom # 0
|
|
268
|
+
args.grid.center_x # 640
|
|
269
|
+
args.grid.center_y # 360
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Clamping Pattern
|
|
273
|
+
|
|
274
|
+
```ruby
|
|
275
|
+
# Keep entity within screen
|
|
276
|
+
entity.x = entity.x.clamp(args.grid.left, args.grid.right - entity.w)
|
|
277
|
+
entity.y = entity.y.clamp(args.grid.bottom, args.grid.top - entity.h)
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Input Source Detection
|
|
283
|
+
|
|
284
|
+
```ruby
|
|
285
|
+
args.inputs.last_active # :keyboard, :mouse, or :controller
|
|
286
|
+
args.inputs.last_active_at # Tick count of last input
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Best Practices
|
|
292
|
+
|
|
293
|
+
### Support Multiple Input Types
|
|
294
|
+
|
|
295
|
+
```ruby
|
|
296
|
+
# Accept action from any source
|
|
297
|
+
if args.inputs.keyboard.key_down.space ||
|
|
298
|
+
args.inputs.keyboard.key_down.enter ||
|
|
299
|
+
args.inputs.controller_one.key_down.a
|
|
300
|
+
fire_action
|
|
301
|
+
end
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Use Unified Helpers for Movement
|
|
305
|
+
|
|
306
|
+
```ruby
|
|
307
|
+
# Instead of checking each key
|
|
308
|
+
speed = 5
|
|
309
|
+
player.x += args.inputs.left_right * speed
|
|
310
|
+
player.y += args.inputs.up_down * speed
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Normalize Diagonal Movement
|
|
314
|
+
|
|
315
|
+
```ruby
|
|
316
|
+
# Prevent faster diagonal movement
|
|
317
|
+
if (vector = args.inputs.directional_vector)
|
|
318
|
+
player.x += vector.x * speed
|
|
319
|
+
player.y += vector.y * speed
|
|
320
|
+
end
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Adapt UI to Input Type
|
|
324
|
+
|
|
325
|
+
```ruby
|
|
326
|
+
if args.inputs.last_active == :controller
|
|
327
|
+
show_prompt "Press [A]"
|
|
328
|
+
else
|
|
329
|
+
show_prompt "Press [Space]"
|
|
330
|
+
end
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## Common Antipatterns
|
|
336
|
+
|
|
337
|
+
### Checking D-Pad AND Analog Separately
|
|
338
|
+
|
|
339
|
+
```ruby
|
|
340
|
+
# WRONG - redundant checks
|
|
341
|
+
if args.inputs.controller_one.dpad_left ||
|
|
342
|
+
args.inputs.controller_one.left_analog_x_perc < -0.5
|
|
343
|
+
move_left
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
# CORRECT - use built-in helper
|
|
347
|
+
if args.inputs.controller_one.left
|
|
348
|
+
move_left
|
|
349
|
+
end
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Not Using Grid for Boundaries
|
|
353
|
+
|
|
354
|
+
```ruby
|
|
355
|
+
# WRONG - hardcoded values
|
|
356
|
+
if player.x > 1280
|
|
357
|
+
player.x = 1280
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# CORRECT - use grid constants
|
|
361
|
+
if player.x + player.w > args.grid.right
|
|
362
|
+
player.x = args.grid.right - player.w
|
|
363
|
+
end
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Forgetting Diagonal Speed
|
|
367
|
+
|
|
368
|
+
```ruby
|
|
369
|
+
# WRONG - diagonal is ~1.41x faster
|
|
370
|
+
player.x += args.inputs.left_right * speed
|
|
371
|
+
player.y += args.inputs.up_down * speed
|
|
372
|
+
|
|
373
|
+
# CORRECT - normalized diagonal
|
|
374
|
+
if (v = args.inputs.directional_vector)
|
|
375
|
+
player.x += v.x * speed
|
|
376
|
+
player.y += v.y * speed
|
|
377
|
+
end
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## Decision Tree
|
|
383
|
+
|
|
384
|
+
```
|
|
385
|
+
What type of movement?
|
|
386
|
+
├─ Simple 4-directional → examples/input/directional_input.rb
|
|
387
|
+
├─ With boundary clamping → examples/input/movement_with_bounds.rb
|
|
388
|
+
├─ Smooth analog → examples/input/analog_movement.rb
|
|
389
|
+
└─ Normalized diagonal → examples/input/normalized_movement.rb
|
|
390
|
+
|
|
391
|
+
What type of action trigger?
|
|
392
|
+
├─ One-shot (fire, jump) → use key_down, examples/input/action_triggers.rb
|
|
393
|
+
├─ Continuous (hold to run) → use key_held, examples/input/keyboard_input.rb
|
|
394
|
+
└─ On release (charge attacks) → use key_up, examples/input/keyboard_input.rb
|
|
395
|
+
|
|
396
|
+
Mouse interaction?
|
|
397
|
+
└─ Click handling → examples/input/mouse_click.rb
|
|
398
|
+
|
|
399
|
+
Controller input?
|
|
400
|
+
└─ Buttons and analog → examples/input/controller_input.rb
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
## Examples
|
|
404
|
+
|
|
405
|
+
| File | Demonstrates |
|
|
406
|
+
|------|--------------|
|
|
407
|
+
| `examples/input/directional_input.rb` | 4-directional movement with unified input |
|
|
408
|
+
| `examples/input/movement_with_bounds.rb` | Clamping player to screen boundaries |
|
|
409
|
+
| `examples/input/analog_movement.rb` | Smooth analog stick movement |
|
|
410
|
+
| `examples/input/normalized_movement.rb` | Normalized diagonal movement |
|
|
411
|
+
| `examples/input/action_triggers.rb` | One-shot actions with key_down |
|
|
412
|
+
| `examples/input/keyboard_input.rb` | Key states: down, held, up |
|
|
413
|
+
| `examples/input/mouse_click.rb` | Mouse click detection and position |
|
|
414
|
+
| `examples/input/controller_input.rb` | Controller buttons and analog sticks |
|