metro-ld25 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (177) hide show
  1. data/.gitignore +17 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +12 -0
  6. data/Guardfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +189 -0
  9. data/Rakefile +18 -0
  10. data/bin/metro +16 -0
  11. data/changelog.md +157 -0
  12. data/lib/assets/menu-movement.wav +0 -0
  13. data/lib/assets/menu-selection.wav +0 -0
  14. data/lib/assets/missing.ogg +0 -0
  15. data/lib/assets/missing.png +0 -0
  16. data/lib/assets/missing.wav +0 -0
  17. data/lib/assets/missing_animation.png +0 -0
  18. data/lib/commands/generate_game.rb +13 -0
  19. data/lib/commands/generate_model.rb +25 -0
  20. data/lib/commands/generate_scene.rb +36 -0
  21. data/lib/commands/generate_view.rb +21 -0
  22. data/lib/commands/thor.rb +83 -0
  23. data/lib/core_ext/class.rb +14 -0
  24. data/lib/core_ext/numeric.rb +59 -0
  25. data/lib/gosu_ext/color.rb +62 -0
  26. data/lib/gosu_ext/gosu_constants.rb +53 -0
  27. data/lib/locale/en.yml +35 -0
  28. data/lib/locale/locale.rb +1 -0
  29. data/lib/metro.rb +140 -0
  30. data/lib/metro/animation.rb +135 -0
  31. data/lib/metro/animation/after_interval_factory.rb +12 -0
  32. data/lib/metro/animation/animation_factory.rb +15 -0
  33. data/lib/metro/animation/easing/ease_in.rb +15 -0
  34. data/lib/metro/animation/easing/easing.rb +51 -0
  35. data/lib/metro/animation/easing/linear.rb +15 -0
  36. data/lib/metro/animation/has_animations.rb +70 -0
  37. data/lib/metro/animation/implicit_animation.rb +100 -0
  38. data/lib/metro/animation/on_update_operation.rb +96 -0
  39. data/lib/metro/animation/scene_animation.rb +16 -0
  40. data/lib/metro/asset_path.rb +97 -0
  41. data/lib/metro/events/control_definition.rb +11 -0
  42. data/lib/metro/events/controls.rb +42 -0
  43. data/lib/metro/events/event_data.rb +60 -0
  44. data/lib/metro/events/event_dictionary.rb +52 -0
  45. data/lib/metro/events/event_factory.rb +17 -0
  46. data/lib/metro/events/event_relay.rb +300 -0
  47. data/lib/metro/events/event_state_manager.rb +63 -0
  48. data/lib/metro/events/events.rb +3 -0
  49. data/lib/metro/events/has_events.rb +108 -0
  50. data/lib/metro/events/hit_list.rb +75 -0
  51. data/lib/metro/events/unknown_sender.rb +5 -0
  52. data/lib/metro/font.rb +69 -0
  53. data/lib/metro/game.rb +102 -0
  54. data/lib/metro/game/dsl.rb +68 -0
  55. data/lib/metro/image.rb +68 -0
  56. data/lib/metro/logging.rb +33 -0
  57. data/lib/metro/missing_scene.rb +21 -0
  58. data/lib/metro/models/audio/song.rb +33 -0
  59. data/lib/metro/models/draws.rb +86 -0
  60. data/lib/metro/models/key_value_coding.rb +38 -0
  61. data/lib/metro/models/model.rb +236 -0
  62. data/lib/metro/models/model_factory.rb +32 -0
  63. data/lib/metro/models/models.rb +62 -0
  64. data/lib/metro/models/properties/animation_property.rb +115 -0
  65. data/lib/metro/models/properties/array_property.rb +24 -0
  66. data/lib/metro/models/properties/boolean_property.rb +27 -0
  67. data/lib/metro/models/properties/color_property.rb +116 -0
  68. data/lib/metro/models/properties/dimensions_property.rb +84 -0
  69. data/lib/metro/models/properties/font_property.rb +130 -0
  70. data/lib/metro/models/properties/image_property.rb +96 -0
  71. data/lib/metro/models/properties/model_property.rb +84 -0
  72. data/lib/metro/models/properties/numeric_property.rb +29 -0
  73. data/lib/metro/models/properties/options_property/no_option.rb +29 -0
  74. data/lib/metro/models/properties/options_property/options.rb +94 -0
  75. data/lib/metro/models/properties/options_property/options_property.rb +125 -0
  76. data/lib/metro/models/properties/position_property.rb +90 -0
  77. data/lib/metro/models/properties/property.rb +221 -0
  78. data/lib/metro/models/properties/property_owner.rb +137 -0
  79. data/lib/metro/models/properties/sample_property.rb +84 -0
  80. data/lib/metro/models/properties/scale_property.rb +80 -0
  81. data/lib/metro/models/properties/song_property.rb +89 -0
  82. data/lib/metro/models/properties/text_property.rb +75 -0
  83. data/lib/metro/models/ui/animated_sprite.rb +85 -0
  84. data/lib/metro/models/ui/border.rb +95 -0
  85. data/lib/metro/models/ui/fps.rb +54 -0
  86. data/lib/metro/models/ui/generic.rb +66 -0
  87. data/lib/metro/models/ui/grid_drawer.rb +74 -0
  88. data/lib/metro/models/ui/image.rb +87 -0
  89. data/lib/metro/models/ui/label.rb +175 -0
  90. data/lib/metro/models/ui/menu.rb +214 -0
  91. data/lib/metro/models/ui/model_label.rb +65 -0
  92. data/lib/metro/models/ui/model_labeler.rb +79 -0
  93. data/lib/metro/models/ui/rectangle.rb +59 -0
  94. data/lib/metro/models/ui/sprite.rb +79 -0
  95. data/lib/metro/models/ui/tile_map.rb +162 -0
  96. data/lib/metro/models/ui/ui.rb +13 -0
  97. data/lib/metro/parameters/command_line_args_parser.rb +68 -0
  98. data/lib/metro/parameters/options.rb +25 -0
  99. data/lib/metro/parameters/parameters.rb +2 -0
  100. data/lib/metro/sample.rb +40 -0
  101. data/lib/metro/scene.rb +477 -0
  102. data/lib/metro/scenes.rb +154 -0
  103. data/lib/metro/song.rb +56 -0
  104. data/lib/metro/template_message.rb +60 -0
  105. data/lib/metro/transitions/edit_transition_scene.rb +100 -0
  106. data/lib/metro/transitions/fade_transition_scene.rb +66 -0
  107. data/lib/metro/transitions/scene_transitions.rb +44 -0
  108. data/lib/metro/transitions/transition_scene.rb +19 -0
  109. data/lib/metro/units/bounds.rb +8 -0
  110. data/lib/metro/units/calculation_validations.rb +74 -0
  111. data/lib/metro/units/dimensions.rb +60 -0
  112. data/lib/metro/units/point.rb +51 -0
  113. data/lib/metro/units/rectangle_bounds.rb +85 -0
  114. data/lib/metro/units/scale.rb +46 -0
  115. data/lib/metro/units/units.rb +6 -0
  116. data/lib/metro/version.rb +32 -0
  117. data/lib/metro/views/json_view.rb +60 -0
  118. data/lib/metro/views/no_view.rb +34 -0
  119. data/lib/metro/views/parsers.rb +42 -0
  120. data/lib/metro/views/scene_view.rb +107 -0
  121. data/lib/metro/views/view.rb +133 -0
  122. data/lib/metro/views/writers.rb +43 -0
  123. data/lib/metro/views/yaml_view.rb +94 -0
  124. data/lib/metro/window.rb +94 -0
  125. data/lib/setup_handlers/exit_if_dry_run.rb +26 -0
  126. data/lib/setup_handlers/game_execution.rb +65 -0
  127. data/lib/setup_handlers/load_game_configuration.rb +65 -0
  128. data/lib/setup_handlers/load_game_files.rb +101 -0
  129. data/lib/setup_handlers/move_to_game_directory.rb +25 -0
  130. data/lib/setup_handlers/reload_game_on_game_file_changes.rb +79 -0
  131. data/lib/templates/game/README.md.tt +52 -0
  132. data/lib/templates/game/assets/brand.jpg +0 -0
  133. data/lib/templates/game/assets/hero.png +0 -0
  134. data/lib/templates/game/lib/custom_easing.rb +32 -0
  135. data/lib/templates/game/metro.tt +63 -0
  136. data/lib/templates/game/models/hero.rb +62 -0
  137. data/lib/templates/game/scenes/brand_scene.rb +19 -0
  138. data/lib/templates/game/scenes/brand_to_title_scene.rb +13 -0
  139. data/lib/templates/game/scenes/first_scene.rb +28 -0
  140. data/lib/templates/game/scenes/game_scene.rb +43 -0
  141. data/lib/templates/game/scenes/title_scene.rb +15 -0
  142. data/lib/templates/game/views/brand.yaml +4 -0
  143. data/lib/templates/game/views/brand_to_title.yaml +8 -0
  144. data/lib/templates/game/views/first.yaml +26 -0
  145. data/lib/templates/game/views/title.yaml +11 -0
  146. data/lib/templates/message.erb +23 -0
  147. data/lib/templates/model.rb.tt +111 -0
  148. data/lib/templates/scene.rb.tt +140 -0
  149. data/lib/templates/view.yaml.tt +11 -0
  150. data/lib/tmxed_ext/tile_set.rb +34 -0
  151. data/metro.gemspec +56 -0
  152. data/spec/core_ext/numeric_spec.rb +78 -0
  153. data/spec/core_ext/string_spec.rb +33 -0
  154. data/spec/gosu_ext/color_spec.rb +80 -0
  155. data/spec/metro/events/event_state_manager_spec.rb +5 -0
  156. data/spec/metro/models/key_value_coding_spec.rb +61 -0
  157. data/spec/metro/models/properties/array_property_spec.rb +60 -0
  158. data/spec/metro/models/properties/color_property_spec.rb +85 -0
  159. data/spec/metro/models/properties/dimensions_spec.rb +29 -0
  160. data/spec/metro/models/properties/font_property_spec.rb +127 -0
  161. data/spec/metro/models/properties/numeric_property_spec.rb +46 -0
  162. data/spec/metro/models/properties/options_property/no_option_spec.rb +25 -0
  163. data/spec/metro/models/properties/options_property/options_property_spec.rb +133 -0
  164. data/spec/metro/models/properties/options_property/options_spec.rb +125 -0
  165. data/spec/metro/models/properties/position_property_spec.rb +90 -0
  166. data/spec/metro/models/ui/label_spec.rb +259 -0
  167. data/spec/metro/parameters/command_line_args_parser_spec.rb +42 -0
  168. data/spec/metro/scene_spec.rb +15 -0
  169. data/spec/metro/scene_views/json_view_spec.rb +27 -0
  170. data/spec/metro/scene_views/yaml_view_spec.rb +38 -0
  171. data/spec/metro/scenes_spec.rb +77 -0
  172. data/spec/metro/units/point_spec.rb +132 -0
  173. data/spec/metro/views/view_spec.rb +53 -0
  174. data/spec/setup_handlers/exit_if_dry_run_spec.rb +27 -0
  175. data/spec/setup_handlers/reload_game_on_game_file_changes_spec.rb +68 -0
  176. data/spec/spec_helper.rb +20 -0
  177. metadata +374 -0
@@ -0,0 +1,135 @@
1
+ module Metro
2
+
3
+ #
4
+ # The animation is an wrapper object for an array of Gosu::Images that also contains
5
+ # the additional information on the path, height, width, and tileability.
6
+ #
7
+ class Animation
8
+
9
+ attr_accessor :images, :path, :height, :width, :tileable, :time_per_image
10
+
11
+ def initialize(params = {})
12
+ @images = Array(params[:images])
13
+ @path = params[:path]
14
+ @height = params[:height]
15
+ @width = params[:width]
16
+ @tileable = params[:tileable]
17
+ @time_per_image = params[:time_per_image]
18
+ end
19
+
20
+ #
21
+ # @return a hash representation of the Animation
22
+ #
23
+ def to_hash
24
+ { path: path,
25
+ width: width.to_i, height: height.to_i,
26
+ tileable: !!tileable,
27
+ time_per_image: time_per_image }
28
+ end
29
+
30
+ #
31
+ # @return [Fixnum] the game time when the animation started to display.
32
+ #
33
+ def start_time
34
+ @start_time ||= current_time
35
+ end
36
+
37
+ #
38
+ # @return [Fixnum] the current time in the game.
39
+ #
40
+ def current_time
41
+ Gosu::milliseconds
42
+ end
43
+
44
+ #
45
+ # @return [Fixnum] the age of the animation.
46
+ #
47
+ def age
48
+ current_time - start_time
49
+ end
50
+
51
+ #
52
+ # @return the current animation image count.
53
+ #
54
+ def current_index
55
+ age / time_per_image
56
+ end
57
+
58
+ #
59
+ # @return the current animation image to display.
60
+ #
61
+ def current_image_index
62
+ current_index % images.size
63
+ end
64
+
65
+ #
66
+ # @return the animation is complete if it the current index exceeds the
67
+ # number of images.
68
+ #
69
+ def complete?
70
+ current_index > (images.size - 1)
71
+ end
72
+
73
+ #
74
+ # @return a Gosu::Image to be displayed in a animation sequence.
75
+ #
76
+ def image
77
+ images[current_image_index]
78
+ end
79
+
80
+ #
81
+ # Finds an existing image or creates a new image given the window, path,
82
+ # width, height and tileablilty.
83
+ #
84
+ # @example Finding or creating an Animation image
85
+ #
86
+ # Metro::Animation.find_or_create window: model.window,
87
+ # path: "asset_path", tileable: tileable, width: 64, height: 64,
88
+ # time_per_image: 50
89
+ #
90
+ def self.find_or_create(options)
91
+ new options.merge(images: find_or_create_gosu_images(options))
92
+ end
93
+
94
+ #
95
+ # Create an animation image given the window, path, width, height,
96
+ # and tileability.
97
+ #
98
+ # @example Creating an Animation Image
99
+ #
100
+ # Metro::Animation.create window: model.window,
101
+ # path: "asset_path", tileable: tileable, width: 64, height: 64,
102
+ # time_per_image: 50
103
+ #
104
+ def self.create(options)
105
+ new options.merge(images: create_gosu_images(options))
106
+ end
107
+
108
+ private
109
+
110
+ def self.create_gosu_images(options)
111
+ path = AssetPath.with(options[:path]).to_s
112
+ images[path] = Gosu::Image.load_tiles(*create_params(options))
113
+ end
114
+
115
+ def self.find_or_create_gosu_images(options)
116
+ path = AssetPath.with(options[:path]).to_s
117
+ images[path] or create_gosu_images(options)
118
+ end
119
+
120
+ def self.create_params(options)
121
+ options.symbolize_keys!
122
+ window = options[:window]
123
+ asset_path = AssetPath.with(options[:path]).filepath
124
+ width = options[:width].to_i
125
+ height = options[:height].to_i
126
+ tileable = !!options[:tileable]
127
+ [ window, asset_path, width, height, tileable ]
128
+ end
129
+
130
+ def self.images
131
+ @images ||= {}
132
+ end
133
+
134
+ end
135
+ end
@@ -0,0 +1,12 @@
1
+ module Metro
2
+
3
+ class AfterIntervalFactory
4
+ attr_reader :ticks, :block
5
+
6
+ def initialize(ticks,&block)
7
+ @ticks = ticks
8
+ @block = block
9
+ end
10
+ end
11
+
12
+ end
@@ -0,0 +1,15 @@
1
+ module Metro
2
+
3
+ class AnimationFactory
4
+
5
+ attr_reader :actor, :options, :on_complete_block
6
+
7
+ def initialize(actor,options = {},&block)
8
+ @actor = actor
9
+ @options = options
10
+ @on_complete_block = block
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,15 @@
1
+ module Metro
2
+ class Easing
3
+
4
+ #
5
+ # Perform a ease-in motion between the start position and the final position.
6
+ #
7
+ class EaseIn < Easing
8
+ def self.calculation(moment,start,change,interval)
9
+ change * (moment = moment / interval) * moment + start
10
+ end
11
+ end
12
+
13
+ register :ease_in, EaseIn
14
+ end
15
+ end
@@ -0,0 +1,51 @@
1
+ module Metro
2
+
3
+ #
4
+ # An easing is a means to calculate the steps between the start and the final
5
+ # over an interval.
6
+ #
7
+ class Easing
8
+
9
+ #
10
+ # The calculate method is called within the ImplicitAnimation and will create
11
+ # an array of all the states between the start and the final value.
12
+ #
13
+ def self.calculate(start,final,interval)
14
+ change = final - start
15
+ (1..interval).map { |time| calculation(time.to_f,start,change,interval) }
16
+ end
17
+
18
+ #
19
+ # The calculation method is to be overriden in the Easing subclasses.
20
+ # This calculation figures out the value at the current moemnt.
21
+ #
22
+ def self.calculation(moment,start,change,interval) ; 0 ; end
23
+
24
+ #
25
+ # Register an easing within the game system.
26
+ #
27
+ def self.register(name,easing_class)
28
+ easings[name] = easing_class.to_s
29
+ end
30
+
31
+ #
32
+ # @return the easing class based on the specified easing name.
33
+ #
34
+ def self.easing_for(easing)
35
+ easing_classname = easings[easing]
36
+ easing_classname.constantize
37
+ end
38
+
39
+ #
40
+ # A hash of all the supported easings within metro or game.
41
+ #
42
+ def self.easings
43
+ @easings_hash ||= HashWithIndifferentAccess.new("Metro::Easing::Linear")
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
50
+ require_relative 'linear'
51
+ require_relative 'ease_in'
@@ -0,0 +1,15 @@
1
+ module Metro
2
+ class Easing
3
+
4
+ #
5
+ # Perform a linear motion between the start position and the final position.
6
+ #
7
+ class Linear < Easing
8
+ def self.calculation(moment,start,change,interval)
9
+ change * moment / interval + start
10
+ end
11
+ end
12
+
13
+ register :linear, Linear
14
+ end
15
+ end
@@ -0,0 +1,70 @@
1
+ require_relative 'animation_factory'
2
+
3
+ module Metro
4
+ module HasAnimations
5
+
6
+ def self.included(base)
7
+ base.extend ClassMethods
8
+ end
9
+
10
+ #
11
+ # Define an animation from within another animation block, an event block
12
+ # or a method.
13
+ #
14
+ # @example Defining an animation that fades out the hero when they have
15
+ # died.
16
+ #
17
+ # class HellScene
18
+ # draws :hero
19
+ #
20
+ # def update
21
+ # if hero.dead?
22
+ # animate :hero, to: { alpha: 0 }, interval: 60.ticks do
23
+ # transition_to :game_over
24
+ # end
25
+ # end
26
+ # end
27
+ #
28
+ # end
29
+ #
30
+ def animate(actor_or_actor_name,options,&block)
31
+ options[:actor] = actor(actor_or_actor_name)
32
+ options[:context] = self
33
+ animation_group = SceneAnimation.build options, &block
34
+ enqueue animation_group
35
+ end
36
+
37
+ # An alternative to stating `animate` syntax.
38
+ alias_method :change, :animate
39
+
40
+ module ClassMethods
41
+
42
+ #
43
+ # Define an animation to execute when the scene starts.
44
+ #
45
+ # @example Defining an animation that fades in and moves a logo when it is
46
+ # done, transition to the title scene.
47
+ #
48
+ # animate :logo, to: { y: 80, alpha: 50 }, interval: 120.ticks do
49
+ # transition_to :title
50
+ # end
51
+ #
52
+ def animate(actor_name,options,&block)
53
+ scene_animation = AnimationFactory.new actor_name, options, &block
54
+ animations.push scene_animation
55
+ end
56
+
57
+ # Provide an alternative to the `animate` syntax.
58
+ alias_method :change, :animate
59
+
60
+ #
61
+ # All the animations that are defined for the scene to be run the scene starts.
62
+ #
63
+ def animations
64
+ @animations ||= []
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,100 @@
1
+ require_relative 'easing/easing'
2
+
3
+ module Metro
4
+
5
+ #
6
+ # An Implicit Animation is an animation without all the work.
7
+ # This little animation will take care of figuring out moving an
8
+ # actor from one position to another, the rotation, the alpha,
9
+ # etc.
10
+ #
11
+ # @example Creating an explicit animation that moves a player
12
+ #
13
+ # animation = ImplicitAnimation.new actor: player,
14
+ # to: { x: final_x, y: final_y },
15
+ # interval: 80,
16
+ # easing: :ease_in,
17
+ # context: scene
18
+ #
19
+ # animation.on_complete do
20
+ # transition_to :main
21
+ # end
22
+ #
23
+ # Here an animation is created that will move the player to the
24
+ # position (final_x,final_y), specified in the :to hash that is
25
+ # provided, over the interval of 80 steps. Additionally the movement
26
+ # is done with an easing in.
27
+ #
28
+ # @note The actor object must respond to setter methods that match
29
+ # the specified attributes (e.g. x, y).
30
+ #
31
+ # The context provided is the context that the 'on_complete' block
32
+ # is executed. In this case, upon completition, transition the scene
33
+ # from the current one to the main scene.
34
+ #
35
+ class ImplicitAnimation < OnUpdateOperation
36
+
37
+ def animations
38
+ @animations ||= []
39
+ end
40
+
41
+ #
42
+ # @return the type of easing that the implicit animation should employ.
43
+ # By default it uses linear but can be overridden when the easing is
44
+ # configured.
45
+ #
46
+ attr_reader :easing
47
+
48
+ #
49
+ # Additional initializion is required to calculate the attributes
50
+ # that are going to be animated and to determine each of their deltas.
51
+ #
52
+ def after_initialize
53
+ to.each do |attribute,final|
54
+ start = actor.send(attribute)
55
+ animations.push build_animation_step(attribute,start,final)
56
+ end
57
+ end
58
+
59
+ def build_animation_step(attribute,start,final)
60
+ step = AnimationStep.new
61
+ step.actor = actor
62
+ step.attribute = attribute
63
+ step.deltas = easing_for(easing).calculate(start.to_f,final.to_f,interval.to_f)
64
+ step
65
+ end
66
+
67
+ class AnimationStep
68
+ attr_accessor :actor, :attribute, :deltas
69
+
70
+ def execute_step(step)
71
+ actor.set(attribute,deltas.at(step))
72
+ end
73
+ end
74
+
75
+ #
76
+ # @return the correct easing based on the specified name. When the name
77
+ # provided does not match anything then default to linear easing.
78
+ #
79
+ def easing_for(name)
80
+ Metro::Easing.easing_for(name)
81
+ end
82
+
83
+ #
84
+ # The ImplicitAnimation overrides the {Animation#execute_step} and
85
+ # updates the attributes of the actor based upon the value of the
86
+ # current animation step.
87
+ #
88
+ def execute_step
89
+ animations.each {|step| step.execute_step(current_step) }
90
+ end
91
+
92
+ #
93
+ # @return the delta for the attribute for the given step
94
+ #
95
+ def delta_for_step(attribute)
96
+ deltas[attribute].at(current_step)
97
+ end
98
+
99
+ end
100
+ end
@@ -0,0 +1,96 @@
1
+ module Metro
2
+
3
+ #
4
+ # OnUpdateOperation is an object that executes on the update cycle
5
+ # of the game. This usually take the form of an animation or some operation
6
+ # that needs to execute with each update of the game.
7
+ #
8
+ class OnUpdateOperation
9
+
10
+ def after_initialize ; end
11
+
12
+ def initialize(options)
13
+ @current_step = 0
14
+
15
+ options.each do |key,value|
16
+ send :instance_variable_set, "@#{key}".to_sym, value
17
+ self.class.send :define_method, key do
18
+ instance_variable_get("@#{key}")
19
+ end
20
+ end
21
+ after_initialize
22
+ end
23
+
24
+ #
25
+ # Sets the action that happens with each step of the animation.
26
+ #
27
+ def on_step(&block)
28
+ @step_block = block
29
+ end
30
+
31
+ #
32
+ # Sets the action that happens when the animation is completed.
33
+ #
34
+ def on_complete(&block)
35
+ @complete_block = block
36
+ end
37
+
38
+ #
39
+ # Perform a step of an animation, if it hasn't already been completed.
40
+ #
41
+ def update
42
+ return if completed?
43
+
44
+ execute_step
45
+ next_step
46
+
47
+ complete! if completed?
48
+ end
49
+
50
+ #
51
+ # @return the current step of the animation.
52
+ #
53
+ attr_reader :current_step
54
+
55
+ attr_reader :step_block, :complete_block
56
+
57
+ #
58
+ # Move to the next step in the animation.
59
+ #
60
+ def next_step
61
+ @current_step = current_step + step_interval
62
+ end
63
+
64
+ #
65
+ # @return the interval at which the animation take place.
66
+ #
67
+ def step_interval
68
+ 1
69
+ end
70
+
71
+ #
72
+ # @return true if the animation has completed all the actions, false
73
+ # if there are remaining actions.
74
+ #
75
+ def completed?
76
+ current_step >= interval
77
+ end
78
+
79
+ #
80
+ # Perform the action that happens with each step of the animation.
81
+ #
82
+ def execute_step
83
+ context.instance_eval(&@step_block) if step_block and context
84
+ end
85
+
86
+ #
87
+ # Perform the action that happens when the animation is completed.
88
+ #
89
+ def complete!
90
+ context.instance_eval(&@complete_block) if complete_block and context
91
+ end
92
+
93
+ end
94
+ end
95
+
96
+ require_relative 'implicit_animation'