metro 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
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