Class: RGame::Engine::Components::CharacterBody

Inherits:
RGame::Engine::Component show all
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

Attributes inherited from RGame::Engine::Component

#node

Instance Method Summary collapse

Methods inherited from RGame::Engine::Component

#context, #control, #draw, #on_detach, #sweep_freed

Methods included from Signal::DSL

#signal

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_xObject (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_yObject (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_boxObject

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_attachObject

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

#xObject

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

#yObject



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