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, effect_generator, #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
# 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
  @scene_arguments        = []
end

Instance Attribute Details

#scene_argumentsObject

The arguments passed to the scene with push_scene


292
293
294
# File 'lib/ray/scene.rb', line 292

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.


217
218
219
# File 'lib/ray/scene.rb', line 217

def always(&block)
  @scene_always_block = block
end

#animationsRay::AnimationList

Returns An animation list automatically updated by the scene.

Returns:


296
297
298
# File 'lib/ray/scene.rb', line 296

def animations
  @scene_animations
end

#clean_up(&block) ⇒ Object

Cleans the scene or registers a block to clean it.


243
244
245
246
247
248
249
# File 'lib/ray/scene.rb', line 243

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.


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

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)


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

def exit!
  exit
  game.pop_scene
end

#gameObject


264
265
266
# File 'lib/ray/scene.rb', line 264

def game
  @scene_game
end

#game=(val) ⇒ Object


268
269
270
# File 'lib/ray/scene.rb', line 268

def game=(val)
  @scene_game = val
end

#loops_per_secondObject Also known as: frames_per_second


280
281
282
# File 'lib/ray/scene.rb', line 280

def loops_per_second
  @scene_loops_per_second
end

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


284
285
286
# File 'lib/ray/scene.rb', line 284

def loops_per_second=(val)
  @scene_loops_per_second = val
end

#nameObject

See Also:


260
261
262
# File 'lib/ray/scene.rb', line 260

def name
  @scene_name
end

#name=(val) ⇒ Object

Sets the name of the scene

Parameters:

  • val (String)

    New name of the scene


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

def name=(val)
  @scene_name = val
end

#pop_scene_until {|scene| ... } ⇒ Object

Pops scenes until a condition is met

Yields:

  • (scene)

    To determine if a scene must be popped.

Yield Parameters:

  • scene (Ray::Scene)

    The scene that will be popped

Yield Returns:

  • (Boolean)

    False to pop the next scene


212
213
214
# File 'lib/ray/scene.rb', line 212

def pop_scene_until(&block)
  game.pop_scene_until(&block)
end

#pop_scene_while {|scene| ... } ⇒ Object

Pops scenes while a condition is true

Yields:

  • (scene)

    To determine if a scene must be popped.

Yield Parameters:

  • scene (Ray::Scene)

    The scene that will be popped

Yield Returns:

  • (Boolean)

    True to pop the next scene


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

def pop_scene_while(&block)
  game.pop_scene_while(&block)
end

#push_scene(scene, *args) ⇒ Object

Pushes a scene in the stack, and exits that one


237
238
239
240
# File 'lib/ray/scene.rb', line 237

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

#registerObject

Override this method in subclasses to register your own events


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

def register
end

#register_eventsObject


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

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


228
229
230
231
232
233
234
# File 'lib/ray/scene.rb', line 228

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.


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

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.


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

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


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

def run_tick(check_events = true)
  collect_events if check_events

  @scene_animations.update
  @scene_always_block.call if @scene_always_block

  listener_runner.run

  @scene_animations.remove_unused

  @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.


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

def setup(*args)
end

#windowObject


272
273
274
# File 'lib/ray/scene.rb', line 272

def window
  @scene_window
end

#window=(val) ⇒ Object


276
277
278
# File 'lib/ray/scene.rb', line 276

def window=(val)
  @scene_window = val
end