metro 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +19 -0
- data/changelog.md +8 -0
- data/lib/assets/missing_animation.png +0 -0
- data/lib/commands/generate_model.rb +2 -2
- data/lib/commands/generate_scene.rb +12 -2
- data/lib/commands/generate_view.rb +1 -1
- data/lib/gosu_ext/color.rb +1 -1
- data/lib/gosu_ext/image.rb +5 -0
- data/lib/metro.rb +18 -5
- data/lib/metro/animation/animation.rb +31 -0
- data/lib/metro/asset_path.rb +9 -0
- data/lib/metro/events/event_dictionary.rb +53 -0
- data/lib/metro/events/event_factory.rb +5 -3
- data/lib/metro/events/has_events.rb +5 -6
- data/lib/metro/game.rb +1 -1
- data/lib/metro/models/dimensions.rb +21 -0
- data/lib/metro/models/model.rb +149 -52
- data/lib/metro/models/model_factory.rb +4 -5
- data/lib/metro/models/{generic.rb → models/generic.rb} +0 -0
- data/lib/metro/models/{grid_drawer.rb → models/grid_drawer.rb} +4 -9
- data/lib/metro/models/{image.rb → models/image.rb} +11 -14
- data/lib/metro/models/models/label.rb +44 -0
- data/lib/metro/models/{menu.rb → models/menu.rb} +23 -18
- data/lib/metro/models/{rectangle.rb → models/rectangle.rb} +6 -5
- data/lib/metro/models/point.rb +23 -0
- data/lib/metro/models/properties/angle.rb +43 -0
- data/lib/metro/models/properties/animation.rb +143 -0
- data/lib/metro/models/properties/color.rb +113 -0
- data/lib/metro/models/properties/dimensions.rb +66 -0
- data/lib/metro/models/properties/font.rb +155 -0
- data/lib/metro/models/properties/image.rb +101 -0
- data/lib/metro/models/properties/numeric.rb +29 -0
- data/lib/metro/models/properties/position.rb +84 -0
- data/lib/metro/models/properties/property.rb +111 -0
- data/lib/metro/models/properties/scale.rb +89 -0
- data/lib/metro/models/properties/text.rb +66 -0
- data/lib/metro/models/properties/velocity.rb +80 -0
- data/lib/metro/models/scale.rb +21 -0
- data/lib/metro/scene.rb +19 -1
- data/lib/metro/scenes.rb +91 -31
- data/lib/metro/transitions/scene_transitions.rb +8 -0
- data/lib/metro/version.rb +1 -1
- data/lib/metro/views/view.rb +9 -1
- data/lib/templates/game/metro.tt +1 -1
- data/lib/templates/game/models/game_model.rb +3 -0
- data/lib/templates/game/scenes/brand_scene.rb +1 -1
- data/lib/templates/game/scenes/brand_to_title_scene.rb +1 -1
- data/lib/templates/game/scenes/game_scene.rb +19 -0
- data/lib/templates/game/scenes/title_scene.rb +1 -1
- data/lib/templates/game/views/brand_to_title.yaml +2 -2
- data/lib/templates/game/views/title.yaml +3 -3
- data/lib/templates/{model.rb.erb → model.rb.tt} +1 -1
- data/lib/templates/{scene.rb.erb → scene.rb.tt} +1 -1
- data/lib/templates/view.yaml.tt +6 -0
- data/spec/metro/models/models/label_spec.rb +110 -0
- data/spec/metro/models/properties/color_spec.rb +85 -0
- data/spec/metro/models/properties/font_spec.rb +129 -0
- data/spec/metro/models/properties/numeric_property_spec.rb +46 -0
- data/spec/metro/models/properties/position_property_spec.rb +90 -0
- data/spec/metro/scenes_spec.rb +77 -0
- metadata +50 -16
- data/lib/metro/models/label.rb +0 -63
- data/lib/templates/view.yaml.erb +0 -32
@@ -0,0 +1,89 @@
|
|
1
|
+
module Metro
|
2
|
+
class Model
|
3
|
+
|
4
|
+
#
|
5
|
+
# A scale property maintains an x and y scaling factor. This scale is not applied to any
|
6
|
+
#
|
7
|
+
# A font property also defines a `font_size` property and a `font_name` property which allows a
|
8
|
+
# more direct interface. Changing these values will update the font the next time that it is drawn.
|
9
|
+
#
|
10
|
+
# A font is stored in the properties as a hash representation and is converted into
|
11
|
+
# a Gosu::Font when it is retrieved within the system. When retrieving a font the Font
|
12
|
+
# Property will attempt to use a font that already exists that meets that criteria.
|
13
|
+
#
|
14
|
+
# The fonts are cached within the font property to help performance by reducing the unncessary
|
15
|
+
# creation of similar fonts.
|
16
|
+
#
|
17
|
+
# @example Defining a font property
|
18
|
+
#
|
19
|
+
# class Scoreboard < Metro::Model
|
20
|
+
# property :font
|
21
|
+
#
|
22
|
+
# def draw
|
23
|
+
# font.draw text, x, y, z_order, x_factor, y_factor, color
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# @example Defining a font property providing a default
|
29
|
+
#
|
30
|
+
# class Hero < Metro::Model
|
31
|
+
# property :font, default: { name: 'Comic Sans', size: 80 }
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# @example Using the `font_size` and `font_name` properties
|
35
|
+
#
|
36
|
+
# class Hero < Metro::Model
|
37
|
+
# property :color, default: "rgba(255,0,0,1.0)"
|
38
|
+
#
|
39
|
+
# def dignified
|
40
|
+
# self.font_size = 45
|
41
|
+
# self.font_name = 'Helvetica'
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# @example Using a font property with a different property name
|
46
|
+
#
|
47
|
+
# class Hero < Metro::Model
|
48
|
+
# property :alt_font, type: :font, default: "rgba(255,0,255,1.0)"
|
49
|
+
#
|
50
|
+
# def draw
|
51
|
+
# puts "Font: #{alt_font_name}:#{alt_font_size}"
|
52
|
+
# alt_font.draw text, x, y, z_order, x_factor, y_factor, color
|
53
|
+
# end
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
class ScaleProperty < Property
|
57
|
+
|
58
|
+
define_property :x_factor
|
59
|
+
|
60
|
+
define_property :y_factor
|
61
|
+
|
62
|
+
get do |value|
|
63
|
+
default_scale
|
64
|
+
end
|
65
|
+
|
66
|
+
get String do |value|
|
67
|
+
Scale.parse(value)
|
68
|
+
end
|
69
|
+
|
70
|
+
set do |value|
|
71
|
+
default_scale.to_s
|
72
|
+
end
|
73
|
+
|
74
|
+
set String do |value|
|
75
|
+
value
|
76
|
+
end
|
77
|
+
|
78
|
+
set Scale do |value|
|
79
|
+
value.to_s
|
80
|
+
end
|
81
|
+
|
82
|
+
def default_scale
|
83
|
+
(options[:default] and options[:default].is_a? Scale) ? options[:default] : Scale.one
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Metro
|
2
|
+
class Model
|
3
|
+
|
4
|
+
#
|
5
|
+
# A text property maintains a string of text
|
6
|
+
#
|
7
|
+
# Text is stored as text in properties. When retrieving the text, the contents of the text will
|
8
|
+
# be evaluated within the instance of the model's scene. Which means that text may contain
|
9
|
+
# escaped variables referencing anything in the scene or the game.
|
10
|
+
#
|
11
|
+
# @example Defining a text property
|
12
|
+
#
|
13
|
+
# class Scoreboard < Metro::Model
|
14
|
+
# property :text
|
15
|
+
#
|
16
|
+
# def draw
|
17
|
+
# font.draw text, x, y, z_order, x_factor, y_factor, color
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# @example Defining with a default and text that will be instance evaluated.
|
23
|
+
#
|
24
|
+
# class ScoreBoard < Metro::Model
|
25
|
+
# property :font, default: 'Score is #{player.score}'
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# @example Using a text property with a different property name
|
29
|
+
#
|
30
|
+
# class Hero < Metro::Model
|
31
|
+
# property :description, type: :text
|
32
|
+
#
|
33
|
+
# def draw
|
34
|
+
# description_font.draw text, x, y, z_order, x_factor, y_factor, color
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
class TextProperty < Property
|
39
|
+
|
40
|
+
# When no text is found for the field use the default text.
|
41
|
+
get do |value|
|
42
|
+
evalute_within_scene default_text
|
43
|
+
end
|
44
|
+
|
45
|
+
# When getting the text, evaluate the text within the scene.
|
46
|
+
get String do |value|
|
47
|
+
evalute_within_scene(value)
|
48
|
+
end
|
49
|
+
|
50
|
+
# When saving, simply save whatever is given as text.
|
51
|
+
set do |value|
|
52
|
+
value.to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
def evalute_within_scene(text)
|
56
|
+
model.scene.instance_eval( "\"#{text}\"" )
|
57
|
+
end
|
58
|
+
|
59
|
+
def default_text
|
60
|
+
options[:default] || 'Text for #{model} not specified!'
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Metro
|
2
|
+
class Model
|
3
|
+
|
4
|
+
class VectorProperty < Property
|
5
|
+
|
6
|
+
def get(value)
|
7
|
+
value ? value : Vector.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def set(value)
|
11
|
+
Vector.new value
|
12
|
+
end
|
13
|
+
|
14
|
+
class Vector
|
15
|
+
|
16
|
+
def initialize(angle,velocity)
|
17
|
+
@angle = angle
|
18
|
+
@velocity = velocity
|
19
|
+
end
|
20
|
+
|
21
|
+
def decay!
|
22
|
+
@velocity.decay!
|
23
|
+
end
|
24
|
+
|
25
|
+
def accelerate(amount,angle)
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def apply_x(x_position)
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
def apply_y(y_position)
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
class VelocityProperty < Property
|
43
|
+
|
44
|
+
def get(value)
|
45
|
+
value ? value : Velocity.new(0.0,0.95)
|
46
|
+
end
|
47
|
+
|
48
|
+
def set(value)
|
49
|
+
Velocity.new value
|
50
|
+
end
|
51
|
+
|
52
|
+
class Velocity
|
53
|
+
|
54
|
+
def initialize(value,decay = default_decay)
|
55
|
+
@value = value.to_f
|
56
|
+
@decay = decay || default_decay
|
57
|
+
end
|
58
|
+
|
59
|
+
def default_decay
|
60
|
+
0.95
|
61
|
+
end
|
62
|
+
|
63
|
+
def decay
|
64
|
+
@value *= @decay
|
65
|
+
end
|
66
|
+
|
67
|
+
def accelerate(amount)
|
68
|
+
@value += amount
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_f
|
72
|
+
@value
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Metro
|
2
|
+
class Scale < Struct.new(:x_factor,:y_factor)
|
3
|
+
|
4
|
+
def self.one
|
5
|
+
new 1.0, 1.0
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.to(x,y)
|
9
|
+
new x.to_f, y.to_f
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.parse(string)
|
13
|
+
to *string.split(",",2).map(&:to_f)
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
"#{x_factor},#{y_factor}"
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/lib/metro/scene.rb
CHANGED
@@ -251,6 +251,7 @@ module Metro
|
|
251
251
|
registering_actor.window = window
|
252
252
|
|
253
253
|
drawers.push(registering_actor)
|
254
|
+
updaters.push(registering_actor)
|
254
255
|
|
255
256
|
register_events_for_target(registering_actor,registering_actor.class.events)
|
256
257
|
end
|
@@ -281,12 +282,29 @@ module Metro
|
|
281
282
|
#
|
282
283
|
def self.scene_name(scene_name=nil)
|
283
284
|
@scene_name ||= begin
|
284
|
-
to_s
|
285
|
+
if to_s == "Metro::Scene"
|
286
|
+
to_s.underscore
|
287
|
+
else
|
288
|
+
to_s.gsub(/_?Scene$/i,'').underscore
|
289
|
+
end
|
285
290
|
end
|
286
291
|
|
287
292
|
scene_name ? @scene_name = scene_name.to_s : @scene_name
|
288
293
|
end
|
289
294
|
|
295
|
+
#
|
296
|
+
# @return a common name that can be used through the system as a common identifier.
|
297
|
+
#
|
298
|
+
def self.metro_name
|
299
|
+
scene_name
|
300
|
+
end
|
301
|
+
|
302
|
+
#
|
303
|
+
# @return an array of all the scene names of all the ancestor scenes
|
304
|
+
#
|
305
|
+
def self.hierarchy
|
306
|
+
ancestors.find_all {|a| a.respond_to? :metro_name }.map(&:metro_name)
|
307
|
+
end
|
290
308
|
|
291
309
|
#
|
292
310
|
# Allows you to set or retrieve the scene name for the Scene.
|
data/lib/metro/scenes.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require_relative 'transitions/scene_transitions'
|
2
|
-
|
3
1
|
module Metro
|
4
2
|
|
5
3
|
#
|
@@ -11,7 +9,6 @@ module Metro
|
|
11
9
|
#
|
12
10
|
# Scenes.find("intro") # => IntroScene
|
13
11
|
# Scenes.find(:intro) # => IntroScene
|
14
|
-
# Scenes.find(IntroScene) # => IntroScene
|
15
12
|
#
|
16
13
|
# @example Creating a scene instance based on the scene name
|
17
14
|
#
|
@@ -21,7 +18,11 @@ module Metro
|
|
21
18
|
#
|
22
19
|
# Scenes.generate("intro") # => [SCENE: title]
|
23
20
|
# Scenes.generate(:intro) # => [SCENE: title]
|
24
|
-
#
|
21
|
+
#
|
22
|
+
# @example Finding a scene that does not exist
|
23
|
+
#
|
24
|
+
# scene = Scenes.find(:unknown)
|
25
|
+
# scene.missing_scene # => :unknown
|
25
26
|
#
|
26
27
|
module Scenes
|
27
28
|
extend self
|
@@ -33,18 +34,7 @@ module Metro
|
|
33
34
|
# @return the Scene class that is found matching the specified scene name.
|
34
35
|
#
|
35
36
|
def find(scene_name)
|
36
|
-
|
37
|
-
|
38
|
-
if found_scene
|
39
|
-
found_scene.constantize
|
40
|
-
else
|
41
|
-
create_missing_scene(scene_name)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def create_missing_scene(scene_name)
|
46
|
-
MissingScene.missing_scene = scene_name
|
47
|
-
MissingScene
|
37
|
+
scene_class( scenes_hash[scene_name] )
|
48
38
|
end
|
49
39
|
|
50
40
|
#
|
@@ -55,16 +45,18 @@ module Metro
|
|
55
45
|
# @return an instance of Scene that is found matching the specified scene name
|
56
46
|
#
|
57
47
|
def generate(scene_or_scene_name,options = {})
|
58
|
-
new_scene =
|
59
|
-
|
60
|
-
post_filters.inject(new_scene) {|scene,post| post.filter(scene,options) }
|
48
|
+
new_scene = generate_scene_from(scene_or_scene_name)
|
49
|
+
apply_post_filters(new_scene,options)
|
61
50
|
end
|
62
51
|
|
63
52
|
#
|
64
53
|
# If we have been given a scene, then we simply want to use it otherwise
|
65
54
|
# we need to find and generate our scene from the scene name.
|
66
|
-
#
|
67
|
-
|
55
|
+
#
|
56
|
+
# @param [String,Sybmol,Class] scene_or_scene_name the name of the scene or an instance
|
57
|
+
# of Scene.
|
58
|
+
#
|
59
|
+
def generate_scene_from(scene_or_scene_name)
|
68
60
|
if scene_or_scene_name.is_a? Scene
|
69
61
|
scene_or_scene_name
|
70
62
|
else
|
@@ -75,27 +67,95 @@ module Metro
|
|
75
67
|
#
|
76
68
|
# Post filters are applied to the scene after it has been found. These are
|
77
69
|
# all objects that can respond to the #filter method.
|
78
|
-
#
|
70
|
+
#
|
79
71
|
def post_filters
|
80
|
-
|
72
|
+
@post_filters ||= []
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# Register a filter that will be executed after a scene is found and generated. This
|
77
|
+
# allows for the scene to be modified or changed based on the provided options.
|
78
|
+
#
|
79
|
+
# A filter is any object that responds to #filter and accepts two parameters: the
|
80
|
+
# scene and a hash of options.
|
81
|
+
#
|
82
|
+
# @param [#filter] post_filter a filter is an object that can act as a filter.
|
83
|
+
#
|
84
|
+
def register_post_filter(post_filter)
|
85
|
+
post_filters.push(post_filter)
|
81
86
|
end
|
82
87
|
|
83
88
|
private
|
84
89
|
|
90
|
+
#
|
91
|
+
# Apply all the post filtering to the specified scene with the given options
|
92
|
+
#
|
93
|
+
# @return a Scene object that has been filtered.
|
94
|
+
#
|
95
|
+
def apply_post_filters(new_scene,options)
|
96
|
+
post_filters.inject(new_scene) {|scene,post| post.filter(scene,options) }
|
97
|
+
end
|
98
|
+
|
85
99
|
#
|
86
100
|
# @return a Hash that allows for accessing symbol names of the scenes
|
87
101
|
# as well as the class name constants to allow for the scenes to be found.
|
88
102
|
#
|
89
103
|
def scenes_hash
|
90
|
-
@scenes_hash ||= Scene.scenes
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
104
|
+
@scenes_hash ||= build_map_of_scenes(Scene.scenes)
|
105
|
+
end
|
106
|
+
|
107
|
+
#
|
108
|
+
# Generate a map from the scene or scenes to include all the sub-classes of
|
109
|
+
# these scenes.
|
110
|
+
#
|
111
|
+
# @param [Scene,Array<Scene>] scenes a scene or scene subclass or an array of
|
112
|
+
# scene subclasses.
|
113
|
+
#
|
114
|
+
# @see #scenes_hash
|
115
|
+
#
|
116
|
+
def build_map_of_scenes(scenes)
|
117
|
+
hash = hash_with_missing_scene_default
|
118
|
+
all_scenes_for(scenes).inject(hash) do |hash,scene|
|
119
|
+
hash[scene.scene_name] = scene.to_s
|
120
|
+
hash
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
#
|
125
|
+
# Create a hash that will return a setup missing scene by default.
|
126
|
+
#
|
127
|
+
def hash_with_missing_scene_default
|
128
|
+
ActiveSupport::HashWithIndifferentAccess.new do |hash,key|
|
129
|
+
missing_scene = scene_class(hash[:missing_scene])
|
130
|
+
missing_scene.missing_scene = key.to_sym
|
131
|
+
missing_scene
|
97
132
|
end
|
98
133
|
end
|
99
134
|
|
135
|
+
#
|
136
|
+
# Returns all subclassed scenes of the scene or scenes provided. This method is
|
137
|
+
# meant to be called recursively to generate the entire list of all the scenes.
|
138
|
+
#
|
139
|
+
# @param [Scene,Array<Scene>] scenes a scene or scene subclass or an array of
|
140
|
+
# scene subclasses.
|
141
|
+
#
|
142
|
+
def all_scenes_for(scenes)
|
143
|
+
Array(scenes).map do |scene_class_name|
|
144
|
+
scene = scene_class(scene_class_name)
|
145
|
+
[ scene ] + all_scenes_for(scene.scenes)
|
146
|
+
end.flatten.compact
|
147
|
+
end
|
148
|
+
|
149
|
+
#
|
150
|
+
# @param [String,Symbol] class_name the name of the class that you want the class
|
151
|
+
#
|
152
|
+
# @return the class with the given class name
|
153
|
+
#
|
154
|
+
def scene_class(class_or_class_name)
|
155
|
+
class_or_class_name.class == Class ? class_or_class_name : class_or_class_name.constantize
|
156
|
+
end
|
157
|
+
|
100
158
|
end
|
101
|
-
end
|
159
|
+
end
|
160
|
+
|
161
|
+
require_relative 'transitions/scene_transitions'
|