metro 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|