metro 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,24 @@
1
+ class Gosu::Color
2
+
3
+ alias_method :gosu_initialize, :initialize
4
+
5
+ #
6
+ # Monkey-patching the initialize to allow for another Gosu::Color
7
+ # and Strings.
8
+ #
9
+ def initialize(*args)
10
+ if args.length == 1
11
+ value = args.first
12
+ if value.is_a? Gosu::Color
13
+ gosu_initialize value.alpha, value.red, value.green, value.blue
14
+ elsif value.is_a? String
15
+ gosu_initialize value.to_i(16)
16
+ else
17
+ gosu_initialize value
18
+ end
19
+ else
20
+ gosu_initialize *args
21
+ end
22
+ end
23
+
24
+ end
data/lib/metro.rb CHANGED
@@ -1,11 +1,15 @@
1
1
  require 'gosu'
2
+ require 'gosu_ext/color'
3
+
2
4
  require 'logger'
3
5
 
6
+
4
7
  require 'metro/version'
5
8
  require 'metro/window'
6
9
  require 'metro/game'
7
- require 'metro/model'
8
10
  require 'metro/scene'
11
+ require 'metro/models/model'
12
+ require 'metro/models/generic'
9
13
 
10
14
  def asset_path(name)
11
15
  File.join Dir.pwd, "assets", name
@@ -50,7 +54,6 @@ module Metro
50
54
  $LOAD_PATH.unshift(Dir.pwd) unless $LOAD_PATH.include?(Dir.pwd)
51
55
  Dir['models/*.rb'].each {|model| require model }
52
56
  Dir['scenes/*.rb'].each {|scene| require scene }
53
- Dir['drawers/*.rb'].each {|drawer| require drawer }
54
57
  end
55
58
 
56
59
  def load_game_configuration(filename)
@@ -62,6 +65,7 @@ module Metro
62
65
 
63
66
  def start_game
64
67
  window = Window.new Game.width, Game.height, Game.fullscreen?
68
+ window.caption = Game.name
65
69
  window.scene = Scenes.generate(Game.first_scene)
66
70
  window.show
67
71
  end
@@ -1,65 +1,94 @@
1
- class Animation
2
-
3
- attr_reader :current_step
4
-
5
- def initialize(options)
6
- @current_step = 0
7
-
8
- options.each do |key,value|
9
- send :instance_variable_set, "@#{key}".to_sym, value
10
- self.class.send :define_method, key do
11
- instance_variable_get("@#{key}")
1
+ module Metro
2
+
3
+ #
4
+ # Animation is the motion that gives a system it's life. An animation
5
+ # in this case is a really a mechanism that allows for an action to
6
+ # be repeated for a given interval of time.
7
+ #
8
+ class Animation
9
+
10
+ def initialize(options)
11
+ @current_step = 0
12
+
13
+ options.each do |key,value|
14
+ send :instance_variable_set, "@#{key}".to_sym, value
15
+ self.class.send :define_method, key do
16
+ instance_variable_get("@#{key}")
17
+ end
12
18
  end
19
+ after_initialize
13
20
  end
14
- after_initialize
15
- end
16
-
17
- def completed?
18
- current_step >= interval
19
- end
20
21
 
21
- def step!
22
- return if completed?
23
-
24
- execute_step
25
- next_step
22
+ #
23
+ # Sets the action that happens with each step of the animation.
24
+ #
25
+ def on_step(&block)
26
+ @step_block = block
27
+ end
26
28
 
27
- complete! if completed?
28
- end
29
+ #
30
+ # Sets the action that happens when the animation is completed.
31
+ #
32
+ def on_complete(&block)
33
+ @complete_block = block
34
+ end
29
35
 
30
- def next_step
31
- @current_step = current_step + step_interval
32
- end
36
+ #
37
+ # Perform a step of an animation, if it hasn't already been completed.
38
+ #
39
+ def update
40
+ return if completed?
33
41
 
34
- def step_interval
35
- 1
36
- end
42
+ execute_step
43
+ next_step
37
44
 
38
- def execute_block_in_context(block_name)
39
- if respond_to? block_name
40
- block_to_execute = send(block_name)
41
- context.instance_eval(&block_to_execute)
42
- else
43
- instance_variable_get("@#{block_name}").call
45
+ complete! if completed?
46
+ end
47
+
48
+ #
49
+ # @return the current step of the animation.
50
+ #
51
+ attr_reader :current_step
52
+
53
+ attr_reader :step_block, :complete_block
54
+
55
+ #
56
+ # Move to the next step in the animation.
57
+ #
58
+ def next_step
59
+ @current_step = current_step + step_interval
44
60
  end
45
- end
46
61
 
47
- def execute_step
48
- execute_block_in_context(:step_block)
49
- end
62
+ #
63
+ # @return the interval at which the animation take place.
64
+ #
65
+ def step_interval
66
+ 1
67
+ end
68
+
69
+ #
70
+ # @return true if the animation has completed all the actions, false
71
+ # if there are remaining actions.
72
+ #
73
+ def completed?
74
+ current_step >= interval
75
+ end
50
76
 
51
- def complete!
52
- execute_block_in_context(:completed)
53
- end
77
+ #
78
+ # Perform the action that happens with each step of the animation.
79
+ #
80
+ def execute_step
81
+ context.instance_eval(&@step_block) if step_block and context
82
+ end
54
83
 
55
- def step(&block)
56
- @step_block = block if block
57
- end
84
+ #
85
+ # Perform the action that happens when the animation is completed.
86
+ #
87
+ def complete!
88
+ context.instance_eval(&@complete_block) if complete_block and context
89
+ end
58
90
 
59
- def completed(&block)
60
- @completed = block if block
61
91
  end
62
-
63
92
  end
64
93
 
65
94
  require_relative 'implicit_animation'
@@ -1,28 +1,31 @@
1
- module Easing
2
- module Linear
3
- extend self
1
+ module Metro
2
+ module Easing
4
3
 
5
- def linear(moment,start,change,interval)
6
- change * moment / interval + start
7
- end
4
+ module Linear
5
+ extend self
6
+
7
+ def linear(moment,start,change,interval)
8
+ change * moment / interval + start
9
+ end
8
10
 
9
- def calculate(start,final,interval)
10
- change = final - start
11
- (1..interval).map { |time| linear(time,start,change,interval) }
11
+ def calculate(start,final,interval)
12
+ change = final - start
13
+ (1..interval).map { |time| linear(time.to_f,start,change,interval) }
14
+ end
12
15
  end
13
- end
14
16
 
15
- module EaseIn
16
- extend self
17
+ module EaseIn
18
+ extend self
17
19
 
18
- def ease_in_quad(moment,start,change,interval)
19
- change * (moment = moment / interval) * moment + start
20
- end
20
+ def ease_in_quad(moment,start,change,interval)
21
+ change * (moment = moment / interval) * moment + start
22
+ end
21
23
 
22
- def calculate(start,final,interval)
23
- change = final - start
24
- (1..interval).map { |time| ease_in_quad(time,start,change,interval) }
24
+ def calculate(start,final,interval)
25
+ change = final - start
26
+ (1..interval).map { |time| ease_in_quad(time.to_f,start,change,interval) }
27
+ end
25
28
  end
29
+
26
30
  end
27
31
  end
28
-
@@ -1,43 +1,102 @@
1
1
  require_relative 'easing'
2
2
 
3
- class ImplicitAnimation < Animation
3
+ module Metro
4
4
 
5
- attr_reader :attributes
6
- attr_reader :deltas
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 < Animation
7
36
 
8
- def delta_for_step(attribute)
9
- deltas[attribute].at(current_step)
10
- end
37
+ #
38
+ # @return the array of attributes that are being animated.
39
+ #
40
+ attr_reader :attributes
11
41
 
12
- def stepping(stepping)
13
- @steppings ||= begin
14
- hash = Hash.new(Easing::Linear)
15
- hash.merge! linear: Easing::Linear,
16
- ease_in: Easing::EaseIn
17
- end
18
- @steppings[stepping]
19
- end
42
+ #
43
+ # @return a Hash that contains all the animation step deltas
44
+ # for each attribute.
45
+ #
46
+ attr_reader :deltas
20
47
 
21
- def easing
22
- @easing || :linear
23
- end
48
+ #
49
+ # @return the type of easing that the implicit animation should employ.
50
+ # By default it uses linear but can be overridden when the easing is
51
+ # configured.
52
+ #
53
+ attr_reader :easing
24
54
 
25
- def after_initialize
26
- @deltas = {}
55
+ #
56
+ # Additional initializion is required to calculate the attributes
57
+ # that are going to be animated and to determine each of their deltas.
58
+ #
59
+ def after_initialize
60
+ @deltas = {}
27
61
 
28
- @attributes = to.map { |attribute,final| attribute }
62
+ @attributes = to.map { |attribute,final| attribute }
29
63
 
30
- to.each do |attribute,final|
31
- start = actor.send(attribute)
32
- deltas[attribute] = stepping(easing).calculate(start,final,interval)
64
+ to.each do |attribute,final|
65
+ start = actor.send(attribute)
66
+ deltas[attribute] = stepping(easing).calculate(start.to_f,final.to_f,interval.to_f)
67
+ end
33
68
  end
34
69
 
35
- step do
70
+ #
71
+ # @return the correct easing based on the specified name. When the name
72
+ # provided does not match anything then default to linear easing.
73
+ #
74
+ def stepping(stepping)
75
+ @steppings ||= begin
76
+ hash = Hash.new(Easing::Linear)
77
+ hash.merge! linear: Easing::Linear,
78
+ ease_in: Easing::EaseIn
79
+ end
80
+ @steppings[stepping]
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
36
89
  attributes.each do |attribute|
37
90
  actor.send "#{attribute}=", delta_for_step(attribute)
38
91
  end
39
92
  end
40
93
 
41
- end
94
+ #
95
+ # @return the delta for the attribute for the given step
96
+ #
97
+ def delta_for_step(attribute)
98
+ deltas[attribute].at(current_step)
99
+ end
42
100
 
101
+ end
43
102
  end
data/lib/metro/game.rb CHANGED
@@ -33,11 +33,15 @@ module Metro
33
33
  def fullscreen?
34
34
  !!config.fullscreen
35
35
  end
36
-
36
+
37
37
  def debug?
38
38
  !!config.debug
39
39
  end
40
40
 
41
+ def name
42
+ config.name
43
+ end
44
+
41
45
  # TODO: ZOrder related constants that belong to Starry Knight
42
46
  Background, Stars, Players, UI = *0..3
43
47
 
@@ -31,6 +31,10 @@ module Metro
31
31
  def debug(set_debug = nil)
32
32
  set_debug.nil? ? @debug : @debug = set_debug
33
33
  end
34
+
35
+ def name(set_name = nil)
36
+ set_name.nil? ? @name : @name = set_name
37
+ end
34
38
 
35
39
  end
36
40
  end
@@ -0,0 +1,12 @@
1
+ module Metro
2
+ module Models
3
+
4
+ #
5
+ # Generic model is used when no model is cannot not be found
6
+ # when mapping the view content
7
+ #
8
+ class Generic < Model
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,29 @@
1
+ module Metro
2
+ module Models
3
+
4
+ #
5
+ # Draws an Image
6
+ #
7
+ # @example Using the Image in a view file
8
+ # model: "metro::models::image"
9
+ #
10
+ class Image < Model
11
+
12
+ attr_accessor :angle, :center_x, :center_y, :x_factor, :y_factor
13
+
14
+ def image
15
+ @image ||= Gosu::Image.new(window,asset_path(path))
16
+ end
17
+
18
+ def draw
19
+ image.draw_rot x, y, z_order,
20
+ angle.to_f,
21
+ center_x, center_y,
22
+ x_factor, y_factor,
23
+ color
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+ end