metro 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +29 -13
- data/changelog.md +10 -0
- data/lib/core_ext/numeric.rb +59 -0
- data/lib/gosu_ext/gosu_constants.rb +53 -0
- data/lib/locale/en.yml +16 -0
- data/lib/locale/locale.rb +1 -0
- data/lib/metro.rb +30 -16
- data/lib/metro/animation/after_interval_factory.rb +12 -0
- data/lib/metro/animation/animation_factory.rb +3 -2
- data/lib/metro/animation/has_animations.rb +3 -3
- data/lib/metro/animation/implicit_animation.rb +33 -19
- data/lib/metro/animation/{animation.rb → on_update_operation.rb} +6 -4
- data/lib/metro/animation/scene_animation.rb +16 -0
- data/lib/metro/events/control_definition.rb +11 -0
- data/lib/metro/events/controls.rb +42 -0
- data/lib/metro/events/event_relay.rb +49 -11
- data/lib/metro/events/has_events.rb +6 -5
- data/lib/metro/game.rb +17 -11
- data/lib/metro/game/dsl.rb +8 -0
- data/lib/metro/models/image.rb +3 -1
- data/lib/metro/models/key_value_coding.rb +38 -0
- data/lib/metro/models/label.rb +18 -3
- data/lib/metro/models/menu.rb +6 -5
- data/lib/metro/models/model.rb +11 -4
- data/lib/metro/models/rectangle.rb +28 -0
- data/lib/metro/scene.rb +76 -15
- data/lib/metro/scene_view/yaml_view.rb +11 -4
- data/lib/metro/scenes.rb +27 -3
- data/lib/metro/template_message.rb +33 -4
- data/lib/metro/transitions/fade_transition_scene.rb +59 -0
- data/lib/metro/transitions/scene_transitions.rb +30 -0
- data/lib/metro/transitions/transition_scene.rb +18 -0
- data/lib/metro/version.rb +1 -1
- data/lib/metro/window.rb +0 -2
- data/lib/templates/game/metro.tt +13 -0
- data/lib/templates/game/scenes/brand_scene.rb +10 -4
- data/lib/templates/game/scenes/brand_to_title_scene.rb +3 -3
- data/lib/templates/game/scenes/title_scene.rb +1 -1
- data/lib/templates/game/views/brand_to_title.yaml +2 -4
- data/lib/templates/game/views/title.yaml +2 -4
- data/lib/templates/message.erb +1 -1
- data/lib/templates/model.rb.erb +2 -2
- data/lib/templates/scene.rb.erb +3 -3
- data/metro.gemspec +1 -0
- data/spec/core_ext/numeric_spec.rb +78 -0
- data/spec/metro/models/key_value_coding_spec.rb +61 -0
- data/spec/metro/scene_views/yaml_view_spec.rb +38 -0
- metadata +44 -6
- data/lib/metro/error.rb +0 -21
data/lib/metro/models/menu.rb
CHANGED
@@ -10,25 +10,26 @@ module Metro
|
|
10
10
|
#
|
11
11
|
class Menu < Model
|
12
12
|
|
13
|
-
event :on_up,
|
13
|
+
event :on_up, KbLeft, GpLeft, KbUp, GpUp do
|
14
14
|
previous_option
|
15
15
|
end
|
16
16
|
|
17
|
-
event :on_up,
|
17
|
+
event :on_up, KbRight, GpRight, KbDown, GpDown do
|
18
18
|
next_option
|
19
19
|
end
|
20
20
|
|
21
|
-
event :on_up,
|
21
|
+
event :on_up, KbEnter, KbReturn, GpButton0 do
|
22
22
|
selection
|
23
23
|
end
|
24
24
|
|
25
25
|
attr_reader :selected_index, :menu_options
|
26
26
|
|
27
|
-
attr_accessor :padding
|
27
|
+
attr_accessor :padding, :z_order
|
28
28
|
|
29
29
|
def after_initialize
|
30
30
|
@selected_index = 0
|
31
31
|
@padding = 40
|
32
|
+
@z_order = 1
|
32
33
|
end
|
33
34
|
|
34
35
|
def window=(value)
|
@@ -79,7 +80,7 @@ module Metro
|
|
79
80
|
draw_color = highlight_color if index == selected_index
|
80
81
|
|
81
82
|
y_position = y + padding * index
|
82
|
-
font.draw option_name, x, y_position,
|
83
|
+
font.draw option_name, x, y_position, z_order, 1.0, 1.0, draw_color
|
83
84
|
end
|
84
85
|
end
|
85
86
|
|
data/lib/metro/models/model.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative 'key_value_coding'
|
2
|
+
|
1
3
|
module Metro
|
2
4
|
|
3
5
|
#
|
@@ -32,6 +34,8 @@ module Metro
|
|
32
34
|
# @see Scene
|
33
35
|
attr_accessor :scene
|
34
36
|
|
37
|
+
include KeyValueCoding
|
38
|
+
|
35
39
|
#
|
36
40
|
# This is an entry point for customization. As the model's {#initialize}
|
37
41
|
# method performs may perform some initialization that may be necessary.
|
@@ -44,14 +48,14 @@ module Metro
|
|
44
48
|
# Generate a custom notification event with the given name.
|
45
49
|
#
|
46
50
|
# @param [Symbol] event the name of the notification to generate.
|
47
|
-
#
|
51
|
+
#
|
48
52
|
def notification(event)
|
49
53
|
scene.notification(event.to_sym)
|
50
54
|
end
|
51
55
|
|
52
56
|
#
|
53
57
|
# Allows for the definition of events within the scene.
|
54
|
-
#
|
58
|
+
#
|
55
59
|
include HasEvents
|
56
60
|
|
57
61
|
#
|
@@ -62,7 +66,9 @@ module Metro
|
|
62
66
|
#
|
63
67
|
# @see #alpha
|
64
68
|
#
|
65
|
-
|
69
|
+
def color
|
70
|
+
@color
|
71
|
+
end
|
66
72
|
|
67
73
|
#
|
68
74
|
# Sets the color of the model.
|
@@ -199,4 +205,5 @@ end
|
|
199
205
|
require_relative 'generic'
|
200
206
|
require_relative 'label'
|
201
207
|
require_relative 'menu'
|
202
|
-
require_relative 'image'
|
208
|
+
require_relative 'image'
|
209
|
+
require_relative 'rectangle'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Metro
|
2
|
+
module Models
|
3
|
+
|
4
|
+
class Rectangle < ::Metro::Model
|
5
|
+
|
6
|
+
attr_accessor :x, :y, :z_order, :width, :height
|
7
|
+
|
8
|
+
def after_initialize
|
9
|
+
@x = @y = 0
|
10
|
+
@z_order = 1
|
11
|
+
end
|
12
|
+
|
13
|
+
def width
|
14
|
+
@width || window.width
|
15
|
+
end
|
16
|
+
|
17
|
+
def height
|
18
|
+
@height || window.height
|
19
|
+
end
|
20
|
+
|
21
|
+
def draw
|
22
|
+
window.draw_quad(x,y,color,width,x,color,
|
23
|
+
width,height,color,y,height,color,
|
24
|
+
z_order)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/metro/scene.rb
CHANGED
@@ -7,7 +7,8 @@ require_relative 'events/unknown_sender'
|
|
7
7
|
require_relative 'models/draws'
|
8
8
|
|
9
9
|
require_relative 'animation/has_animations'
|
10
|
-
require_relative 'animation/
|
10
|
+
require_relative 'animation/scene_animation'
|
11
|
+
require_relative 'animation/after_interval_factory'
|
11
12
|
|
12
13
|
module Metro
|
13
14
|
|
@@ -91,8 +92,12 @@ module Metro
|
|
91
92
|
#
|
92
93
|
# @return the actor with the given name.
|
93
94
|
#
|
94
|
-
def actor(
|
95
|
-
|
95
|
+
def actor(actor_or_actor_name)
|
96
|
+
if actor_or_actor_name.is_a? String or actor_or_actor_name.is_a? Symbol
|
97
|
+
send(actor_or_actor_name)
|
98
|
+
else
|
99
|
+
actor_or_actor_name
|
100
|
+
end
|
96
101
|
end
|
97
102
|
|
98
103
|
#
|
@@ -125,6 +130,47 @@ module Metro
|
|
125
130
|
#
|
126
131
|
include HasAnimations
|
127
132
|
|
133
|
+
#
|
134
|
+
# Allow the definition of a updater that will be executed when the scene starts.
|
135
|
+
#
|
136
|
+
# @example Setting up an event to 2 seconds after the scene has started.
|
137
|
+
#
|
138
|
+
# class ExampleScene
|
139
|
+
#
|
140
|
+
# draws :title
|
141
|
+
#
|
142
|
+
# after 2.seconds do
|
143
|
+
# transition_to :next_scene
|
144
|
+
# end
|
145
|
+
# end
|
146
|
+
#
|
147
|
+
def self.after(ticks,&block)
|
148
|
+
after_intervals.push AfterIntervalFactory.new ticks, &block
|
149
|
+
end
|
150
|
+
|
151
|
+
#
|
152
|
+
# Perform an operation after the specified interval.
|
153
|
+
#
|
154
|
+
# class ExampleScene
|
155
|
+
#
|
156
|
+
# draws :player
|
157
|
+
#
|
158
|
+
# def update
|
159
|
+
# if player.is_dead?
|
160
|
+
# after 2.seconds do
|
161
|
+
# transition_to :game_over
|
162
|
+
# end
|
163
|
+
# end
|
164
|
+
# end
|
165
|
+
#
|
166
|
+
# end
|
167
|
+
#
|
168
|
+
def after(ticks,&block)
|
169
|
+
tick = OnUpdateOperation.new interval: ticks, context: self
|
170
|
+
tick.on_complete(&block)
|
171
|
+
enqueue tick
|
172
|
+
end
|
173
|
+
|
128
174
|
#
|
129
175
|
# Setups up the Actors for the Scene based on the ModelFactories that have been
|
130
176
|
# defined.
|
@@ -166,6 +212,7 @@ module Metro
|
|
166
212
|
register_events!
|
167
213
|
register_actors!
|
168
214
|
register_animations!
|
215
|
+
register_after_intervals!
|
169
216
|
|
170
217
|
show
|
171
218
|
end
|
@@ -189,7 +236,13 @@ module Metro
|
|
189
236
|
#
|
190
237
|
def register_animations!
|
191
238
|
self.class.animations.each do |animation|
|
192
|
-
animate animation.options, &animation.on_complete_block
|
239
|
+
animate animation.actor, animation.options, &animation.on_complete_block
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def register_after_intervals!
|
244
|
+
self.class.after_intervals.each do |after_interval|
|
245
|
+
after after_interval.ticks, &after_interval.block
|
193
246
|
end
|
194
247
|
end
|
195
248
|
|
@@ -282,13 +335,20 @@ module Metro
|
|
282
335
|
# A simplier syntax to enqueue an animation. At the moment this animation is going
|
283
336
|
# to be an implicit animation.
|
284
337
|
#
|
285
|
-
def animate(options,&block)
|
286
|
-
options[:actor] = actor(
|
287
|
-
|
288
|
-
|
289
|
-
enqueue
|
338
|
+
def animate(actor_or_actor_name,options,&block)
|
339
|
+
options[:actor] = actor(actor_or_actor_name)
|
340
|
+
options[:context] = self
|
341
|
+
animation_group = SceneAnimation.build options, &block
|
342
|
+
enqueue animation_group
|
290
343
|
end
|
291
344
|
|
345
|
+
#
|
346
|
+
# The class defined updaters which will be converted to instance updaters when the scene
|
347
|
+
# has started.
|
348
|
+
#
|
349
|
+
def self.after_intervals
|
350
|
+
@after_intervals ||= []
|
351
|
+
end
|
292
352
|
|
293
353
|
#
|
294
354
|
# The objects that need to be executed on every update. These objects are traditionally
|
@@ -334,11 +394,12 @@ module Metro
|
|
334
394
|
# `transition_to` performs the work of transitioning this scene
|
335
395
|
# to another scene.
|
336
396
|
#
|
337
|
-
# @param [String,Symbol,
|
338
|
-
# the class or a string/symbol representation of the shortened scene name.
|
397
|
+
# @param [String,Symbol,Object] scene_or_scene_name the name of the Scene which can
|
398
|
+
# be either the class or a string/symbol representation of the shortened scene name.
|
399
|
+
# This could also be an instance of scene.
|
339
400
|
#
|
340
|
-
def transition_to(
|
341
|
-
new_scene = Scenes.generate(
|
401
|
+
def transition_to(scene_or_scene_name,options = {})
|
402
|
+
new_scene = Scenes.generate(scene_or_scene_name,options)
|
342
403
|
_prepare_transition(new_scene)
|
343
404
|
window.scene = new_scene
|
344
405
|
end
|
@@ -412,7 +473,7 @@ module Metro
|
|
412
473
|
#
|
413
474
|
def button_up(id)
|
414
475
|
event_relays.each do |relay|
|
415
|
-
relay.
|
476
|
+
relay.fire_button_up(id)
|
416
477
|
end
|
417
478
|
end
|
418
479
|
|
@@ -422,7 +483,7 @@ module Metro
|
|
422
483
|
#
|
423
484
|
def button_down(id)
|
424
485
|
event_relays.each do |relay|
|
425
|
-
relay.
|
486
|
+
relay.fire_button_down(id)
|
426
487
|
end
|
427
488
|
end
|
428
489
|
|
@@ -12,7 +12,7 @@ module Metro
|
|
12
12
|
# @return a true if the yaml view exists and false if it does not exist.
|
13
13
|
#
|
14
14
|
def self.exists?(view_name)
|
15
|
-
File.exists?
|
15
|
+
yaml_view_names(view_name).find { |view_name| File.exists? view_name }
|
16
16
|
end
|
17
17
|
|
18
18
|
#
|
@@ -25,12 +25,19 @@ module Metro
|
|
25
25
|
YAML.load File.read yaml_view_name(view_name)
|
26
26
|
end
|
27
27
|
|
28
|
+
#
|
29
|
+
# A helper method to get the view file.
|
30
|
+
#
|
31
|
+
def self.yaml_view_name(view_name)
|
32
|
+
yaml_view_names(view_name).find { |view_name| File.exists? view_name }
|
33
|
+
end
|
34
|
+
|
28
35
|
#
|
29
36
|
# A helper method to generate the name of the yaml view file. In this case
|
30
|
-
# it is the view name with the suffix
|
37
|
+
# it is the view name with the suffix `.yaml` or `.yml`.
|
31
38
|
#
|
32
|
-
def self.
|
33
|
-
File.extname(view_name) == "" ? "#{view_name}.yaml" : view_name
|
39
|
+
def self.yaml_view_names(view_name)
|
40
|
+
File.extname(view_name) == "" ? [ "#{view_name}.yaml", "#{view_name}.yml" ] : [ view_name ]
|
34
41
|
end
|
35
42
|
end
|
36
43
|
|
data/lib/metro/scenes.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative 'transitions/scene_transitions'
|
2
|
+
|
1
3
|
module Metro
|
2
4
|
|
3
5
|
#
|
@@ -49,11 +51,33 @@ module Metro
|
|
49
51
|
# Finds the scene with the specified name and then creates an instance of that
|
50
52
|
# scene.
|
51
53
|
#
|
52
|
-
# @param [String,Symbol] scene_name the name of the scene to locate.
|
54
|
+
# @param [String,Symbol,Object] scene_name the name of the scene to locate.
|
53
55
|
# @return an instance of Scene that is found matching the specified scene name
|
54
56
|
#
|
55
|
-
def generate(
|
56
|
-
|
57
|
+
def generate(scene_or_scene_name,options = {})
|
58
|
+
new_scene = use_scene_or_generate_scene(scene_or_scene_name)
|
59
|
+
|
60
|
+
post_filters.inject(new_scene) {|scene,post| post.filter(scene,options) }
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# If we have been given a scene, then we simply want to use it otherwise
|
65
|
+
# we need to find and generate our scene from the scene name.
|
66
|
+
#
|
67
|
+
def use_scene_or_generate_scene(scene_or_scene_name)
|
68
|
+
if scene_or_scene_name.is_a? Scene
|
69
|
+
scene_or_scene_name
|
70
|
+
else
|
71
|
+
find(scene_or_scene_name).new
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# Post filters are applied to the scene after it has been found. These are
|
77
|
+
# all objects that can respond to the #filter method.
|
78
|
+
#
|
79
|
+
def post_filters
|
80
|
+
[ SceneTransitions ]
|
57
81
|
end
|
58
82
|
|
59
83
|
private
|
@@ -2,18 +2,47 @@ class TemplateMessage
|
|
2
2
|
|
3
3
|
def initialize(details = {})
|
4
4
|
@messages = Array(details[:message]) + Array(details[:messages])
|
5
|
+
@details = details[:details]
|
5
6
|
@website = details[:website]
|
6
|
-
@email =
|
7
|
+
@email = details[:contact]
|
7
8
|
end
|
8
9
|
|
9
|
-
|
10
|
+
class Message
|
11
|
+
|
12
|
+
attr_reader :name, :details
|
13
|
+
|
14
|
+
def initialize(name,details)
|
15
|
+
@name = name
|
16
|
+
@details = details
|
17
|
+
end
|
18
|
+
|
19
|
+
def field_locale(field)
|
20
|
+
I18n.t("#{name}.#{field}",details)
|
21
|
+
end
|
22
|
+
|
23
|
+
def title
|
24
|
+
field_locale 'title'
|
25
|
+
end
|
26
|
+
|
27
|
+
def message
|
28
|
+
field_locale 'message'
|
29
|
+
end
|
30
|
+
|
31
|
+
def actions
|
32
|
+
Array( field_locale('actions') ).map {|action| "* #{action}" }.join("\n")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def messages
|
37
|
+
@messages.map {|m| Message.new m, @details }
|
38
|
+
end
|
10
39
|
|
11
40
|
def website
|
12
|
-
"* #{
|
41
|
+
Array(@website).map {|website| "* #{website}" }.join("\n")
|
13
42
|
end
|
14
43
|
|
15
44
|
def email
|
16
|
-
@email.map {|email| "* #{email}" }.join("\n")
|
45
|
+
Array(@email).map {|email| "* #{email}" }.join("\n")
|
17
46
|
end
|
18
47
|
|
19
48
|
def message_filename
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Metro
|
2
|
+
class FadeTransitionScene < TransitionScene
|
3
|
+
|
4
|
+
draw :rectangle, model: "metro::models::rectangle"
|
5
|
+
|
6
|
+
#
|
7
|
+
# When the scene is shown set up the starting color for the rectangle
|
8
|
+
# and queue the animation to transition the color to the final color.
|
9
|
+
#
|
10
|
+
def show
|
11
|
+
rectangle.color = starting_color
|
12
|
+
|
13
|
+
animate :rectangle, to: { color: final_color }, interval: interval do
|
14
|
+
transition_to next_scene
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def interval
|
19
|
+
options[:interval] || default_interval
|
20
|
+
end
|
21
|
+
|
22
|
+
def default_interval
|
23
|
+
60
|
24
|
+
end
|
25
|
+
|
26
|
+
def starting_color
|
27
|
+
options_starting_color || default_starting_color
|
28
|
+
end
|
29
|
+
|
30
|
+
def options_starting_color
|
31
|
+
color_from_options(:from)
|
32
|
+
end
|
33
|
+
|
34
|
+
def default_starting_color
|
35
|
+
Gosu::Color.new "rgb(255,255,255)"
|
36
|
+
end
|
37
|
+
|
38
|
+
def final_color
|
39
|
+
options_final_color || default_final_color
|
40
|
+
end
|
41
|
+
|
42
|
+
def options_final_color
|
43
|
+
color_from_options(:to)
|
44
|
+
end
|
45
|
+
|
46
|
+
def default_final_color
|
47
|
+
Gosu::Color.new "rgb(0,0,0)"
|
48
|
+
end
|
49
|
+
|
50
|
+
def color_from_options(position)
|
51
|
+
if options[position]
|
52
|
+
if options[position][:color]
|
53
|
+
Gosu::Color.new options[position][:color]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|