Class: RGame::Engine::ActionMapper

Inherits:
Object
  • Object
show all
Defined in:
lib/rgame/engine/input/action_mapper.rb

Overview

Polls one player's device through an InputMap and produces their Actions snapshot.

mapper = ActionMapper.new(input_map, device: Controls.gamepad(0))
actions = mapper.poll(input)

One of these per player. The device is what makes that work: every query carries it, so two mappers over the same map read two different controllers, and each keeps its own previous-frame state so their edge queries are independent.

Pure logic. The backend is duck-typed and the whole interface is down?(physical_id, device:) and axis(axis_id, device:) — a spec passes a fake and a game passes RGame::Core::Input.

Constant Summary collapse

DEAD_ZONE =

A resting analog stick genuinely reports small non-zero values, so something has to ignore them. Here rather than in the game, because it is a property of the device, and here rather than in Core, because how much to ignore is a judgement rather than a fact about the hardware.

0.15

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(map, device: RGame::Util::Controls::KEYBOARD, dead_zone: DEAD_ZONE) ⇒ ActionMapper

Returns a new instance of ActionMapper.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/rgame/engine/input/action_mapper.rb', line 29

def initialize(map, device: RGame::Util::Controls::KEYBOARD, dead_zone: DEAD_ZONE)
  @map = map
  @device = device
  @dead_zone = dead_zone

  # One reusable snapshot: there is exactly one input state per tick per
  # player, so these are mutated in place each poll instead of allocated.
  # Seeded from the map's action list, so the hashes are warm before the
  # first poll and steady-state polling allocates nothing at all.
  @held = {}
  @prev_held = {}
  @axes = {}
  map.bindings.each_key do |name|
    @held[name] = false
    @prev_held[name] = false
    @axes[name] = 0.0
  end
  @actions = Actions.new(held: @held, axes: @axes, prev_held: @prev_held)
end

Instance Attribute Details

#actionsObject (readonly)

Returns the value of attribute actions.



26
27
28
# File 'lib/rgame/engine/input/action_mapper.rb', line 26

def actions
  @actions
end

#dead_zoneObject

Returns the value of attribute dead_zone.



27
28
29
# File 'lib/rgame/engine/input/action_mapper.rb', line 27

def dead_zone
  @dead_zone
end

#deviceObject

Returns the value of attribute device.



27
28
29
# File 'lib/rgame/engine/input/action_mapper.rb', line 27

def device
  @device
end

#mapObject (readonly)

Returns the value of attribute map.



26
27
28
# File 'lib/rgame/engine/input/action_mapper.rb', line 26

def map
  @map
end

Instance Method Details

#poll(backend) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/rgame/engine/input/action_mapper.rb', line 49

def poll(backend)
  # Snapshot this frame's held state as "previous" before recomputing it
  # (in-place copy: no allocation, the keys already exist).
  @held.each { |name, down| @prev_held[name] = down }

  return rest if @device.nil?

  @map.bindings.each do |name, binding|
    @held[name] = any_down?(backend, binding.buttons) if binding.buttons
    @axes[name] = axis_value(backend, binding) if binding.pairs || binding.stick
  end

  @actions
end