Class: LZRTag::Game::Base

Inherits:
Hook::Base show all
Defined in:
lib/lzrtag/game/base_game.rb

Overview

The base game class. It implements a DSL that allows users to easily define their own games, and hooks in with the game event system

Examples:

class OwnGame < LZRTag::Game::Base
   def initialize(handler)
      super(handler);
      @tickTime = 1;
   end

   hook :dmgHook, LZRTag::Hook::Damager

   phase :running do |deltaTick|
      puts "I tick!"
   end

   on :playerRegistered do |newPlayer|
      puts "Hello new player!";
   end
end

handler.start_game(OwnGame)
# Alternatively, register the game and let it be activated via MQTT
handler.register_game("My Game", OwnGame);

Instance Attribute Summary collapse

DSL functions collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Hook::Base

describe_option, getCBs, getOptionDescriptions, on, #on, #on_hookin, #on_hookout, #process_raw_hit

Constructor Details

#initialize(handler) ⇒ Base

Initializes a generic game handler. This function is usually not called by the user, but instead by the LZRTag::Handler::Game when starting a game.

Parameters:



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/lzrtag/game/base_game.rb', line 81

def initialize(handler)
	super(handler)

	@hookList = Array.new();
	self.class.get_hooks().each do |hookID, hookData|
		@hookList << hookData[0].new(@handler, **hookData[1])
	end

	@tickTime = 0.1;

	@phaseMap = self.class.get_phase_map();
	@phasePrepMap = self.class.get_phase_prep_map();
	@phaseEndMap = self.class.get_phase_end_map();

	@phases = [@phaseMap.keys, @phasePrepMap.keys].flatten.uniq

	@phaseTime = 0;
	@phaseLastTime = 0;
end

Instance Attribute Details

#hookListObject (readonly)

Returns a list of all currently instantiated hooks



34
35
36
# File 'lib/lzrtag/game/base_game.rb', line 34

def hookList
  @hookList
end

#phasesObject (readonly)

Returns a list of the known phases of this game



40
41
42
# File 'lib/lzrtag/game/base_game.rb', line 40

def phases
  @phases
end

#tickTimeObject (readonly)

Returns the current per-tick target time. Can, and should, be set during constructor to control the granularity of the game



37
38
39
# File 'lib/lzrtag/game/base_game.rb', line 37

def tickTime
  @tickTime
end

Class Method Details

.get_hooksObject

See Also:

  • get_phase_map()


63
64
65
66
# File 'lib/lzrtag/game/base_game.rb', line 63

def self.get_hooks()
	@globalHookList ||= Hash.new();
	return @globalHookList;
end

.get_phase_end_mapObject

See Also:

  • get_phase_map()


57
58
59
60
# File 'lib/lzrtag/game/base_game.rb', line 57

def self.get_phase_end_map()
	@globalPhaseEndMap ||= Hash.new();
	return @globalPhaseEndMap;
end

.get_phase_mapObject

This function is meant for the DSL, to allow adding to the class itself



45
46
47
48
# File 'lib/lzrtag/game/base_game.rb', line 45

def self.get_phase_map()
	@globalPhaseMap ||= Hash.new();
	return @globalPhaseMap;
end

.get_phase_prep_mapObject

See Also:

  • get_phase_map()


51
52
53
54
# File 'lib/lzrtag/game/base_game.rb', line 51

def self.get_phase_prep_map()
	@globalPhasePrepMap ||= Hash.new();
	return @globalPhasePrepMap;
end

.hook(hookID, hookType, hookOptions = {}) ⇒ Object

DSL function to add a Hook type to this game. Any hook type added by this function will be instantiated when the game itself is instantiated, and will be linked in with the internal game signals.

Parameters:

  • hookID (Symbol)

    The ID of the hook, used for later referencing

  • hookType (Hook::Base)

    The class of the hook to instantiate

  • hookOptions (Hash) (defaults to: {})

    A hash of options to pass to the constructor of the hook

Raises:

  • (ArgumentError)


110
111
112
113
114
115
116
117
# File 'lib/lzrtag/game/base_game.rb', line 110

def self.hook(hookID, hookType, hookOptions = {})
	raise ArgumentError, "Hook ID needs to be a symbol!" unless hookID.is_a? Symbol
	unless hookType.is_a? Class and hookType < LZRTag::Hook::Base
		raise ArgumentError, "Hook needs to be a LZR::Hook!"
	end
	raise ArgumentError, "Hook options need to be a hash" unless hookOptions.is_a? Hash
	get_hooks()[hookID] << [hookType, hookOptions];
end

.phase(phaseName) {|deltaTime| ... } ⇒ Object

DSL function to provide a phase tick code to this game The block provided to this function will be executed every game tick, with the delta-time since last tick as parameter.

Parameters:

  • phaseName (Symbol)

    The name of the phase during which to execute this code

Yields:

  • (deltaTime)

    Calls this block every game-tick during the specified phase

Raises:

  • (ArgumentError)


124
125
126
127
128
129
130
131
132
133
134
# File 'lib/lzrtag/game/base_game.rb', line 124

def self.phase(phaseName, &block)
	raise ArgumentError, "Block needs to be given!" unless block_given?

	phaseName = [phaseName].flatten
	phaseName.each do |evt|
		unless (evt.is_a? Symbol)
			raise ArgumentError, "Phase needs to be a symbol or array of symbols!"
		end
		self.get_phase_map()[evt] = block;
	end
end

.phase_end(phaseName) {|newPhase| ... } ⇒ Object

DSL function to provide a callback immediately before switching to a new phase. The provided block is guaranteed to execute before any phase and phase_prep blocks, giving the user an option to reset and clean up after themselves.

Parameters:

  • phaseName (Symbol)

    Name of the phase after which to call this block

Yields:

  • (newPhase)

    Calls the block right before the switch, with the upcoming phase as parameter

Raises:

  • (ArgumentError)


159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/lzrtag/game/base_game.rb', line 159

def self.phase_end(phaseName, &block)
	raise ArgumentError, "Block needs to be given!" unless block_given?

	phaseName = [phaseName].flatten
	phaseName.each do |evt|
		unless (evt.is_a? Symbol)
			raise ArgumentError, "Phase needs to be a symbol or array of symbols!"
		end
		self.get_phase_end_map()[evt] ||= Array.new()
		self.get_phase_end_map()[evt] << block;
	end
end

.phase_prep(phaseName) {|oldPhase| ... } ⇒ Object

DSL function to provide a callback immediately after switching to a new phase. The provided block will be called only once, right after a phase switch happened. As such, it can be used to prepare game timer settings, player classes, etc.

Parameters:

  • phaseName (Symbol)

    The name of the phase before which to execute

Yields:

  • (oldPhase)

    Calls the block right after a switch, with the old phase as parameter

Raises:

  • (ArgumentError)


141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/lzrtag/game/base_game.rb', line 141

def self.phase_prep(phaseName, &block)
	raise ArgumentError, "Block needs to be given!" unless block_given?

	phaseName = [phaseName].flatten
	phaseName.each do |evt|
		unless (evt.is_a? Symbol)
			raise ArgumentError, "Phase needs to be a symbol or array of symbols!"
		end
		self.get_phase_prep_map()[evt] ||= Array.new()
		self.get_phase_prep_map()[evt] << block;
	end
end

Instance Method Details

#consume_event(evt, data) ⇒ Object



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/lzrtag/game/base_game.rb', line 175

def consume_event(evt, data)
	super(evt, data);

	case evt
	when :gameTick
		handle_game_tick(*data);
	when :gamePhaseStarts
		handle_phase_change();
	when :gamePhaseEnds
		if @phaseEndMap[data[0]]
			@phaseEndMap[data[0]].each do |cb|
				instance_exec(&cb);
			end
		end
	end

	@hookList.each do |hook|
		hook.consume_event(evt, data);
	end
end

#get_phase_mapObject

This function returns a list of possible phases and their tick callbacks



70
71
72
# File 'lib/lzrtag/game/base_game.rb', line 70

def get_phase_map()
	return @phaseMap
end

#handle_game_tick(dT) ⇒ Object



207
208
209
210
211
212
213
214
215
216
217
# File 'lib/lzrtag/game/base_game.rb', line 207

def handle_game_tick(dT)
	phase = @handler.gamePhase
	return unless @phaseMap[phase];
	return if phase == :idle;

	@phaseLastTime = @phaseTime;
	@phaseTime += dT;
	@handler.mqtt.publish_to "Lasertag/Game/Timer", @phaseTime

	instance_exec(dT, &@phaseMap[phase]);
end

#handle_phase_changeObject



197
198
199
200
201
202
203
204
# File 'lib/lzrtag/game/base_game.rb', line 197

def handle_phase_change
	@phaseTime = 0;

	return unless @phasePrepMap[@handler.gamePhase]
	@phasePrepMap[@handler.gamePhase].each do |cb|
		instance_exec(&cb);
	end
end