Class: Ray::Scene

Inherits:
Object
  • Object
show all
Includes:
Helper
Defined in:
lib/ray/scene.rb

Overview

Scenes contain the main logic of a game.

You can define a new scene using a block, which will be called every time your scene is about to be used. However, you may also want to subclass Ray::Scene. When doing this, you’ll probably want to override the register method:

def register
  on :some_event do some_stuff end
end

Another method is called before register: setup. Putting code in register or in setup doesn’t matter, but setting the scene up inside register method seems (and, indeed, is) inappropriate. You can override it:

def setup
  @sprite = sprite("image.png")
end

You can indicate how your scene should be rendered there:

render do |win|
  # Do drawing here
end

Or you can override render:

def render(win)
  # Do draw ing here
end

Once your scene is loaded, you’ll probably want to clean it up (set some instance variables to nil so they can be garbaged collected for instance). You can do that by passing a block to clean_up:

clean_up do
  @some_big_resource = nil
end

Or by overriding it:

def clean_up
  @some_big_resource = nil
end

Managing the stack of scenes

exit is called when you want to stop running the scene, but not to remove the last scene from the stack. It is useful if you want to push a new scene. Hence Ray::Scene#push_scene will call exit.

exit! (or pop_scene), on the other hand, is used to go back to the previous scene in the hierarchy

Sending informations to a scene

Scenes may need some arguments to work. You can pass those in push_scene:

push_scene(:polygon, 6, Ray::Color.red)

Then you can use them with scene_arguments:

scene :polygon do
  sides, color = scene_arguments
  # ...
end

They are also passed to #setup:

def setup(sides, color)
  # ...
end

Limiting the loop rate

You can prevent a scene from always running by using #loops_per_second=:

self.loops_per_second = 30 # will sleep some time after each loop

This defaults to 60.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Helper

#create_event_runner, #disable_event_group, #enable_event_group, #event_runner, #event_runner=, font, holding?, image, image_target, mouse_pos, music, #remove_event_group, #rotation, #scale_variation, sound, sound_buffer, sprite, text, #translation

Methods included from Matchers

key, key_mod, where

Methods included from DSL::EventListener

#add_hook, #current_event_group, #current_event_group=, #event_group, #listener_runner, #listener_runner=, #on

Methods included from DSL::EventRaiser

#raise_event, #raiser_runner, #raiser_runner=

Constructor Details

#initialize(&block) ⇒ Scene

Creates a new scene. block will be instance evaluated when this scene becomes the current one.



101
102
103
104
105
106
107
108
109
110
# File 'lib/ray/scene.rb', line 101

def initialize(&block)
  @scene_register_block   = block
  @scene_always_block     = nil
  @scene_render_block     = nil
  @scene_clean_block      = nil

  @scene_loops_per_second = 60

  @scene_animations       = Ray::AnimationList.new
end

Instance Attribute Details

#scene_argumentsObject

The arguments passed to the scene with push_scene



274
275
276
# File 'lib/ray/scene.rb', line 274

def scene_arguments
  @scene_arguments
end

Class Method Details

.bind(game) ⇒ Object

Registers a scene to a game object, used for subclasses.



74
75
76
# File 'lib/ray/scene.rb', line 74

def bind(game)
  game.scene(@scene_name || snake_cased_name, self)
end

.scene_nameSymbol .scene_name(value) ⇒ Object

Overloads:

  • .scene_nameSymbol

    Returns the name of the scene.

    Returns:

    • (Symbol)

      the name of the scene

  • .scene_name(value) ⇒ Object

    Sets the name of the scene. Defaulted to the snake cased name of the scene.



83
84
85
# File 'lib/ray/scene.rb', line 83

def scene_name(val)
  @scene_name = val
end

Instance Method Details

#always(&block) ⇒ Object

Registers a block to be excuted as often as possible.



206
207
208
# File 'lib/ray/scene.rb', line 206

def always(&block)
  @scene_always_block = block
end

#animationsRay::AnimationList

Returns An animation list automatically updated by the scene.

Returns:



278
279
280
# File 'lib/ray/scene.rb', line 278

def animations
  @scene_animations
end

#clean_up(&block) ⇒ Object

Cleans the scene or registers a block to clean it.



232
233
234
235
236
237
238
# File 'lib/ray/scene.rb', line 232

def clean_up(&block)
  if block_given?
    @scene_clean_block = block
  else
    @scene_clean_block.call if @scene_clean_block
  end
end

#exitObject

Exits the scene, but does not pop the scene.

You may want to call this if you pushed a new scene, to switch to the new scene.



194
195
196
# File 'lib/ray/scene.rb', line 194

def exit
  @scene_exit = true
end

#exit!Object Also known as: pop_scene

Exits the scene and pops it (may not work as expected if the current scene is not the last one)



200
201
202
203
# File 'lib/ray/scene.rb', line 200

def exit!
  exit
  game.pop_scene
end

#gameObject



246
247
248
# File 'lib/ray/scene.rb', line 246

def game
  @scene_game
end

#game=(val) ⇒ Object



250
251
252
# File 'lib/ray/scene.rb', line 250

def game=(val)
  @scene_game = val
end

#inspectObject



240
241
242
# File 'lib/ray/scene.rb', line 240

def inspect
  "#<#{self.class} game=#{self.game.inspect}>"
end

#loops_per_secondObject Also known as: frames_per_second



262
263
264
# File 'lib/ray/scene.rb', line 262

def loops_per_second
  @scene_loops_per_second
end

#loops_per_second=(val) ⇒ Object Also known as: frames_per_second=



266
267
268
# File 'lib/ray/scene.rb', line 266

def loops_per_second=(val)
  @scene_loops_per_second = val
end

#push_scene(scene, *args) ⇒ Object

Pushes a scene in the stack, and exits that one



226
227
228
229
# File 'lib/ray/scene.rb', line 226

def push_scene(scene, *args)
  game.push_scene(scene, *args)
  exit
end

#registerObject

Override this method in subclasses to register your own events



128
129
# File 'lib/ray/scene.rb', line 128

def register
end

#register_eventsObject



112
113
114
115
116
117
118
119
120
# File 'lib/ray/scene.rb', line 112

def register_events
  if @scene_register_block
    instance_exec(@scene_arguments,  &@scene_register_block)
  else
    register
  end

  @scene_exit = false
end

#render(win = nil) {|window| ... } ⇒ Object

Registers the block to draw the scene.

If no block is given, renders the scen on the image passed as an argument.

Yields:

  • (window)

    Block to render this scene.

Yield Parameters:

  • window (Ray::Image)

    The window you should draw on



217
218
219
220
221
222
223
# File 'lib/ray/scene.rb', line 217

def render(win = nil, &block)
  if block_given?
    @scene_render_block = block
  else
    @scene_render_block.call(win) if @scene_render_block
  end
end

#runObject

Runs until you exit the scene. This will also raise events if the mouse moves, … allowing you to directly listen to a such event.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/ray/scene.rb', line 134

def run
  until @scene_exit
    loop_start = Time.now

    run_tick

    if @scene_loops_per_second
      ellapsed_time = Time.now - loop_start
      time_per_loop = 1.0 / @scene_loops_per_second

      sleep(time_per_loop - ellapsed_time) if ellapsed_time < time_per_loop
    end
  end

  clean_up
end

#run_scene(name, *args) ⇒ Object

Runs another scene over the current one. This method will return when the scene is done running.



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/ray/scene.rb', line 170

def run_scene(name, *args)
  scene_list = SceneList.new(game)
  scene_list.push(name, *args)

  event_runner = DSL::EventRunner.new

  old_event_runner = game.event_runner
  old_scene_list   = game.scenes

  game.event_runner = event_runner
  game.scenes = scene_list

  begin
    game.run
  ensure
    game.event_runner = old_event_runner
    game.scenes       = old_scene_list
  end
end

#run_tick(check_events = true) ⇒ Object

Runs one tick of the scene, checking for events, running the event loop, and drawing on the window.

Parameters:

  • check_events (true, false) (defaults to: true)

    True to check for events



155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/ray/scene.rb', line 155

def run_tick(check_events = true)
  collect_events if check_events

  @scene_always_block.call if @scene_always_block
  listener_runner.run

  @scene_animations.update

  @scene_window.clear Ray::Color.none
  render @scene_window
  @scene_window.update
end

#setup(*args) ⇒ Object

Override this method in subclasses to setup the initial state of your scene.



124
125
# File 'lib/ray/scene.rb', line 124

def setup(*args)
end

#windowObject



254
255
256
# File 'lib/ray/scene.rb', line 254

def window
  @scene_window
end

#window=(val) ⇒ Object



258
259
260
# File 'lib/ray/scene.rb', line 258

def window=(val)
  @scene_window = val
end