metro 0.2.1 → 0.2.2
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/README.md +2 -0
- data/changelog.md +10 -0
- data/lib/assets/missing.mp3 +0 -0
- data/lib/assets/missing.wav +0 -0
- data/lib/gosu_ext/image.rb +4 -0
- data/lib/gosu_ext/sample.rb +18 -0
- data/lib/gosu_ext/song.rb +18 -0
- data/lib/metro.rb +2 -0
- data/lib/metro/animation/easing/ease_in.rb +15 -0
- data/lib/metro/animation/easing/easing.rb +51 -0
- data/lib/metro/animation/easing/linear.rb +15 -0
- data/lib/metro/animation/has_animations.rb +17 -0
- data/lib/metro/animation/implicit_animation.rb +5 -24
- data/lib/metro/models/draws.rb +10 -1
- data/lib/metro/models/model.rb +117 -89
- data/lib/metro/models/models/image.rb +8 -9
- data/lib/metro/models/models/label.rb +4 -8
- data/lib/metro/models/models/menu.rb +7 -9
- data/lib/metro/models/models/rectangle.rb +7 -12
- data/lib/metro/models/models/song.rb +33 -0
- data/lib/metro/models/properties/dimensions_property.rb +18 -1
- data/lib/metro/models/properties/image_property.rb +2 -2
- data/lib/metro/models/properties/position_property.rb +6 -0
- data/lib/metro/models/properties/property.rb +129 -23
- data/lib/metro/models/properties/sample_property.rb +97 -0
- data/lib/metro/models/properties/song_property.rb +113 -0
- data/lib/metro/scene.rb +2 -11
- data/lib/metro/scenes.rb +14 -7
- data/lib/metro/transitions/fade_transition_scene.rb +8 -1
- data/lib/metro/units/bounds.rb +8 -0
- data/lib/metro/units/dimensions.rb +23 -5
- data/lib/metro/units/point.rb +26 -1
- data/lib/metro/units/rectangle_bounds.rb +52 -0
- data/lib/metro/units/scale.rb +16 -0
- data/lib/metro/units/units.rb +3 -1
- data/lib/metro/version.rb +1 -1
- data/lib/metro/window.rb +7 -0
- data/lib/templates/game/README.md.tt +20 -1
- data/spec/metro/models/models/label_spec.rb +4 -4
- data/spec/metro/models/properties/dimensions_spec.rb +29 -0
- data/spec/metro/models/properties/position_property_spec.rb +5 -5
- data/spec/spec_helper.rb +3 -1
- metadata +22 -9
- data/lib/metro/animation/easing.rb +0 -31
- data/lib/metro/models/rectangle_bounds.rb +0 -28
@@ -0,0 +1,113 @@
|
|
1
|
+
module Metro
|
2
|
+
class Model
|
3
|
+
|
4
|
+
#
|
5
|
+
# A song property maintains a Gosu::Song.
|
6
|
+
#
|
7
|
+
# A song is stored in the properties as the path in the assets folder and is converted into
|
8
|
+
# a Gosu::Song when it is retrieved within the system. When retrieving a song the Song
|
9
|
+
# Property will attempt to use a song that already exists that meets that criteria.
|
10
|
+
#
|
11
|
+
# The songs are cached within the song property to help performance by reducing the unncessary
|
12
|
+
# creation of similar song.
|
13
|
+
#
|
14
|
+
# @example Defining a song property
|
15
|
+
#
|
16
|
+
# class Song < Metro::Model
|
17
|
+
# property :song
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# @example Defining a song property providing a default
|
21
|
+
#
|
22
|
+
# class Song < Metro::Model
|
23
|
+
# property :song, path: 'happy-song.wav'
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# @example Using a song property with a different property name
|
27
|
+
#
|
28
|
+
# class Song < Metro::Model
|
29
|
+
# property :intro, type: :song, path: 'intro-song.wav'
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
class SongProperty < Metro::Model::Property
|
33
|
+
|
34
|
+
# By default, getting an unsupported value will return the default song
|
35
|
+
get do |value|
|
36
|
+
default_song
|
37
|
+
end
|
38
|
+
|
39
|
+
# By default, setting an unsupported value will save the default song
|
40
|
+
set do |value|
|
41
|
+
default_song_name
|
42
|
+
end
|
43
|
+
|
44
|
+
# Generate a song from the specified string filepath
|
45
|
+
get String do |filename|
|
46
|
+
self.class.song_for path: filename, window: model.window
|
47
|
+
end
|
48
|
+
|
49
|
+
# The assumption here is that the string is a song filepath
|
50
|
+
set String do |filename|
|
51
|
+
filename
|
52
|
+
end
|
53
|
+
|
54
|
+
# Setting the song value with a Metro::Song will save the string filepath
|
55
|
+
set Metro::Song do |song|
|
56
|
+
song.path
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# @return the default song for the song property. This is based on the default
|
61
|
+
# song name.
|
62
|
+
#
|
63
|
+
def default_song
|
64
|
+
self.class.song_for path: default_song_name, window: model.window
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# @return a string song name that is default. If the property was not created with
|
69
|
+
# a default value the the default song is the missing song found in Metro.
|
70
|
+
#
|
71
|
+
def default_song_name
|
72
|
+
options[:path] || metro_asset_path('missing.mp3')
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# Returns a Metro::Song. This is composed of the metadata provided and a Gosu::Song.
|
77
|
+
#
|
78
|
+
# Songs are cached within the property to increase performance.
|
79
|
+
#
|
80
|
+
# @param [Hash] options the path, window, and other parameters necessary to generate
|
81
|
+
# a song.
|
82
|
+
#
|
83
|
+
def self.song_for(options)
|
84
|
+
options.symbolize_keys!
|
85
|
+
relative_path = options[:path]
|
86
|
+
window = options[:window]
|
87
|
+
|
88
|
+
absolute_path = path = options[:path]
|
89
|
+
absolute_path = asset_path(absolute_path) unless absolute_path.start_with? "/"
|
90
|
+
|
91
|
+
gosu_song = songs[relative_path]
|
92
|
+
|
93
|
+
unless gosu_song
|
94
|
+
gosu_song = create_song(window,absolute_path)
|
95
|
+
songs[relative_path] = gosu_song
|
96
|
+
end
|
97
|
+
|
98
|
+
Metro::Song.new gosu_song, relative_path
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.songs
|
102
|
+
@songs ||= {}
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def self.create_song(window,filename)
|
108
|
+
Gosu::Song.new(window, filename)
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
data/lib/metro/scene.rb
CHANGED
@@ -250,6 +250,7 @@ module Metro
|
|
250
250
|
def register_actor(actor_factory)
|
251
251
|
registering_actor = actor(actor_factory.name)
|
252
252
|
registering_actor.window = window
|
253
|
+
registering_actor.show
|
253
254
|
|
254
255
|
drawers.push(registering_actor)
|
255
256
|
updaters.push(registering_actor)
|
@@ -338,6 +339,7 @@ module Metro
|
|
338
339
|
#
|
339
340
|
def self.inherited(base)
|
340
341
|
scenes << base.to_s
|
342
|
+
Scenes.add_scene(base)
|
341
343
|
end
|
342
344
|
|
343
345
|
#
|
@@ -358,17 +360,6 @@ module Metro
|
|
358
360
|
updaters.push(updater)
|
359
361
|
end
|
360
362
|
|
361
|
-
#
|
362
|
-
# A simplier syntax to enqueue an animation. At the moment this animation is going
|
363
|
-
# to be an implicit animation.
|
364
|
-
#
|
365
|
-
def animate(actor_or_actor_name,options,&block)
|
366
|
-
options[:actor] = actor(actor_or_actor_name)
|
367
|
-
options[:context] = self
|
368
|
-
animation_group = SceneAnimation.build options, &block
|
369
|
-
enqueue animation_group
|
370
|
-
end
|
371
|
-
|
372
363
|
#
|
373
364
|
# The class defined updaters which will be converted to instance updaters when the scene
|
374
365
|
# has started.
|
data/lib/metro/scenes.rb
CHANGED
@@ -27,6 +27,16 @@ module Metro
|
|
27
27
|
module Scenes
|
28
28
|
extend self
|
29
29
|
|
30
|
+
#
|
31
|
+
# Add a scene to the hash of scenes with the scene name of the scene as the key
|
32
|
+
# to retrieving this scene.
|
33
|
+
#
|
34
|
+
# @param [Scene] scene the scene to be added to the hash of Scenes.
|
35
|
+
#
|
36
|
+
def add_scene(scene)
|
37
|
+
all_scenes_for(scene).each { |scene| scenes_hash[scene.scene_name] = scene.to_s }
|
38
|
+
end
|
39
|
+
|
30
40
|
#
|
31
41
|
# Finds the scene based on the specified scene name.
|
32
42
|
#
|
@@ -101,7 +111,7 @@ module Metro
|
|
101
111
|
# as well as the class name constants to allow for the scenes to be found.
|
102
112
|
#
|
103
113
|
def scenes_hash
|
104
|
-
@scenes_hash ||=
|
114
|
+
@scenes_hash ||= hash_with_missing_scene_default
|
105
115
|
end
|
106
116
|
|
107
117
|
#
|
@@ -114,22 +124,19 @@ module Metro
|
|
114
124
|
# @see #scenes_hash
|
115
125
|
#
|
116
126
|
def build_map_of_scenes(scenes)
|
117
|
-
hash = hash_with_missing_scene_default
|
118
|
-
all_scenes_for(scenes).inject(hash) do |hash,scene|
|
119
|
-
hash[scene.scene_name] = scene.to_s
|
120
|
-
hash
|
121
|
-
end
|
122
127
|
end
|
123
128
|
|
124
129
|
#
|
125
130
|
# Create a hash that will return a setup missing scene by default.
|
126
131
|
#
|
127
132
|
def hash_with_missing_scene_default
|
128
|
-
|
133
|
+
hash = HashWithIndifferentAccess.new do |hash,key|
|
129
134
|
missing_scene = scene_class(hash[:missing_scene])
|
130
135
|
missing_scene.missing_scene = key.to_sym
|
131
136
|
missing_scene
|
132
137
|
end
|
138
|
+
hash[:missing_scene] = "Metro::MissingScene"
|
139
|
+
hash
|
133
140
|
end
|
134
141
|
|
135
142
|
#
|
@@ -10,7 +10,14 @@ module Metro
|
|
10
10
|
def show
|
11
11
|
rectangle.color = starting_color
|
12
12
|
|
13
|
-
|
13
|
+
color = final_color
|
14
|
+
|
15
|
+
animate :rectangle, to: { red: color.red,
|
16
|
+
green: color.green,
|
17
|
+
blue: color.blue,
|
18
|
+
alpha: color.alpha },
|
19
|
+
interval: interval do
|
20
|
+
|
14
21
|
transition_to next_scene
|
15
22
|
end
|
16
23
|
end
|
@@ -1,17 +1,35 @@
|
|
1
1
|
module Metro
|
2
2
|
module Units
|
3
|
+
|
4
|
+
#
|
5
|
+
# Represents an object that contains both the width and height.
|
6
|
+
#
|
3
7
|
class Dimensions < Struct.new(:width,:height)
|
4
8
|
|
9
|
+
#
|
10
|
+
# Create a dimensions objects with zero width and zero height.
|
11
|
+
#
|
5
12
|
def self.none
|
6
|
-
|
13
|
+
of 0.0, 0.0
|
7
14
|
end
|
8
15
|
|
9
|
-
|
10
|
-
|
16
|
+
#
|
17
|
+
# Parse a string representation of a dimensions object. The
|
18
|
+
# supported formated is a comma-delimited string that contains
|
19
|
+
# two attributes width and height.
|
20
|
+
#
|
21
|
+
def self.parse(string)
|
22
|
+
of *string.split(",",2).map(&:to_f)
|
11
23
|
end
|
12
24
|
|
13
|
-
|
14
|
-
|
25
|
+
|
26
|
+
#
|
27
|
+
# An alternate way of creating a dimensions object which
|
28
|
+
# will enforce that the values added are converted to floating
|
29
|
+
# point numbers.
|
30
|
+
#
|
31
|
+
def self.of(width,height)
|
32
|
+
new width.to_f, height.to_f
|
15
33
|
end
|
16
34
|
|
17
35
|
def to_s
|
data/lib/metro/units/point.rb
CHANGED
@@ -1,18 +1,37 @@
|
|
1
1
|
module Metro
|
2
2
|
module Units
|
3
|
+
|
4
|
+
#
|
5
|
+
# Represents and object that contains the x, y, and z position.
|
6
|
+
#
|
3
7
|
class Point < Struct.new(:x,:y,:z)
|
8
|
+
|
9
|
+
#
|
10
|
+
# Generate a point at 0,0,0.
|
11
|
+
#
|
4
12
|
def self.zero
|
5
13
|
new 0.0, 0.0, 0.0
|
6
14
|
end
|
7
15
|
|
16
|
+
#
|
17
|
+
# An alternate way of creating a point. Creation here converts
|
18
|
+
# all inputs to floating point and assumes that the z-value is
|
19
|
+
# zero (as this is a 2D universe).
|
20
|
+
#
|
8
21
|
def self.at(x,y,z=0.0)
|
9
22
|
new x.to_f, y.to_f, z.to_f
|
10
23
|
end
|
11
24
|
|
25
|
+
#
|
26
|
+
# Parse a string representation of a point object. The
|
27
|
+
# supported formated is a comma-delimited string that contains
|
28
|
+
# either "x,y" or "x,y,z".
|
29
|
+
#
|
12
30
|
def self.parse(string)
|
13
31
|
at *string.split(",",3).map(&:to_f)
|
14
32
|
end
|
15
33
|
|
34
|
+
# As this is a 2D world, the Z is often refered to as a the z-ordering
|
16
35
|
alias_method :z_order, :z
|
17
36
|
alias_method :z_order=, :z=
|
18
37
|
|
@@ -20,9 +39,15 @@ module Metro
|
|
20
39
|
"#{x},#{y},#{z}"
|
21
40
|
end
|
22
41
|
|
42
|
+
#
|
43
|
+
# Add the point to another point-like structure. Anything that also has
|
44
|
+
# the methods x, y, and z.
|
45
|
+
#
|
46
|
+
# @return a new point which is the sum of the point and the provided value.
|
47
|
+
#
|
23
48
|
def +(value)
|
24
49
|
raise "Unabled to add point to #{value} #{value.class}" if [ :x, :y, :z ].find { |method| ! value.respond_to?(method) }
|
25
|
-
self.class.
|
50
|
+
self.class.at((x + value.x),(y + value.y),(z + value.z))
|
26
51
|
end
|
27
52
|
|
28
53
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Metro
|
2
|
+
module Units
|
3
|
+
|
4
|
+
#
|
5
|
+
# An object that represents a rectanglar bounds.
|
6
|
+
#
|
7
|
+
class RectangleBounds < Struct.new(:min_x,:min_y,:max_x,:max_y)
|
8
|
+
|
9
|
+
# Allow the ability to refer to the min, max values with their
|
10
|
+
# other alternate names.
|
11
|
+
|
12
|
+
alias_method :left, :min_x
|
13
|
+
alias_method :left=, :min_x=
|
14
|
+
alias_method :right, :max_x
|
15
|
+
alias_method :right=, :max_x=
|
16
|
+
alias_method :top, :min_y
|
17
|
+
alias_method :top=, :min_y=
|
18
|
+
alias_method :bottom, :max_y
|
19
|
+
alias_method :bottom=, :max_y=
|
20
|
+
|
21
|
+
#
|
22
|
+
# Create a bounds with bounds.
|
23
|
+
#
|
24
|
+
def initialize(params = {})
|
25
|
+
self.min_x = params[:x] || params[:min_x]
|
26
|
+
self.min_y = params[:y] || params[:min_y]
|
27
|
+
self.max_x = (params[:max_x] || (min_x + params[:width]))
|
28
|
+
self.max_y = (params[:max_y] || (min_y + params[:height]))
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Does this bounds contain the following point?
|
33
|
+
#
|
34
|
+
def contains?(x,y)
|
35
|
+
x > min_x and x < max_x and y > min_y and y < max_y
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Does this rectanglular bounds intersect with another rectanglular bounds?
|
40
|
+
#
|
41
|
+
def intersect?(b)
|
42
|
+
not(b.min_x > max_x or b.max_x < min_x or b.min_y > max_y or b.max_y < min_y)
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
"(#{min_x},#{min_y}) to (#{max_x},#{max_y})"
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
data/lib/metro/units/scale.rb
CHANGED
@@ -1,15 +1,31 @@
|
|
1
1
|
module Metro
|
2
2
|
module Units
|
3
|
+
|
4
|
+
#
|
5
|
+
# Represents an object that contains the x scale factor, and y scale factor.
|
6
|
+
#
|
3
7
|
class Scale < Struct.new(:x_factor,:y_factor)
|
4
8
|
|
9
|
+
#
|
10
|
+
# Create a scale that is 1:1.
|
11
|
+
#
|
5
12
|
def self.one
|
6
13
|
new 1.0, 1.0
|
7
14
|
end
|
8
15
|
|
16
|
+
#
|
17
|
+
# An alternative way to create a scale which will automatically convert
|
18
|
+
# the inputs into floating numbers.
|
19
|
+
#
|
9
20
|
def self.to(x,y)
|
10
21
|
new x.to_f, y.to_f
|
11
22
|
end
|
12
23
|
|
24
|
+
#
|
25
|
+
# Parse a string representation of a scale object. The
|
26
|
+
# supported formated is a comma-delimited string that contains
|
27
|
+
# two attributes x-factor and y-factor.
|
28
|
+
#
|
13
29
|
def self.parse(string)
|
14
30
|
to *string.split(",",2).map(&:to_f)
|
15
31
|
end
|
data/lib/metro/units/units.rb
CHANGED
data/lib/metro/version.rb
CHANGED
data/lib/metro/window.rb
CHANGED
@@ -60,6 +60,13 @@ module Metro
|
|
60
60
|
scene.button_down(id)
|
61
61
|
end
|
62
62
|
|
63
|
+
#
|
64
|
+
# @return the dimensions of the current window.
|
65
|
+
#
|
66
|
+
def dimensions
|
67
|
+
Metro::Units::Dimensions.of width, height
|
68
|
+
end
|
69
|
+
|
63
70
|
#
|
64
71
|
# Define an acessor that enables/disables the use of a cursor
|
65
72
|
# within the window. The value should be truthy/falsy.
|
@@ -7,4 +7,23 @@ are creating. This file's intention is to allow a user to
|
|
7
7
|
refer to this for more information related to the game or
|
8
8
|
possibly any notes or caveats about the game.
|
9
9
|
|
10
|
-
## Contact
|
10
|
+
## Contact
|
11
|
+
|
12
|
+
|
13
|
+
## Resources
|
14
|
+
|
15
|
+
#### Art
|
16
|
+
|
17
|
+
* [Lost Garden](http://www.lostgarden.com/2007/05/dancs-miraculously-flexible-game.html)
|
18
|
+
|
19
|
+
#### Books
|
20
|
+
|
21
|
+
* [Rules of Play](http://www.amazon.com/dp/0262240459)
|
22
|
+
* [Game Programming Gems 8](http://www.amazon.com/dp/1584507020)
|
23
|
+
* [Game Feel](http://www.amazon.com/dp/0123743281)
|
24
|
+
* [Game Coding Complete](http://www.amazon.com/dp/1584506806)
|
25
|
+
* [Game Design Workshop](http://www.amazon.com/dp/0240809742)
|
26
|
+
* [Challenges For Game Designers](http://www.amazon.com/dp/158450580X)
|
27
|
+
* [The Art of Game Design: A book of lenses](http://www.amazon.com/dp/0123694965)
|
28
|
+
* [A Theory of Fun](http://www.theoryoffun.com)
|
29
|
+
* [Andrew Rollings and Ernest Adams on Game Design](http://www.amazon.com/dp/1592730019)
|