metro 0.1.2 → 0.1.3

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 (49) hide show
  1. data/README.md +29 -13
  2. data/changelog.md +10 -0
  3. data/lib/core_ext/numeric.rb +59 -0
  4. data/lib/gosu_ext/gosu_constants.rb +53 -0
  5. data/lib/locale/en.yml +16 -0
  6. data/lib/locale/locale.rb +1 -0
  7. data/lib/metro.rb +30 -16
  8. data/lib/metro/animation/after_interval_factory.rb +12 -0
  9. data/lib/metro/animation/animation_factory.rb +3 -2
  10. data/lib/metro/animation/has_animations.rb +3 -3
  11. data/lib/metro/animation/implicit_animation.rb +33 -19
  12. data/lib/metro/animation/{animation.rb → on_update_operation.rb} +6 -4
  13. data/lib/metro/animation/scene_animation.rb +16 -0
  14. data/lib/metro/events/control_definition.rb +11 -0
  15. data/lib/metro/events/controls.rb +42 -0
  16. data/lib/metro/events/event_relay.rb +49 -11
  17. data/lib/metro/events/has_events.rb +6 -5
  18. data/lib/metro/game.rb +17 -11
  19. data/lib/metro/game/dsl.rb +8 -0
  20. data/lib/metro/models/image.rb +3 -1
  21. data/lib/metro/models/key_value_coding.rb +38 -0
  22. data/lib/metro/models/label.rb +18 -3
  23. data/lib/metro/models/menu.rb +6 -5
  24. data/lib/metro/models/model.rb +11 -4
  25. data/lib/metro/models/rectangle.rb +28 -0
  26. data/lib/metro/scene.rb +76 -15
  27. data/lib/metro/scene_view/yaml_view.rb +11 -4
  28. data/lib/metro/scenes.rb +27 -3
  29. data/lib/metro/template_message.rb +33 -4
  30. data/lib/metro/transitions/fade_transition_scene.rb +59 -0
  31. data/lib/metro/transitions/scene_transitions.rb +30 -0
  32. data/lib/metro/transitions/transition_scene.rb +18 -0
  33. data/lib/metro/version.rb +1 -1
  34. data/lib/metro/window.rb +0 -2
  35. data/lib/templates/game/metro.tt +13 -0
  36. data/lib/templates/game/scenes/brand_scene.rb +10 -4
  37. data/lib/templates/game/scenes/brand_to_title_scene.rb +3 -3
  38. data/lib/templates/game/scenes/title_scene.rb +1 -1
  39. data/lib/templates/game/views/brand_to_title.yaml +2 -4
  40. data/lib/templates/game/views/title.yaml +2 -4
  41. data/lib/templates/message.erb +1 -1
  42. data/lib/templates/model.rb.erb +2 -2
  43. data/lib/templates/scene.rb.erb +3 -3
  44. data/metro.gemspec +1 -0
  45. data/spec/core_ext/numeric_spec.rb +78 -0
  46. data/spec/metro/models/key_value_coding_spec.rb +61 -0
  47. data/spec/metro/scene_views/yaml_view_spec.rb +38 -0
  48. metadata +44 -6
  49. data/lib/metro/error.rb +0 -21
@@ -0,0 +1,16 @@
1
+ require_relative 'on_update_operation'
2
+
3
+ module Metro
4
+
5
+ module SceneAnimation
6
+ extend self
7
+
8
+ def build(options,&block)
9
+ animation = Metro::ImplicitAnimation.new options
10
+ animation.on_complete(&block) if block
11
+ animation
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,11 @@
1
+ module Metro
2
+ class ControlDefinition
3
+ attr_accessor :name, :event, :args
4
+
5
+ def initialize(name,event,args)
6
+ @name = name
7
+ @event = event
8
+ @args = args
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,42 @@
1
+ require_relative 'control_definition'
2
+
3
+ module Metro
4
+ #
5
+ # Assists in creating and the storing of ControlDefinitions.
6
+ #
7
+ # @see DSL
8
+ #
9
+ class Controls
10
+
11
+ #
12
+ # Creation through controls is usually done with an instance_eval
13
+ # of a block and this allows for a flexible interface.
14
+ #
15
+ # @param [String,Symbol] name the name or the alias of the control
16
+ # as it will be used within the course of the game.
17
+ #
18
+ def method_missing(name,*params,&block)
19
+ options = params.find {|param| param.is_a? Hash }
20
+ define_control(name,options)
21
+ end
22
+
23
+ def define_control(name,options)
24
+ event = _event_type(options)
25
+ args = _event_args(options)
26
+
27
+ defined_controls.push ControlDefinition.new name, event, args
28
+ end
29
+
30
+ def _event_type(options)
31
+ options[:is]
32
+ end
33
+
34
+ def _event_args(options)
35
+ options[:with]
36
+ end
37
+
38
+ def defined_controls
39
+ @defined_controls ||= []
40
+ end
41
+ end
42
+ end
@@ -41,6 +41,37 @@ module Metro
41
41
  #
42
42
  class EventRelay
43
43
 
44
+ #
45
+ # Defines the provided controls for every EventRelay that is created.
46
+ #
47
+ # @see #define_control
48
+ #
49
+ # @param [Array<ControlDefinition>] controls the definitions of controls
50
+ # that should be added to all EventRelays.
51
+ #
52
+ def self.define_controls(controls)
53
+ controls.each { |control| define_control control }
54
+ end
55
+
56
+ #
57
+ # Defines a control from a ControlDefinition for all EventRelays. A
58
+ # control is a way of defining a shortcut for a common event. This
59
+ # could be the use of a common set of keys for confirmation or canceling.
60
+ #
61
+ def self.define_control(control)
62
+ check_for_already_defined_control!(control)
63
+
64
+ define_method control.name do |&block|
65
+ send(control.event,*control.args,&block)
66
+ end
67
+ end
68
+
69
+ def self.check_for_already_defined_control!(control)
70
+ if instance_methods.include? control.name
71
+ error "error.reserved_control_name", name: control.name
72
+ end
73
+ end
74
+
44
75
  #
45
76
  # An event relay is created a with a target and optionally a window.
46
77
  #
@@ -69,7 +100,7 @@ module Metro
69
100
  # @example Registering for a button down event to call a method named 'previous_option'
70
101
  #
71
102
  # class ExampleScene
72
- # event :on_down, Gosu::GpLeft, Gosu::GpUp, do: :previous_option
103
+ # event :on_down, GpLeft, GpUp, do: :previous_option
73
104
  #
74
105
  # def previous_option
75
106
  # @selected_index = @selected_index - 1
@@ -84,7 +115,7 @@ module Metro
84
115
  # @example Registering for a button down event with a block of code to execute
85
116
  #
86
117
  # class ExampleScene
87
- # event :on_down, Gosu::GpLeft, Gosu::GpUp do
118
+ # event :on_down, GpLeft, GpUp do
88
119
  # @selected_index = @selected_index - 1
89
120
  # @selected_index = options.length - 1 if @selected_index <= -1
90
121
  # end
@@ -97,6 +128,8 @@ module Metro
97
128
  _on(@down_actions,args,block)
98
129
  end
99
130
 
131
+ alias_method :button_down, :on_down
132
+
100
133
  #
101
134
  # Register for a button_up event. These events are fired when
102
135
  # the button is released (from being pressed down). This event only fires
@@ -105,7 +138,7 @@ module Metro
105
138
  # @example Registering for a button down event to call a method named 'next_option'
106
139
  #
107
140
  # class ExampleScene
108
- # event :on_up, Gosu::KbEscape, do: :leave_scene
141
+ # event :on_up, KbEscape, do: :leave_scene
109
142
  #
110
143
  # def leave_scene
111
144
  # transition_to :title
@@ -118,7 +151,7 @@ module Metro
118
151
  # @example Registering for a button up event with a block of code to execute
119
152
  #
120
153
  # class ExampleScene
121
- # event :on_up, Gosu::KbEscape do
154
+ # event :on_up, KbEscape do
122
155
  # transition_to :title
123
156
  # end
124
157
  # end
@@ -130,6 +163,8 @@ module Metro
130
163
  _on(@up_actions,args,block)
131
164
  end
132
165
 
166
+ alias_method :button_up, :on_up
167
+
133
168
  #
134
169
  # Register for a button_held event. These events are fired when
135
170
  # the button is currently in the downstate. This event continues to fire at the
@@ -140,15 +175,15 @@ module Metro
140
175
  # @example Registering for button held events
141
176
  #
142
177
  # class ExampleScene
143
- # event :on_hold Gosu::KbLeft, Gosu::GpLeft do
178
+ # event :on_hold KbLeft, GpLeft do
144
179
  # player.turn_left
145
180
  # end
146
181
  #
147
- # event :on_hold, Gosu::KbRight, Gosu::GpRight do
182
+ # event :on_hold, KbRight, GpRight do
148
183
  # player.turn_right
149
184
  # end
150
185
  #
151
- # event :on_hold, Gosu::KbUp, Gosu::GpButton0, do: :calculate_accleration
186
+ # event :on_hold, KbUp, Gosu::GpButton0, do: :calculate_accleration
152
187
  #
153
188
  # def calculate_acceleration
154
189
  # long_complicated_calculated_result = 0
@@ -162,6 +197,9 @@ module Metro
162
197
  _on(@held_actions,args,block)
163
198
  end
164
199
 
200
+ alias_method :button_hold, :on_hold
201
+ alias_method :button_held, :on_hold
202
+
165
203
  #
166
204
  # Register for a custom notification event. These events are fired when
167
205
  # another object within the game posts a notification with matching criteria.
@@ -214,7 +252,7 @@ module Metro
214
252
  # This is called by external or parent source of events, usually a Scene, when a button up event
215
253
  # has been triggered.
216
254
  #
217
- def button_up(id)
255
+ def fire_button_up(id)
218
256
  target.instance_eval( &up_action(id) )
219
257
  end
220
258
 
@@ -222,7 +260,7 @@ module Metro
222
260
  # This is called by external or parent source of events, usually a Scene, when a button down
223
261
  # event has been triggered.
224
262
  #
225
- def button_down(id)
263
+ def fire_button_down(id)
226
264
  target.instance_eval( &down_action(id) )
227
265
  end
228
266
 
@@ -265,10 +303,10 @@ module Metro
265
303
  # An action without any parameters is assumed to be executed within the contexxt
266
304
  # of the target. If there are two parameters we will simply execute the action and
267
305
  # pass it both the target and the sender.
268
- #
306
+ #
269
307
  # @TODO: Allow for the blocks to be specified with one parameter: source (and executed
270
308
  # within the context of the target)
271
- #
309
+ #
272
310
  # @TODO: Allow for the blocks to be specified with three parameters: source, target, event
273
311
  #
274
312
  def _fire_event_for_notification(event,sender,action)
@@ -6,6 +6,7 @@ module Metro
6
6
 
7
7
  def self.included(base)
8
8
  base.extend ClassMethods
9
+ base.extend GosuConstants
9
10
  end
10
11
 
11
12
  module ClassMethods
@@ -24,15 +25,15 @@ module Metro
24
25
  # @example Registering for button held events
25
26
  #
26
27
  # class ExampleScene
27
- # event :on_hold Gosu::KbLeft, Gosu::GpLeft do
28
+ # event :on_hold KbLeft, Gosu::GpLeft do
28
29
  # player.turn_left
29
30
  # end
30
31
  #
31
- # event :on_hold, Gosu::KbRight, Gosu::GpRight do
32
+ # event :on_hold, KbRight, Gosu::GpRight do
32
33
  # player.turn_right
33
34
  # end
34
35
  #
35
- # event :on_hold, Gosu::KbUp, Gosu::GpButton0, do: :calculate_accleration
36
+ # event :on_hold, KbUp, Gosu::GpButton0, do: :calculate_accleration
36
37
  #
37
38
  # def calculate_acceleration
38
39
  # long_complicated_calculated_result = 0
@@ -44,7 +45,7 @@ module Metro
44
45
  # @example Registering for a button down event to call a method named 'next_option'
45
46
  #
46
47
  # class ExampleScene
47
- # event :on_up, Gosu::KbEscape, do: :leave_scene
48
+ # event :on_up, KbEscape, do: :leave_scene
48
49
  #
49
50
  # def leave_scene
50
51
  # transition_to :title
@@ -57,7 +58,7 @@ module Metro
57
58
  # @example Registering for a button up event with a block of code to execute
58
59
  #
59
60
  # class ExampleScene
60
- # event :on_up, Gosu::KbEscape do
61
+ # event :on_up, KbEscape do
61
62
  # transition_to :title
62
63
  # end
63
64
  # end
data/lib/metro/game.rb CHANGED
@@ -11,15 +11,15 @@ module Metro
11
11
  attr_reader :config
12
12
 
13
13
  def first_scene
14
- config.first_scene
14
+ fetch(:first_scene)
15
15
  end
16
16
 
17
17
  def width
18
- config.width || 640
18
+ fetch(:width,640)
19
19
  end
20
20
 
21
21
  def height
22
- config.height || 480
22
+ fetch(:height,480)
23
23
  end
24
24
 
25
25
  def dimensions
@@ -31,31 +31,37 @@ module Metro
31
31
  end
32
32
 
33
33
  def fullscreen?
34
- !!config.fullscreen
34
+ !!fetch(:fullscreen)
35
35
  end
36
36
 
37
37
  def debug?
38
- !!config.debug
38
+ !!fetch(:debug)
39
39
  end
40
40
 
41
41
  def name
42
- config.name
42
+ fetch(:name)
43
43
  end
44
44
 
45
45
  def authors
46
- config.authors
46
+ fetch(:authors)
47
47
  end
48
48
 
49
49
  def website
50
- config.website
50
+ fetch(:website,Metro::WEBSITE)
51
51
  end
52
52
 
53
53
  def contact
54
- config.contact
54
+ fetch(:contact)
55
+ end
56
+
57
+ def controls
58
+ config.controls.defined_controls
59
+ end
60
+
61
+ def fetch(name,fallback = nil)
62
+ config.send(name) rescue fallback
55
63
  end
56
64
 
57
- # TODO: ZOrder related constants that belong to Starry Knight
58
- Background, Stars, Players, UI = *0..3
59
65
 
60
66
  end
61
67
  end
@@ -1,3 +1,5 @@
1
+ require_relative '../events/controls'
2
+
1
3
  module Metro
2
4
  module Game
3
5
  class DSL
@@ -55,6 +57,12 @@ module Metro
55
57
  game_contact ? @contact = game_contact : @contact
56
58
  end
57
59
 
60
+ def controls(&block)
61
+ @controls ||= Controls.new
62
+ @controls.instance_eval(&block) if block
63
+ @controls
64
+ end
65
+
58
66
  end
59
67
  end
60
68
  end
@@ -9,7 +9,7 @@ module Metro
9
9
  #
10
10
  class Image < Model
11
11
 
12
- attr_accessor :angle, :center_x, :center_y, :x_factor, :y_factor, :z_order
12
+ attr_accessor :x, :y, :angle, :center_x, :center_y, :x_factor, :y_factor, :z_order
13
13
 
14
14
  def after_initialize
15
15
  @angle = 0
@@ -17,6 +17,8 @@ module Metro
17
17
  @x_factor = @y_factor = 1
18
18
  @z_order = 0
19
19
  @color = Gosu::Color.new "rgba(255,255,255,1.0)"
20
+ @x = Game.width / 2
21
+ @y = Game.height / 2
20
22
  end
21
23
 
22
24
  def image
@@ -0,0 +1,38 @@
1
+ module Metro
2
+
3
+ #
4
+ # Key-Value coding emulates the functionality found in Objective-C, which allows
5
+ # for an object to be sent a message which contains the method to return. This is
6
+ # the same as Ruby. However, Objective-C also supports the use of the dot notation
7
+ # within the keys to acces the sub-values.
8
+ #
9
+ # @example Setting the red value of the color on a Model.
10
+ #
11
+ # class Elf
12
+ # include KeyValueCoding
13
+ #
14
+ # attr_accessor :color
15
+ # end
16
+ #
17
+ # elf = Elf.new
18
+ # elf.color = Gosu::Color.new "rgb(0,0,0)"
19
+ #
20
+ # elf.get("color.red") # => 0
21
+ # elf.set("color.red",255)
22
+ # elf.get("color.red") # => 255
23
+ #
24
+ module KeyValueCoding
25
+
26
+ def set(name,value)
27
+ keys = name.to_s.split('.')
28
+ key_to_set = keys[0..-2].inject(self) {|target,method| target.send(method) }
29
+ key_to_set.send("#{keys.last}=",value)
30
+ end
31
+
32
+ def get(name)
33
+ keys = name.to_s.split('.')
34
+ keys.inject(self) {|target,method| target.send(method) }
35
+ end
36
+ end
37
+
38
+ end
@@ -10,20 +10,35 @@ module Metro
10
10
  class Label < Model
11
11
 
12
12
  attr_accessor :x, :y, :x_factor, :y_factor, :z_order
13
+ attr_accessor :size, :size, :font_family
13
14
 
14
15
  def after_initialize
15
16
  @text = ""
16
17
  @x_factor = @y_factor = 1.0
17
18
  @z_order = 0
18
19
  @color = Gosu::Color.new "rgba(255,255,255,1.0)"
20
+ @size = 20
21
+ @font_family = Gosu::default_font_name
19
22
  end
20
-
23
+
21
24
  def font
22
- @font ||= Gosu::Font.new(window, Gosu::default_font_name, 20)
25
+ @font ||= Gosu::Font.new(window, font_family, size)
26
+ end
27
+
28
+ def x
29
+ @x || (Game.width/2 - font.text_width(text)/2)
30
+ end
31
+
32
+ def y
33
+ @y || (Game.height/2 - font.height/2)
34
+ end
35
+
36
+ def text
37
+ scene.instance_eval( "\"#{@text}\"" )
23
38
  end
24
39
 
25
40
  def draw
26
- label_text = scene.instance_eval( "\"#{text}\"" )
41
+ label_text = text
27
42
  font.draw label_text, x, y, z_order, x_factor, y_factor, color
28
43
  end
29
44