metro 0.0.3 → 0.0.5
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.
- data/lib/gosu_ext/color.rb +24 -0
- data/lib/metro.rb +6 -2
- data/lib/metro/animation/animation.rb +78 -49
- data/lib/metro/animation/easing.rb +22 -19
- data/lib/metro/animation/implicit_animation.rb +84 -25
- data/lib/metro/game.rb +5 -1
- data/lib/metro/game/dsl.rb +4 -0
- data/lib/metro/models/generic.rb +12 -0
- data/lib/metro/models/image.rb +29 -0
- data/lib/metro/models/label.rb +29 -0
- data/lib/metro/models/model.rb +188 -0
- data/lib/metro/models/select.rb +77 -0
- data/lib/metro/scene.rb +106 -6
- data/lib/metro/scene_actor.rb +26 -0
- data/lib/metro/scene_view/scene_view.rb +24 -27
- data/lib/metro/version.rb +1 -1
- data/lib/metro/window.rb +1 -1
- metadata +9 -9
- data/lib/metro/model.rb +0 -12
- data/lib/metro/scene_view/drawers/artists_block.rb +0 -17
- data/lib/metro/scene_view/drawers/composite_drawer.rb +0 -87
- data/lib/metro/scene_view/drawers/drawer.rb +0 -115
- data/lib/metro/scene_view/drawers/image.rb +0 -31
- data/lib/metro/scene_view/drawers/label.rb +0 -28
- data/lib/metro/scene_view/drawers/select.rb +0 -70
@@ -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
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
28
|
-
|
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
|
-
|
31
|
-
|
32
|
-
|
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
|
-
|
35
|
-
|
36
|
-
end
|
42
|
+
execute_step
|
43
|
+
next_step
|
37
44
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
52
|
-
|
53
|
-
|
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
|
-
|
56
|
-
|
57
|
-
|
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
|
2
|
-
module
|
3
|
-
extend self
|
1
|
+
module Metro
|
2
|
+
module Easing
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
module Linear
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def linear(moment,start,change,interval)
|
8
|
+
change * moment / interval + start
|
9
|
+
end
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
16
|
-
|
17
|
+
module EaseIn
|
18
|
+
extend self
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
def ease_in_quad(moment,start,change,interval)
|
21
|
+
change * (moment = moment / interval) * moment + start
|
22
|
+
end
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
3
|
+
module Metro
|
4
4
|
|
5
|
-
|
6
|
-
|
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
|
-
|
9
|
-
|
10
|
-
|
37
|
+
#
|
38
|
+
# @return the array of attributes that are being animated.
|
39
|
+
#
|
40
|
+
attr_reader :attributes
|
11
41
|
|
12
|
-
|
13
|
-
@
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
22
|
-
@easing
|
23
|
-
|
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
|
-
|
26
|
-
|
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
|
-
|
62
|
+
@attributes = to.map { |attribute,final| attribute }
|
29
63
|
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
-
|
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
|
-
|
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
|
|
data/lib/metro/game/dsl.rb
CHANGED
@@ -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
|