Class: Zif::Game

Inherits:
Object
  • Object
show all
Includes:
Traceable
Defined in:
app/lib/zif/game.rb

Overview

The main entrypoint for your game.

Orchestrates main tick & active Scene.

It's suggested to subclass this so that you can set the opening scene during #initialize, see example below.

Includes attr_gtk – supports what DRGTK provides for these classes in addition to what is documented here. docs.dragonruby.org/#—-attr_gtk.rb

Expects the #scene to be an object which responds to #perform_tick (See Scene#perform_tick) If @scene.perform_tick returns an instance of Scene, the game will switch to that scene

If you need some more advanced usage, you can override #perform_tick to pass a block to #standard_tick and do something with the @scene.perform_tick return value (See second example).

Examples:

Suggested initialization procedure:


# =-=-=- In your app/my_game.rb -=-=-=
class MyGame < Zif::Game
  def initialize
    super()
    MyOneTime.setups # do anything here, like register services...
    register_scene(:rainbow_road, RainbowRoadScene) # (RainbowRoadScene is a Zif::Scene subclass)
    @scene = OpeningScene.new # (this is a Zif::Scene subclass)
  end
end

# =-=-=- In your app/main.rb -=-=-=
# Require all of the Zif library:
require 'app/lib/zif/require.rb'
require 'my_game.rb'

def tick(args)
  if args.tick_count == 2
    $game = MyGame.new
    $game.scene.prepare_scene # if needed on first scene
  end

  $game&.perform_tick
end

Custom scene switching behavior (advanced):


# =-=-=- In your MyGame class in app/my_game.rb -=-=-=
# You would only need to override #perform_tick if you are doing something advanced.  Generally you can just
# use the normal scene switching mechanisms described in the example above.
#
# Important that this isn't named #tick, otherwise it gets suppressed by "trace!"
def perform_tick
  # tick_result here is just the return value of the active scene's #perform_tick method
  standard_tick do |tick_result|
    case tick_result
    when :load_water_level
      water_level = WaterLevelScene.new
      water_level.do_special_stuff # like something you can't do in #prepare_scene for whatever reason
      @scene = water_level
    else # an unhandled return
      @scene = OpeningScene.new
    end
  end
end

Direct Known Subclasses

ExampleApp::ZifExample

Instance Attribute Summary collapse

Attributes included from Traceable

#tracer_service_name

1. Public Interface collapse

2. Private-ish methods collapse

Methods included from Traceable

#mark, #mark_and_print, #mark_prefix, #tracer

Constructor Details

#initializeGame

It's suggested that you extend this and set #scene manually, see the example above.


80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'app/lib/zif/game.rb', line 80

def initialize
  $services = Zif::Services::ServiceGroup.new
  @services = $services
  @services.register(:action_service, Zif::Services::ActionService.new)
  @tracer_service_name = :tracer
  @services.register(@tracer_service_name, Zif::Services::TickTraceService.new)
  @services.register(:sprite_registry, Zif::Services::SpriteRegistry.new)
  @services.register(:input_service, Zif::Services::InputService.new)
  @scene_registry = {}
  @pause_actions = false

  Zif.check_compatibility
end

Instance Attribute Details

#sceneZif::Scene

Returns The active scene.

Returns:


68
69
70
# File 'app/lib/zif/game.rb', line 68

def scene
  @scene
end

#scene_registryHash<Symbol, Class<Zif::Scene>> (readonly)

Returns A mapping of scene names to classes. Use #register_scene to add one.

Returns:


74
75
76
# File 'app/lib/zif/game.rb', line 74

def scene_registry
  @scene_registry
end

#servicesZif::Services::ServiceGroup

Returns A handle for all services.

Returns:


71
72
73
# File 'app/lib/zif/game.rb', line 71

def services
  @services
end

Instance Method Details

#decorate_exception(e) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


175
176
177
178
179
180
181
182
183
184
185
186
# File 'app/lib/zif/game.rb', line 175

def decorate_exception(e)
  puts '=' * 120
  puts "Exception: #{e.class}"
  puts e.message.wrap(118).gsub("\n", "\n  ")
  tick_trace_step = @services[:tracer]&.last_label
  if tick_trace_step
    puts "Exception occurred after: #{tick_trace_step}"
  else
    puts 'Exception occured before tracer service was initialized'
  end
  puts "=#{'-' * 118}="
end

#inspectObject

See Also:


119
120
121
# File 'app/lib/zif/game.rb', line 119

def inspect
  serialize.to_s
end

#perform_tickObject

Override, or extend with super() if you need to pass a block to #standard_tick or do anything else


106
107
108
# File 'app/lib/zif/game.rb', line 106

def perform_tick
  standard_tick # No block provided usually
end

#register_scene(scene_name, scene) ⇒ Object

Register a Scene subclass by a Symbol name, for scene transitions.

Parameters:

  • scene_name (Symbol)

    The name of the scene to register. If your scene returns this symbol from Scene#perform_tick, this class will switch to this scene during #standard_tick

  • scene (Class<Zif::Scene>)

    The class name of a Scene subclass. When invoked via the scene_name, a new instance of this class is created and switched to be the active scene.


101
102
103
# File 'app/lib/zif/game.rb', line 101

def register_scene(scene_name, scene)
  @scene_registry[scene_name] = scene
end

#serializeObject

See Also:


111
112
113
114
115
116
# File 'app/lib/zif/game.rb', line 111

def serialize
  {
    scene:  @scene.class.to_s,
    tracer: @services[:tracer]&.last_label
  }
end

#standard_tick(&_block) ⇒ Object

Generally this shouldn't be called directly, unless you are extending #perform_tick. See example above.

Parameters:

  • _block (Proc)

    A block to run which is given the return value of the active #scene's #perform_tick method


133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'app/lib/zif/game.rb', line 133

def standard_tick(&_block)
  @services[:tracer].reset_tick
  mark('#standard_tick: begin')

  @services[:input_service].process_click
  mark('#standard_tick: input_service #process_click')

  tick_result = @scene.perform_tick
  mark('#standard_tick: Scene #perform_tick complete')

  next_scene = switch_scene(tick_result)
  if next_scene
    next_scene.prepare_scene
    @scene = next_scene
  else
    yield tick_result if block_given?
  end

  mark('#standard_tick: Scene switching handled')

  mark('#standard_tick: Action service complete') if @services[:action_service].run_all_actions
  mark('#standard_tick: Complete')
  @services[:tracer].finish
rescue StandardError => e
  decorate_exception(e)
  @services[:tracer]&.finish
  $gtk.console
  $gtk.pause!
end

#switch_scene(tick_result) ⇒ Zif::Scene

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns An instance of a Scene to transition to.

Returns:


165
166
167
168
169
170
171
172
# File 'app/lib/zif/game.rb', line 165

def switch_scene(tick_result)
  return tick_result if tick_result.is_a?(Zif::Scene)
  return tick_result.new if tick_result.is_a?(Class)

  return unless @scene_registry[tick_result] && @scene_registry[tick_result] <= Zif::Scene

  @scene_registry[tick_result].new
end

#to_sObject

See Also:


124
125
126
# File 'app/lib/zif/game.rb', line 124

def to_s
  serialize.to_s
end