Class: Doom::Game::Ticcmd

Inherits:
Struct
  • Object
show all
Defined in:
lib/doom/game/ticcmd.rb

Overview

One tic's worth of player intent, as in DOOM's ticcmd_t.

This is the only thing that travels between peers in lockstep multiplayer: never positions, never health. Each peer feeds identical ticcmds to an identical simulation and arrives at an identical world, so the wire format stays tiny and cheating by position injection is impossible by construction.

forwardmove  -1.0..1.0  (negative = backward)
sidemove     -1.0..1.0  (positive = strafe right)
angleturn    degrees to turn this tic (positive = left, as DOOM)
buttons      bitmask, see constants below

Subclassed rather than built with a Struct.new block: constants assigned inside a block land in the enclosing lexical scope (Doom::Game), not on the struct class, so Ticcmd::BTN_FIRE would not resolve.

Constant Summary collapse

BTN_FIRE =
1
BTN_USE =
2
PACKED_SIZE =
7

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#angleturnObject

Returns the value of attribute angleturn

Returns:

  • the current value of angleturn



20
21
22
# File 'lib/doom/game/ticcmd.rb', line 20

def angleturn
  @angleturn
end

#buttonsObject

Returns the value of attribute buttons

Returns:

  • the current value of buttons



20
21
22
# File 'lib/doom/game/ticcmd.rb', line 20

def buttons
  @buttons
end

#forwardmoveObject

Returns the value of attribute forwardmove

Returns:

  • the current value of forwardmove



20
21
22
# File 'lib/doom/game/ticcmd.rb', line 20

def forwardmove
  @forwardmove
end

#sidemoveObject

Returns the value of attribute sidemove

Returns:

  • the current value of sidemove



20
21
22
# File 'lib/doom/game/ticcmd.rb', line 20

def sidemove
  @sidemove
end

Class Method Details

.noneObject



25
26
27
# File 'lib/doom/game/ticcmd.rb', line 25

def self.none
  new(0.0, 0.0, 0.0, 0)
end

.unpack(bytes) ⇒ Object



55
56
57
58
# File 'lib/doom/game/ticcmd.rb', line 55

def self.unpack(bytes)
  f, s, a, b = bytes.unpack('s>s>s>C')
  new(f / 1000.0, s / 1000.0, a / 100.0, b)
end

Instance Method Details

#fire?Boolean

Returns:



29
30
31
# File 'lib/doom/game/ticcmd.rb', line 29

def fire?
  (buttons & BTN_FIRE) != 0
end

#moving?Boolean

Returns:



37
38
39
# File 'lib/doom/game/ticcmd.rb', line 37

def moving?
  forwardmove != 0.0 || sidemove != 0.0
end

#packObject

Fixed 7 bytes on the wire ('s>s>s>C', == PACKED_SIZE): three signed shorts plus a byte of buttons, no padding. Movement is quantised to 1/1000 and the turn to 1/100 of a degree -- both far finer than any input device resolves, and identical on every peer, which matters more than the precision itself.



46
47
48
49
50
51
52
53
# File 'lib/doom/game/ticcmd.rb', line 46

def pack
  [
    (forwardmove * 1000).round.clamp(-32_768, 32_767),
    (sidemove * 1000).round.clamp(-32_768, 32_767),
    (angleturn * 100).round.clamp(-32_768, 32_767),
    buttons & 0xff
  ].pack('s>s>s>C')
end

#use?Boolean

Returns:



33
34
35
# File 'lib/doom/game/ticcmd.rb', line 33

def use?
  (buttons & BTN_USE) != 0
end