metro 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -9,10 +9,9 @@ module Metro
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def create
|
12
|
-
|
13
|
-
actor_class = class_for_actor(model_name(contents))
|
12
|
+
actor_class = class_for_actor(model_name)
|
14
13
|
instance = actor_class.new
|
15
|
-
instance._load options
|
14
|
+
instance._load options
|
16
15
|
instance
|
17
16
|
end
|
18
17
|
|
@@ -20,8 +19,8 @@ module Metro
|
|
20
19
|
options[:from] == :previous_scene
|
21
20
|
end
|
22
21
|
|
23
|
-
def model_name
|
24
|
-
|
22
|
+
def model_name
|
23
|
+
options['model'] || options[:model] || name
|
25
24
|
end
|
26
25
|
|
27
26
|
def class_for_actor(model_name)
|
File without changes
|
@@ -3,16 +3,15 @@ module Metro
|
|
3
3
|
|
4
4
|
class GridDrawer < Model
|
5
5
|
|
6
|
-
|
6
|
+
property :color, default: "rgba(255,255,255,0.1)"
|
7
|
+
property :spacing, type: :numeric, default: 10
|
8
|
+
|
9
|
+
attr_writer :spacing, :height, :width
|
7
10
|
|
8
11
|
def name
|
9
12
|
self.class.name
|
10
13
|
end
|
11
14
|
|
12
|
-
def spacing
|
13
|
-
@spacing ||= 10
|
14
|
-
end
|
15
|
-
|
16
15
|
def height
|
17
16
|
@height || Game.height
|
18
17
|
end
|
@@ -21,10 +20,6 @@ module Metro
|
|
21
20
|
@width || Game.width
|
22
21
|
end
|
23
22
|
|
24
|
-
def color
|
25
|
-
@color ||= Gosu::Color.new("rgba(255,255,255,0.1)")
|
26
|
-
end
|
27
|
-
|
28
23
|
def saveable?
|
29
24
|
false
|
30
25
|
end
|
@@ -9,21 +9,18 @@ module Metro
|
|
9
9
|
#
|
10
10
|
class Image < Model
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
def after_initialize
|
15
|
-
@angle = 0
|
16
|
-
@center_x = @center_y = 0.5
|
17
|
-
@x_factor = @y_factor = 1
|
18
|
-
@z_order = 0
|
19
|
-
@color = Gosu::Color.new "rgba(255,255,255,1.0)"
|
20
|
-
@x = Game.width / 2
|
21
|
-
@y = Game.height / 2
|
22
|
-
end
|
12
|
+
property :position
|
23
13
|
|
24
|
-
|
25
|
-
|
26
|
-
|
14
|
+
property :scale, default: Scale.one
|
15
|
+
|
16
|
+
property :color
|
17
|
+
|
18
|
+
property :angle, type: :numeric, default: 0
|
19
|
+
|
20
|
+
property :center_x, type: :numeric, default: 0.5
|
21
|
+
property :center_y, type: :numeric, default: 0.5
|
22
|
+
|
23
|
+
property :image
|
27
24
|
|
28
25
|
def contains?(x,y)
|
29
26
|
bounds.contains?(x,y)
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Metro
|
2
|
+
module Models
|
3
|
+
|
4
|
+
#
|
5
|
+
# Draws a string of text
|
6
|
+
#
|
7
|
+
# @example Using the Label in a view file
|
8
|
+
# model: "metro::models::label"
|
9
|
+
#
|
10
|
+
class Label < Model
|
11
|
+
|
12
|
+
property :position
|
13
|
+
|
14
|
+
property :scale, default: Scale.one
|
15
|
+
|
16
|
+
property :color, default: "rgba(255,255,255,1.0)"
|
17
|
+
|
18
|
+
property :font, default: { size: 20 }
|
19
|
+
|
20
|
+
property :text
|
21
|
+
|
22
|
+
def bounds
|
23
|
+
Bounds.new x, y, x + width, y + height
|
24
|
+
end
|
25
|
+
|
26
|
+
def width
|
27
|
+
font.text_width(text) * x_factor
|
28
|
+
end
|
29
|
+
|
30
|
+
def height
|
31
|
+
font.height * y_factor
|
32
|
+
end
|
33
|
+
|
34
|
+
def contains?(x,y)
|
35
|
+
bounds.contains?(x,y)
|
36
|
+
end
|
37
|
+
|
38
|
+
def draw
|
39
|
+
font.draw text, x, y, z_order, x_factor, y_factor, color
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -10,6 +10,26 @@ module Metro
|
|
10
10
|
#
|
11
11
|
class Menu < Model
|
12
12
|
|
13
|
+
property :position, default: Game.center
|
14
|
+
|
15
|
+
property :scale, default: Scale.one
|
16
|
+
|
17
|
+
property :padding, type: :numeric, default: 40
|
18
|
+
|
19
|
+
property :unselected_color, type: :color, default: "rgba(119,119,119,1.0)"
|
20
|
+
property :selected_color, type: :color, default: "rgba(255,255,255,1.0)"
|
21
|
+
|
22
|
+
def alpha
|
23
|
+
self.unselected_color_alpha
|
24
|
+
end
|
25
|
+
|
26
|
+
def alpha=(value)
|
27
|
+
self.unselected_color_alpha = value.floor
|
28
|
+
self.selected_color_alpha = value.floor
|
29
|
+
end
|
30
|
+
|
31
|
+
property :font
|
32
|
+
|
13
33
|
event :on_up, KbLeft, GpLeft, KbUp, GpUp do
|
14
34
|
previous_option
|
15
35
|
end
|
@@ -24,12 +44,8 @@ module Metro
|
|
24
44
|
|
25
45
|
attr_reader :selected_index, :menu_options
|
26
46
|
|
27
|
-
attr_accessor :padding, :z_order
|
28
|
-
|
29
47
|
def after_initialize
|
30
48
|
@selected_index = 0
|
31
|
-
@padding = 40
|
32
|
-
@z_order = 1
|
33
49
|
end
|
34
50
|
|
35
51
|
def window=(value)
|
@@ -76,17 +92,6 @@ module Metro
|
|
76
92
|
options.length * font.height + (options.length - 1) * padding
|
77
93
|
end
|
78
94
|
|
79
|
-
attr_reader :highlight_color
|
80
|
-
|
81
|
-
def highlight_color=(value)
|
82
|
-
@highlight_color = Gosu::Color.new(value)
|
83
|
-
end
|
84
|
-
|
85
|
-
def alpha=(value)
|
86
|
-
color.alpha = value.floor
|
87
|
-
highlight_color.alpha = value.floor
|
88
|
-
end
|
89
|
-
|
90
95
|
def option_at_index(index)
|
91
96
|
menu_options[index]
|
92
97
|
end
|
@@ -96,11 +101,11 @@ module Metro
|
|
96
101
|
|
97
102
|
option_name = option_at_index(index).name
|
98
103
|
|
99
|
-
draw_color =
|
100
|
-
draw_color =
|
104
|
+
draw_color = unselected_color
|
105
|
+
draw_color = selected_color if index == selected_index
|
101
106
|
|
102
107
|
y_position = y + padding * index
|
103
|
-
font.draw option_name, x, y_position, z_order,
|
108
|
+
font.draw option_name, x, y_position, z_order, x_factor, y_factor, draw_color
|
104
109
|
end
|
105
110
|
end
|
106
111
|
|
@@ -3,12 +3,13 @@ module Metro
|
|
3
3
|
|
4
4
|
class Rectangle < ::Metro::Model
|
5
5
|
|
6
|
-
|
6
|
+
property :position
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
property :z_order, type: :numeric, default: 0
|
9
|
+
|
10
|
+
property :color
|
11
|
+
|
12
|
+
attr_writer :width, :height
|
12
13
|
|
13
14
|
def width
|
14
15
|
@width || window.width
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Metro
|
2
|
+
class Point < Struct.new(:x,:y,:z)
|
3
|
+
def self.zero
|
4
|
+
new 0.0, 0.0, 0.0
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.at(x,y,z=0.0)
|
8
|
+
new x.to_f, y.to_f, z.to_f
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.parse(string)
|
12
|
+
at *string.split(",",3).map(&:to_f)
|
13
|
+
end
|
14
|
+
|
15
|
+
alias_method :z_order, :z
|
16
|
+
alias_method :z_order=, :z=
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
"#{x},#{y},#{z}"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Metro
|
2
|
+
class Model
|
3
|
+
|
4
|
+
class AngleProperty < Property
|
5
|
+
|
6
|
+
def get(value)
|
7
|
+
value ? value : Angle.new(0.0, options[:step])
|
8
|
+
end
|
9
|
+
|
10
|
+
def set(value)
|
11
|
+
Angle.new(value.to_f, options[:step])
|
12
|
+
end
|
13
|
+
|
14
|
+
class Angle
|
15
|
+
|
16
|
+
attr_reader :value
|
17
|
+
|
18
|
+
def initialize(value = 0.0,step = 1.0)
|
19
|
+
@value = value.to_f
|
20
|
+
@step = step || 1.0
|
21
|
+
end
|
22
|
+
|
23
|
+
def turn(direction)
|
24
|
+
send(direction) if [ :left, :right ].include?(direction)
|
25
|
+
end
|
26
|
+
|
27
|
+
def left
|
28
|
+
@value -= @step
|
29
|
+
end
|
30
|
+
|
31
|
+
def right
|
32
|
+
@value += @step
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_f
|
36
|
+
@value.to_f
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require_relative '../../animation/animation'
|
2
|
+
|
3
|
+
module Metro
|
4
|
+
class Model
|
5
|
+
|
6
|
+
#
|
7
|
+
# A animation property manages an Animation, which is an array of Gosu::Images,
|
8
|
+
# and some metadata.
|
9
|
+
#
|
10
|
+
# @see Animation
|
11
|
+
#
|
12
|
+
# A animation is stored in the properties as a hash representation and is
|
13
|
+
# converted into an Animation when it is retrieved within the system.
|
14
|
+
#
|
15
|
+
# The animate images are cached within the animation property to help
|
16
|
+
# performance by reducing the unncessary creation of similar animations.
|
17
|
+
#
|
18
|
+
# @example Defining an animation property (will default to the missing animation)
|
19
|
+
#
|
20
|
+
# class Scoreboard < Metro::Model
|
21
|
+
# property :animation
|
22
|
+
#
|
23
|
+
# def draw
|
24
|
+
# animation.image.draw text, x, y, z_order, x_factor, y_factor, color
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# @example Defining an animation default.
|
29
|
+
#
|
30
|
+
# class Hero < Metro::Model
|
31
|
+
# property :animation, default: { path: "star.png",
|
32
|
+
# dimensions: Metro::Dimensions.of(25,25) }
|
33
|
+
#
|
34
|
+
# def draw
|
35
|
+
# animation.image.draw text, x, y, z_order, x_factor, y_factor, color
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# @example Using an animation property with a different property name
|
40
|
+
#
|
41
|
+
# class Hero < Metro::Model
|
42
|
+
# property :walking, type: :animation, default: { path: "star.png",
|
43
|
+
# dimensions: Metro::Dimensions.of(25,25) }
|
44
|
+
#
|
45
|
+
# def draw
|
46
|
+
# walking.image.draw text, x, y, z_order, x_factor, y_factor, color
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
class AnimationProperty < Property
|
51
|
+
|
52
|
+
# By default return the default animation when getting a nil or
|
53
|
+
# other unsupported value.
|
54
|
+
get do
|
55
|
+
default_animation
|
56
|
+
end
|
57
|
+
|
58
|
+
# When getting a hash, create the animation with the properties.
|
59
|
+
get Hash do |value|
|
60
|
+
self.class.animation_for value.merge(window: model.window)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Setting the animation with a nil or other unsupported value
|
64
|
+
# will default to the default animation.
|
65
|
+
set do
|
66
|
+
default_animation.to_hash
|
67
|
+
end
|
68
|
+
|
69
|
+
# Setting with an animation will convert it to it's hash representation.
|
70
|
+
set Animation do |image|
|
71
|
+
image.to_hash
|
72
|
+
end
|
73
|
+
|
74
|
+
# Setting with a hash will assume the hash defines an animation.
|
75
|
+
set Hash do |value|
|
76
|
+
value
|
77
|
+
end
|
78
|
+
|
79
|
+
def default_animation
|
80
|
+
self.class.animation_for window: model.window,
|
81
|
+
path: default_image_path,
|
82
|
+
width: default_dimensions.width,
|
83
|
+
height: default_dimensions.height,
|
84
|
+
tileable: false
|
85
|
+
end
|
86
|
+
|
87
|
+
def default_image_path
|
88
|
+
if options[:default] and options[:default][:path]
|
89
|
+
asset_path(options[:default][:path])
|
90
|
+
else
|
91
|
+
metro_asset_path("missing_animation.png")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def default_dimensions
|
96
|
+
if options[:default] and options[:default][:dimensions]
|
97
|
+
options[:default][:dimensions]
|
98
|
+
else
|
99
|
+
Dimensions.of 16.0, 16.0
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# Return an animation for the specified path. On first request it will be loaded from
|
105
|
+
# the file-system. On subsequent requests it will be pulled from the cache.
|
106
|
+
#
|
107
|
+
# @param [Hash] options the relative `path` to the image and the window for which it
|
108
|
+
# will be displayed.
|
109
|
+
#
|
110
|
+
def self.animation_for(options)
|
111
|
+
options.symbolize_keys!
|
112
|
+
window = options[:window]
|
113
|
+
|
114
|
+
absolute_path = path = options[:path]
|
115
|
+
absolute_path = asset_path(absolute_path) unless absolute_path.start_with? "/"
|
116
|
+
|
117
|
+
width = options[:width].to_i
|
118
|
+
height = options[:height].to_i
|
119
|
+
tileable = options[:tileable]
|
120
|
+
|
121
|
+
animation_images = images[path]
|
122
|
+
unless animation_images
|
123
|
+
animation_images = create_image(window,absolute_path,width,height,tileable)
|
124
|
+
images[path] = animation_images
|
125
|
+
end
|
126
|
+
|
127
|
+
Animation.new options.merge(images: animation_images)
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.images
|
131
|
+
@images ||= {}
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def self.create_image(window,path,width,height,tileable)
|
137
|
+
Gosu::Image.load_tiles(window,path,width,height,tileable)
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Metro
|
2
|
+
class Model
|
3
|
+
|
4
|
+
#
|
5
|
+
# A color property maintains a Gosu::Color.
|
6
|
+
#
|
7
|
+
# A color property also defines an alpha property which allows a more direct interface
|
8
|
+
# to setting the alpha property on the color. This is useful in cases for images where
|
9
|
+
# the color remains as white but the alpha value needs to be adjusted.
|
10
|
+
#
|
11
|
+
# A color is stored in the properties as a string representation and is converted into
|
12
|
+
# a Gosu::Color when it is retrieved within the system.
|
13
|
+
#
|
14
|
+
# @example Defining a color property using the color properties default
|
15
|
+
#
|
16
|
+
# class Hero < Metro::Model
|
17
|
+
# property :color
|
18
|
+
#
|
19
|
+
# def draw
|
20
|
+
# image.draw x, y, z_order, x_factor, y_factor, color, :add)
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# @example Defining a color property providing a default
|
26
|
+
#
|
27
|
+
# class Hero < Metro::Model
|
28
|
+
# property :color, default: "rgba(255,0,0,1.0)"
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# @example Using the alpha property
|
32
|
+
#
|
33
|
+
# class Hero < Metro::Model
|
34
|
+
# property :color, default: "rgba(255,0,0,1.0)"
|
35
|
+
#
|
36
|
+
# def become_ghost!
|
37
|
+
# self.alpha = 127
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# @example Using a color property with a different property name
|
42
|
+
#
|
43
|
+
# class Hero < Metro::Model
|
44
|
+
# property :color
|
45
|
+
# property :invincible_color, type: :color, default: "rgba(255,0,255,1.0)"
|
46
|
+
#
|
47
|
+
# def draw
|
48
|
+
# if invincible?
|
49
|
+
# image.draw x, y, z_order, x_factor, y_factor, invincible_color, :add)
|
50
|
+
# else
|
51
|
+
# image.draw x, y, z_order, x_factor, y_factor, color, :add)
|
52
|
+
# end
|
53
|
+
# end
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
class ColorProperty < Property
|
57
|
+
|
58
|
+
define_property :alpha
|
59
|
+
|
60
|
+
# By default convert the value to the default color if it
|
61
|
+
# cannot be processed by the other get filters.
|
62
|
+
get do |value|
|
63
|
+
default_color
|
64
|
+
end
|
65
|
+
|
66
|
+
# A color should remain a color.
|
67
|
+
get Gosu::Color do |value|
|
68
|
+
value
|
69
|
+
end
|
70
|
+
|
71
|
+
# A string representation of a color will be converted to a color.
|
72
|
+
# If Gosu::Color does not support the format, then it will default to white.
|
73
|
+
get String do |value|
|
74
|
+
create_color value
|
75
|
+
end
|
76
|
+
|
77
|
+
# By default save the default color string.
|
78
|
+
set do |value|
|
79
|
+
default_color_string
|
80
|
+
end
|
81
|
+
|
82
|
+
# When given a string assume that it is a string representation of color.
|
83
|
+
set String do |value|
|
84
|
+
value
|
85
|
+
end
|
86
|
+
|
87
|
+
# When given a color, convert it into the string representation.
|
88
|
+
set Gosu::Color do |value|
|
89
|
+
value.to_s
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# @return the default color of the color property. This can be set during initialization
|
94
|
+
# by usign the option `default`.
|
95
|
+
#
|
96
|
+
def default_color
|
97
|
+
create_color(default_color_string)
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def default_color_string
|
103
|
+
options[:default] || "rgba(255,255,255,1.0)"
|
104
|
+
end
|
105
|
+
|
106
|
+
def create_color(value)
|
107
|
+
Gosu::Color.new value
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|