Class: RGame::Engine::Components::CharacterBody
- Inherits:
-
RGame::Engine::Component
- Object
- RGame::Engine::Component
- RGame::Engine::Components::CharacterBody
- Defined in:
- lib/rgame/engine/components/character_body.rb
Overview
Walking movement for a tile-bound actor (player or NPC). A controller writes a per-step movement intent — each axis in -1..1 — and this component turns it into a real move each update, resolved against the scene's TileWorld so the actor slides along walls and stays inside the map. Distinct from Velocity (which integrates blindly): here every step is collision-checked.
The intent doubles as the facing for AnimatedSprite (move_x / move_y readers), so a character is just CharacterBody + a controller + AnimatedSprite.
The feet box is built from the node's dimensions (which AnimatedSprite sets from the
sprite frame), not a passed-in sprite size — feet_width/feet_height are the box,
centred horizontally and anchored to the node's bottom. It's built lazily on first
use (the first update, after every on_attach has run), so the order components are
added in doesn't matter. A body with no sprite must set the node's width/height.
Instance Attribute Summary collapse
-
#move_x ⇒ Object
readonly
Returns the value of attribute move_x.
-
#move_y ⇒ Object
readonly
Returns the value of attribute move_y.
Attributes inherited from RGame::Engine::Component
Instance Method Summary collapse
-
#collision_box ⇒ Object
The feet box, derived from the node's sprite size and memoised.
-
#initialize(feet_width:, feet_height:, speed:) ⇒ CharacterBody
constructor
A new instance of CharacterBody.
-
#on_attach ⇒ Object
The TileWorld is a scene-scoped system, reachable once we're in the tree.
-
#set_intent(intent_x, intent_y) ⇒ Object
Set this step's movement intent; each axis is in -1..1.
- #update(dt) ⇒ Object
-
#x ⇒ Object
CollisionSystem#move drives an "actor" through x/y/collision_box and writes the resolved position back — back those by the owning node's transform.
- #x=(value) ⇒ Object
- #y ⇒ Object
- #y=(value) ⇒ Object
Methods inherited from RGame::Engine::Component
#context, #control, #draw, #on_detach, #sweep_freed
Methods included from Signal::DSL
Constructor Details
#initialize(feet_width:, feet_height:, speed:) ⇒ CharacterBody
Returns a new instance of CharacterBody.
23 24 25 26 27 28 29 30 31 |
# File 'lib/rgame/engine/components/character_body.rb', line 23 def initialize(feet_width:, feet_height:, speed:) super() @feet_width = feet_width @feet_height = feet_height @speed = speed @move_x = 0.0 @move_y = 0.0 @collision_box = nil end |
Instance Attribute Details
#move_x ⇒ Object (readonly)
Returns the value of attribute move_x.
21 22 23 |
# File 'lib/rgame/engine/components/character_body.rb', line 21 def move_x @move_x end |
#move_y ⇒ Object (readonly)
Returns the value of attribute move_y.
21 22 23 |
# File 'lib/rgame/engine/components/character_body.rb', line 21 def move_y @move_y end |
Instance Method Details
#collision_box ⇒ Object
The feet box, derived from the node's sprite size and memoised.
Only valid once the node is in the tree, and it says so rather than letting you find out later. The size comes from AnimatedSprite#on_attach, so a read from a constructor sees a 0x0 node and bakes a box anchored to nothing — permanently, because this memoises, and for the collision system too, because it reads the same box. The symptom is an actor that walks through walls it should not, a long way from the call that caused it. Guarding costs one comparison, once.
42 43 44 |
# File 'lib/rgame/engine/components/character_body.rb', line 42 def collision_box @collision_box ||= build_collision_box end |
#on_attach ⇒ Object
The TileWorld is a scene-scoped system, reachable once we're in the tree.
47 |
# File 'lib/rgame/engine/components/character_body.rb', line 47 def on_attach = @world = node.system(TileWorld) |
#set_intent(intent_x, intent_y) ⇒ Object
Set this step's movement intent; each axis is in -1..1.
50 51 52 53 |
# File 'lib/rgame/engine/components/character_body.rb', line 50 def set_intent(intent_x, intent_y) @move_x = intent_x @move_y = intent_y end |
#update(dt) ⇒ Object
55 56 57 58 59 |
# File 'lib/rgame/engine/components/character_body.rb', line 55 def update(dt) return if @move_x.zero? && @move_y.zero? @world.move(self, @move_x * @speed * dt, @move_y * @speed * dt) end |
#x ⇒ Object
CollisionSystem#move drives an "actor" through x/y/collision_box and writes the resolved position back — back those by the owning node's transform.
63 |
# File 'lib/rgame/engine/components/character_body.rb', line 63 def x = node.x |
#x=(value) ⇒ Object
66 67 68 |
# File 'lib/rgame/engine/components/character_body.rb', line 66 def x=(value) node.x = value end |
#y ⇒ Object
64 |
# File 'lib/rgame/engine/components/character_body.rb', line 64 def y = node.y |
#y=(value) ⇒ Object
70 71 72 |
# File 'lib/rgame/engine/components/character_body.rb', line 70 def y=(value) node.y = value end |