metro 0.3.2 → 0.3.3
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 +51 -20
- data/changelog.md +9 -0
- data/lib/metro/events/hit_list.rb +7 -8
- data/lib/metro/font.rb +3 -0
- data/lib/metro/game.rb +7 -3
- data/lib/metro/models/model.rb +16 -13
- data/lib/metro/models/properties/animation_property.rb +5 -1
- data/lib/metro/models/properties/dimensions_property.rb +8 -7
- data/lib/metro/models/properties/font_property.rb +2 -1
- data/lib/metro/models/properties/model_property.rb +84 -0
- data/lib/metro/models/properties/property.rb +2 -1
- data/lib/metro/models/ui/border.rb +69 -0
- data/lib/metro/models/ui/fps.rb +54 -0
- data/lib/metro/models/ui/generic.rb +8 -1
- data/lib/metro/models/ui/grid_drawer.rb +17 -5
- data/lib/metro/models/ui/image.rb +40 -8
- data/lib/metro/models/ui/label.rb +48 -7
- data/lib/metro/models/ui/menu.rb +61 -8
- data/lib/metro/models/ui/model_label.rb +65 -0
- data/lib/metro/models/ui/model_labeler.rb +79 -0
- data/lib/metro/models/ui/rectangle.rb +6 -0
- data/lib/metro/scene.rb +1 -1
- data/lib/metro/transitions/edit_transition_scene.rb +28 -1
- data/lib/metro/units/dimensions.rb +29 -2
- data/lib/metro/units/point.rb +16 -4
- data/lib/metro/units/rectangle_bounds.rb +38 -16
- data/lib/metro/version.rb +1 -1
- data/lib/setup_handlers/reload_game_on_game_file_changes.rb +6 -1
- data/lib/templates/game/scenes/first_scene.rb +4 -0
- metadata +14 -8
data/README.md
CHANGED
@@ -7,7 +7,10 @@
|
|
7
7
|
|
8
8
|
```
|
9
9
|
|
10
|
-
Metro is a framework built around [gosu](https://github.com/jlnr/gosu) (the 2D
|
10
|
+
Metro is a framework built around [gosu](https://github.com/jlnr/gosu) (the 2D
|
11
|
+
game development library in Ruby). The goal of Metro is to enforce common
|
12
|
+
conceptual structures and conventions making it easier to quickly generate a
|
13
|
+
game.
|
11
14
|
|
12
15
|
[](https://codeclimate.com/github/burtlo/metro)
|
13
16
|
|
@@ -21,42 +24,62 @@ You want to develop games in Ruby.
|
|
21
24
|
|
22
25
|
### Why not just use Gosu?
|
23
26
|
|
24
|
-
Gosu does a lot of great work bringing OpenGL to Ruby. However, when you finish
|
27
|
+
Gosu does a lot of great work bringing OpenGL to Ruby. However, when you finish
|
28
|
+
the [initial tutorial](https://github.com/jlnr/gosu/wiki/Ruby-Tutorial) you are
|
29
|
+
left with a brittle game that is very resistant to changes or new features.
|
25
30
|
|
26
|
-
* Metro provides the concept of a
|
31
|
+
* Metro provides the concept of a
|
32
|
+
[Scene](https://github.com/burtlo/metro/wiki/Scenes) which is the first
|
33
|
+
abstraction you would likely build after completing the tutorial.
|
27
34
|
|
28
|
-
> Developing your game in individual scenes will make it easier to logically
|
35
|
+
> Developing your game in individual scenes will make it easier to logically
|
36
|
+
layout your game.
|
29
37
|
|
30
|
-
* Sane management of images, animations, fonts, songs, and samples through
|
38
|
+
* Sane management of images, animations, fonts, songs, and samples through
|
39
|
+
[model properties](https://github.com/burtlo/metro/wiki/Model-properties).
|
31
40
|
|
32
|
-
> Having to load and cache fonts and images in every one of your models is
|
41
|
+
> Having to load and cache fonts and images in every one of your models is
|
42
|
+
tedious. It is also is wasteful as several of the same fonts are being used all
|
43
|
+
over the place.
|
33
44
|
|
34
45
|
* [Key-frame animations](https://github.com/burtlo/metro/wiki/Animations)
|
35
46
|
|
36
|
-
> Metro makes it simple to move an actor from one position to another position.
|
47
|
+
> Metro makes it simple to move an actor from one position to another position.
|
48
|
+
So simple movements, fades, color changes, and really any property change over
|
49
|
+
time is defined very simply.
|
37
50
|
|
38
51
|
* [Event Handling](https://github.com/burtlo/metro/wiki/Events)
|
39
52
|
|
40
|
-
> Delete those huge `if ... elsif ... else` input checking structures for
|
53
|
+
> Delete those huge `if ... elsif ... else` input checking structures for
|
54
|
+
keyboard, gamepad, and mouse button presses (down,up, and held). Metro makes it
|
55
|
+
easy to define them and an attach a course of action to take when the event
|
56
|
+
happens.
|
41
57
|
|
42
58
|
### Why not use Chingu or Gamebox?
|
43
59
|
|
44
60
|
Both [Gamebox](https://github.com/shawn42/gamebox) and
|
45
|
-
[Chingu](https://github.com/ippa/chingu) are
|
46
|
-
larger set of features.
|
61
|
+
[Chingu](https://github.com/ippa/chingu) are more mature libraries with a
|
62
|
+
larger set of features. I encourage you to check out those libraries.
|
47
63
|
|
48
|
-
|
49
|
-
|
64
|
+
Metro's primary goal is to be a framework of features that make game development
|
65
|
+
joyful.
|
50
66
|
|
51
67
|
* Active Reloading while building your scenes.
|
52
68
|
|
53
69
|
> Adjustments to your game code while working on a scene will automatically
|
54
|
-
reload your game code. The template game sets up a shortcut key (**Ctrl+R**)
|
70
|
+
reload your game code. The template game sets up a shortcut key (**Ctrl+R**)
|
71
|
+
that allows you to explicitly reload the game and the current scene.
|
55
72
|
|
56
73
|
* Scene Edit Support
|
57
74
|
|
58
|
-
>
|
59
|
-
|
75
|
+
> Scenes can enter an edit mode which allows you to re-position actors within
|
76
|
+
the scene. The changes can then be saved back to the view. This allows you to
|
77
|
+
fine tune the layout of those scene elements, making it easier to get things
|
78
|
+
pixel perfect.
|
79
|
+
|
80
|
+
Metro's secondary goal is to make it easier for individuals familiar with Rails
|
81
|
+
get into game development. That is the reason for some of the design choices,
|
82
|
+
the opinionated structure, and generators that come with Metro.
|
60
83
|
|
61
84
|
### Why you shouldn't use Metro?
|
62
85
|
|
@@ -64,11 +87,16 @@ Metro has some the following limitations:
|
|
64
87
|
|
65
88
|
* Limited to the gems defined within Metro
|
66
89
|
|
67
|
-
> At this point in time you are not able to define and package additional
|
90
|
+
> At this point in time you are not able to define and package additional
|
91
|
+
dependencies with your game. This means if you are using a gem that is not
|
92
|
+
already defined by Metro you will run into trouble when running it on alternate
|
93
|
+
systems. This will likely be addressed in the future when more demand arises.
|
68
94
|
|
69
95
|
* Difficult Deployment
|
70
96
|
|
71
|
-
> For individuals to play your game, they will also have to install Metro.
|
97
|
+
> For individuals to play your game, they will also have to install Metro.
|
98
|
+
However, work is being made to bring some simple packaging to Metro games to
|
99
|
+
make them stand-along executables.
|
72
100
|
|
73
101
|
## Installation
|
74
102
|
|
@@ -80,7 +108,8 @@ $ gem install metro
|
|
80
108
|
|
81
109
|
### Running a Game
|
82
110
|
|
83
|
-
By default `metro` will look for a file named 'metro' within the current working
|
111
|
+
By default `metro` will look for a file named 'metro' within the current working
|
112
|
+
directory if no *gamefilename* has been provided.
|
84
113
|
|
85
114
|
```bash
|
86
115
|
$ metro GAMEFILENAME
|
@@ -104,9 +133,11 @@ Creating a Game can be done with a single command.
|
|
104
133
|
$ metro new GAMENAME
|
105
134
|
```
|
106
135
|
|
107
|
-
This should generate for you a starting game with a branding scene and a title
|
136
|
+
This should generate for you a starting game with a branding scene and a title
|
137
|
+
scene. The game allows the player to start the game.
|
108
138
|
|
109
|
-
The game is missing the `first` scene of the game. This can be created with the
|
139
|
+
The game is missing the `first` scene of the game. This can be created with the
|
140
|
+
scene generator:
|
110
141
|
|
111
142
|
```bash
|
112
143
|
$ metro generate scene first
|
data/changelog.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Metro
|
2
2
|
|
3
|
+
## 0.3.3 / 2012-11-28
|
4
|
+
|
5
|
+
* Edit Mode - actors within a scene can have their position edited
|
6
|
+
and saved. Actors within the scene that have a valid bounds
|
7
|
+
specified will appear within the scene with name and bounding box.
|
8
|
+
* Dimensions can now be defined as strings
|
9
|
+
* Game bounds and Game dimensions return objects of that type
|
10
|
+
* `metr::ui::fps` added and has some shortcut placements settings
|
11
|
+
|
3
12
|
## 0.3.2 / 2012-11-26
|
4
13
|
|
5
14
|
* Debug Mode will now automatically reload the game and scene on source
|
@@ -27,24 +27,22 @@ module Metro
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def update(event)
|
30
|
-
|
31
|
-
|
32
|
-
list.each { |d| d.offset(offset_x,offset_y) }
|
30
|
+
offset = offset_from_last_event(event)
|
31
|
+
list.each { |d| d.position = d.position + offset }
|
33
32
|
|
34
33
|
save_event event
|
35
34
|
end
|
36
35
|
|
37
36
|
def release(event)
|
38
|
-
|
39
|
-
|
40
|
-
list.each { |d| d.offset(offset_x,offset_y) }
|
37
|
+
offset = offset_from_last_event(event)
|
38
|
+
list.each { |d| d.position = d.position + offset }
|
41
39
|
|
42
40
|
save_event event
|
43
41
|
clear
|
44
42
|
end
|
45
43
|
|
46
44
|
def drawers_at(x,y)
|
47
|
-
hit_drawers = drawers.find_all { |drawer| drawer.contains?(x,y) }
|
45
|
+
hit_drawers = drawers.find_all { |drawer| drawer.bounds.contains?(x,y) }
|
48
46
|
|
49
47
|
# assumed that we only want one item
|
50
48
|
top_drawer = hit_drawers.inject(hit_drawers.first) {|top,drawer| drawer.z_order > top.z_order ? drawer : top }
|
@@ -52,7 +50,8 @@ module Metro
|
|
52
50
|
end
|
53
51
|
|
54
52
|
def offset_from_last_event(event)
|
55
|
-
|
53
|
+
return Point.zero unless @last_event
|
54
|
+
Metro::Units::Point.at (event.mouse_x - @last_event.mouse_x).to_i, (event.mouse_y - @last_event.mouse_y).to_i
|
56
55
|
end
|
57
56
|
|
58
57
|
def save_event(event)
|
data/lib/metro/font.rb
CHANGED
@@ -10,6 +10,9 @@ module Metro
|
|
10
10
|
super(gosu_font)
|
11
11
|
end
|
12
12
|
|
13
|
+
# An alias to Gosu::Font's height method
|
14
|
+
def size ; height ; end
|
15
|
+
|
13
16
|
#
|
14
17
|
# Return a font that matches the specified criteria. Using the name, size,
|
15
18
|
# and window a font will be generated or retrieved from the cache.
|
data/lib/metro/game.rb
CHANGED
@@ -32,10 +32,10 @@ module Metro
|
|
32
32
|
attr_reader :window
|
33
33
|
|
34
34
|
#
|
35
|
-
# @return [Scene,NilClass] the current scene that is being displayed. If
|
35
|
+
# @return [Scene,NilClass] the current scene that is being displayed. If
|
36
36
|
# this is called before the window is being displayed when this will return
|
37
37
|
# a nil value.
|
38
|
-
#
|
38
|
+
#
|
39
39
|
def current_scene
|
40
40
|
window ? window.scene : nil
|
41
41
|
end
|
@@ -52,8 +52,12 @@ module Metro
|
|
52
52
|
fetch(:height,480)
|
53
53
|
end
|
54
54
|
|
55
|
+
def bounds
|
56
|
+
Units::RectangleBounds.new left: 0, right: width, top: 0, bottom: height
|
57
|
+
end
|
58
|
+
|
55
59
|
def dimensions
|
56
|
-
|
60
|
+
Units::Dimensions.of width, height
|
57
61
|
end
|
58
62
|
|
59
63
|
def center
|
data/lib/metro/models/model.rb
CHANGED
@@ -76,6 +76,12 @@ module Metro
|
|
76
76
|
#
|
77
77
|
property :name, type: :text
|
78
78
|
|
79
|
+
#
|
80
|
+
# @return [TrueClass,FalseClass] true if the model should be saved to the
|
81
|
+
# view file, false when the model should not be savedable to the view file.
|
82
|
+
#
|
83
|
+
property :saveable_to_view, type: :boolean, default: true
|
84
|
+
|
79
85
|
#
|
80
86
|
# The window that this model that this window is currently being
|
81
87
|
# displayed.
|
@@ -130,19 +136,12 @@ module Metro
|
|
130
136
|
mc
|
131
137
|
end
|
132
138
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
false
|
140
|
-
end
|
141
|
-
|
142
|
-
# Belongs to positionable items only
|
143
|
-
def offset(x,y)
|
144
|
-
self.x += x
|
145
|
-
self.y += y
|
139
|
+
#
|
140
|
+
# By default a model has no bounds. Each subclass of model will have to
|
141
|
+
# define how their bounds are defined.
|
142
|
+
#
|
143
|
+
def bounds
|
144
|
+
Bounds.none
|
146
145
|
end
|
147
146
|
|
148
147
|
#
|
@@ -241,4 +240,8 @@ require_relative 'ui/menu'
|
|
241
240
|
require_relative 'ui/image'
|
242
241
|
require_relative 'ui/rectangle'
|
243
242
|
require_relative 'ui/grid_drawer'
|
243
|
+
require_relative 'ui/border'
|
244
|
+
require_relative 'ui/model_label'
|
245
|
+
require_relative 'ui/model_labeler'
|
246
|
+
require_relative 'ui/fps'
|
244
247
|
require_relative 'audio/song'
|
@@ -94,7 +94,11 @@ module Metro
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def default_dimensions
|
97
|
-
options[:dimensions]
|
97
|
+
if options[:dimensions]
|
98
|
+
Dimensions.parse options[:dimensions]
|
99
|
+
else
|
100
|
+
Dimensions.of 16.0, 16.0
|
101
|
+
end
|
98
102
|
end
|
99
103
|
|
100
104
|
def default_time_per_image
|
@@ -68,15 +68,16 @@ module Metro
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def default_dimensions
|
71
|
-
|
72
|
-
model.instance_eval(&block)
|
73
|
-
elsif options[:default] and options[:default].is_a? Dimensions
|
74
|
-
options[:default]
|
75
|
-
else
|
76
|
-
Dimensions.none
|
77
|
-
end
|
71
|
+
Dimensions.parse default_dimensions_params.to_s
|
78
72
|
end
|
79
73
|
|
74
|
+
private
|
75
|
+
|
76
|
+
def default_dimensions_params
|
77
|
+
block ? model.instance_eval(&block) : options[:default]
|
78
|
+
end
|
79
|
+
|
80
|
+
|
80
81
|
end
|
81
82
|
|
82
83
|
end
|
@@ -34,6 +34,7 @@ module Metro
|
|
34
34
|
# @example Using the `font_size` and `font_name` properties
|
35
35
|
#
|
36
36
|
# class Hero < Metro::Model
|
37
|
+
# property :font, default: { name: 'Comic Sans', size: 80 }
|
37
38
|
# property :color, default: "rgba(255,0,0,1.0)"
|
38
39
|
#
|
39
40
|
# def dignified
|
@@ -45,7 +46,7 @@ module Metro
|
|
45
46
|
# @example Using a font property with a different property name
|
46
47
|
#
|
47
48
|
# class Hero < Metro::Model
|
48
|
-
# property :alt_font, type: :font, default:
|
49
|
+
# property :alt_font, type: :font, default: { name: 'Helvetica', size: 80 }
|
49
50
|
#
|
50
51
|
# def draw
|
51
52
|
# puts "Font: #{alt_font_name}:#{alt_font_size}"
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Metro
|
2
|
+
class Model
|
3
|
+
|
4
|
+
#
|
5
|
+
# A model property maintains a reference to another model. This property
|
6
|
+
# allows for an existing model to be more easily composed with other models.
|
7
|
+
#
|
8
|
+
# The model is stored as a hash which describes the model.
|
9
|
+
#
|
10
|
+
# @example Defining a model property with a block
|
11
|
+
#
|
12
|
+
# class ScoreBoard < Metro::Model
|
13
|
+
# property :position
|
14
|
+
# property :score
|
15
|
+
# property :label, type: :model do
|
16
|
+
# create "metro::ui::label", text: "", position: position
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# @example Defining a model property with a hash
|
21
|
+
#
|
22
|
+
# class ScoreBoard < Metro::Model
|
23
|
+
# property :position
|
24
|
+
# property :score
|
25
|
+
# property :label, type: :model, default: { model: "metro::ui::label",
|
26
|
+
# text: "", position: position }
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
class ModelProperty < Property
|
31
|
+
|
32
|
+
# When retrieving a model and the type is unsupported generate the
|
33
|
+
# model instance from the default.
|
34
|
+
get do
|
35
|
+
default_model
|
36
|
+
end
|
37
|
+
|
38
|
+
# When retrieving a hash representation of the model, convert it into
|
39
|
+
# a Metro::Model instance.
|
40
|
+
get Hash do |params|
|
41
|
+
create_model params
|
42
|
+
end
|
43
|
+
|
44
|
+
# When setting the property with an unsupported type, simply save an
|
45
|
+
# empty hash. Which later, if retrieved, it will generate a generic
|
46
|
+
# model.
|
47
|
+
set do
|
48
|
+
{}
|
49
|
+
end
|
50
|
+
|
51
|
+
# When setting the property with a hash, assume that the hash is a
|
52
|
+
# valid description of a Metro::Model.
|
53
|
+
set Hash, HashWithIndifferentAccess do |hash|
|
54
|
+
hash
|
55
|
+
end
|
56
|
+
|
57
|
+
# When setting the property with a Metro::Model, convert the model into
|
58
|
+
# a hash.
|
59
|
+
set Metro::Model do |model|
|
60
|
+
model.to_hash
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# Allow for a model property to be defined with a block initialization or
|
65
|
+
# a default hash.
|
66
|
+
#
|
67
|
+
def default_model
|
68
|
+
if block
|
69
|
+
model.instance_eval(&block)
|
70
|
+
else
|
71
|
+
create_model options[:default]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [Metro::Model] return a model created by the current model that
|
76
|
+
# owns the property.
|
77
|
+
def create_model
|
78
|
+
model.create params[:model], params.except(:model)
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
@@ -217,4 +217,5 @@ require_relative 'position_property'
|
|
217
217
|
require_relative 'scale_property'
|
218
218
|
require_relative 'song_property'
|
219
219
|
require_relative 'sample_property'
|
220
|
-
require_relative 'options_property/options_property'
|
220
|
+
require_relative 'options_property/options_property'
|
221
|
+
require_relative 'model_property'
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Metro
|
2
|
+
module UI
|
3
|
+
|
4
|
+
#
|
5
|
+
# Draws a rectanglar border around the specififed position and dimensions
|
6
|
+
# with the width provided. This is an unfilled rectangle.
|
7
|
+
#
|
8
|
+
class Border < Metro::Model
|
9
|
+
|
10
|
+
# @attribute
|
11
|
+
# The starting position of the border.
|
12
|
+
property :position
|
13
|
+
|
14
|
+
# @attribute
|
15
|
+
# The dimension of the border.
|
16
|
+
property :dimensions
|
17
|
+
|
18
|
+
# @attribute
|
19
|
+
# The color which to use to draw the border.
|
20
|
+
property :color, default: "rgba(255,255,255,1.0)"
|
21
|
+
|
22
|
+
# @attribute
|
23
|
+
# The width of the border lines
|
24
|
+
property :border, default: 2
|
25
|
+
|
26
|
+
def draw
|
27
|
+
draw_border
|
28
|
+
end
|
29
|
+
|
30
|
+
def draw_border
|
31
|
+
draw_top
|
32
|
+
draw_bottom
|
33
|
+
draw_left
|
34
|
+
draw_right
|
35
|
+
end
|
36
|
+
|
37
|
+
def draw_top
|
38
|
+
window.draw_quad(x + border,y,color,
|
39
|
+
width + x,y,color,
|
40
|
+
x + width,y + border,color,
|
41
|
+
x + border,y + border,color,z_order)
|
42
|
+
end
|
43
|
+
|
44
|
+
def draw_left
|
45
|
+
window.draw_quad(x,y,color,
|
46
|
+
border + x,y,color,
|
47
|
+
x + border,y + border + height,color,
|
48
|
+
x,y + border + height,color,z_order)
|
49
|
+
end
|
50
|
+
|
51
|
+
def draw_right
|
52
|
+
window.draw_quad(x + width,y,color,
|
53
|
+
x + width + border,y,color,
|
54
|
+
x + width + border,y + border + height,color,
|
55
|
+
x + width,y + border + height,color,z_order)
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
def draw_bottom
|
60
|
+
window.draw_quad(x + border,y + height,color,
|
61
|
+
width + x,y + height,color,
|
62
|
+
x + width,y + border + height,color,
|
63
|
+
x + border,y + border + height,color,z_order)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|