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.
Files changed (63) hide show
  1. data/README.md +19 -0
  2. data/changelog.md +8 -0
  3. data/lib/assets/missing_animation.png +0 -0
  4. data/lib/commands/generate_model.rb +2 -2
  5. data/lib/commands/generate_scene.rb +12 -2
  6. data/lib/commands/generate_view.rb +1 -1
  7. data/lib/gosu_ext/color.rb +1 -1
  8. data/lib/gosu_ext/image.rb +5 -0
  9. data/lib/metro.rb +18 -5
  10. data/lib/metro/animation/animation.rb +31 -0
  11. data/lib/metro/asset_path.rb +9 -0
  12. data/lib/metro/events/event_dictionary.rb +53 -0
  13. data/lib/metro/events/event_factory.rb +5 -3
  14. data/lib/metro/events/has_events.rb +5 -6
  15. data/lib/metro/game.rb +1 -1
  16. data/lib/metro/models/dimensions.rb +21 -0
  17. data/lib/metro/models/model.rb +149 -52
  18. data/lib/metro/models/model_factory.rb +4 -5
  19. data/lib/metro/models/{generic.rb → models/generic.rb} +0 -0
  20. data/lib/metro/models/{grid_drawer.rb → models/grid_drawer.rb} +4 -9
  21. data/lib/metro/models/{image.rb → models/image.rb} +11 -14
  22. data/lib/metro/models/models/label.rb +44 -0
  23. data/lib/metro/models/{menu.rb → models/menu.rb} +23 -18
  24. data/lib/metro/models/{rectangle.rb → models/rectangle.rb} +6 -5
  25. data/lib/metro/models/point.rb +23 -0
  26. data/lib/metro/models/properties/angle.rb +43 -0
  27. data/lib/metro/models/properties/animation.rb +143 -0
  28. data/lib/metro/models/properties/color.rb +113 -0
  29. data/lib/metro/models/properties/dimensions.rb +66 -0
  30. data/lib/metro/models/properties/font.rb +155 -0
  31. data/lib/metro/models/properties/image.rb +101 -0
  32. data/lib/metro/models/properties/numeric.rb +29 -0
  33. data/lib/metro/models/properties/position.rb +84 -0
  34. data/lib/metro/models/properties/property.rb +111 -0
  35. data/lib/metro/models/properties/scale.rb +89 -0
  36. data/lib/metro/models/properties/text.rb +66 -0
  37. data/lib/metro/models/properties/velocity.rb +80 -0
  38. data/lib/metro/models/scale.rb +21 -0
  39. data/lib/metro/scene.rb +19 -1
  40. data/lib/metro/scenes.rb +91 -31
  41. data/lib/metro/transitions/scene_transitions.rb +8 -0
  42. data/lib/metro/version.rb +1 -1
  43. data/lib/metro/views/view.rb +9 -1
  44. data/lib/templates/game/metro.tt +1 -1
  45. data/lib/templates/game/models/game_model.rb +3 -0
  46. data/lib/templates/game/scenes/brand_scene.rb +1 -1
  47. data/lib/templates/game/scenes/brand_to_title_scene.rb +1 -1
  48. data/lib/templates/game/scenes/game_scene.rb +19 -0
  49. data/lib/templates/game/scenes/title_scene.rb +1 -1
  50. data/lib/templates/game/views/brand_to_title.yaml +2 -2
  51. data/lib/templates/game/views/title.yaml +3 -3
  52. data/lib/templates/{model.rb.erb → model.rb.tt} +1 -1
  53. data/lib/templates/{scene.rb.erb → scene.rb.tt} +1 -1
  54. data/lib/templates/view.yaml.tt +6 -0
  55. data/spec/metro/models/models/label_spec.rb +110 -0
  56. data/spec/metro/models/properties/color_spec.rb +85 -0
  57. data/spec/metro/models/properties/font_spec.rb +129 -0
  58. data/spec/metro/models/properties/numeric_property_spec.rb +46 -0
  59. data/spec/metro/models/properties/position_property_spec.rb +90 -0
  60. data/spec/metro/scenes_spec.rb +77 -0
  61. metadata +50 -16
  62. data/lib/metro/models/label.rb +0 -63
  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
- contents = {} unless contents
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.merge(contents)
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(contents = {})
24
- contents['model'] || contents[:model] || options['model'] || options[:model] || name
22
+ def model_name
23
+ options['model'] || options[:model] || name
25
24
  end
26
25
 
27
26
  def class_for_actor(model_name)
@@ -3,16 +3,15 @@ module Metro
3
3
 
4
4
  class GridDrawer < Model
5
5
 
6
- attr_writer :color, :spacing, :height, :width
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
- attr_accessor :x, :y, :angle, :center_x, :center_y, :x_factor, :y_factor, :z_order
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
- def image
25
- @image ||= Gosu::Image.new(window,asset_path(path))
26
- end
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 = color
100
- draw_color = highlight_color if index == selected_index
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, 1.0, 1.0, draw_color
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
- attr_accessor :x, :y, :z_order, :width, :height
6
+ property :position
7
7
 
8
- def after_initialize
9
- @x = @y = 0
10
- @z_order = 1
11
- end
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