metro 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
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 game development library in Ruby). The goal of Metro is to enforce common conceptual structures and conventions making it easier to quickly generate a game.
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
  [![Code Climate](https://codeclimate.com/badge.png)](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 the [initial tutorial](https://github.com/jlnr/gosu/wiki/Ruby-Tutorial) you are left with a brittle game that is very resistant to changes or new features.
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 [Scene](https://github.com/burtlo/metro/wiki/Scenes) which is the first abstraction you would likely build after completing the tutorial.
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 layout your game.
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 [model properties](https://github.com/burtlo/metro/wiki/Model-properties).
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 tedious. It is also is wasteful as several of the same fonts are being used all over the place.
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. So simple movements, fades, color changes, and really any property change over time is defined very simply.
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 keyboard, gamepad, and mouse button presses (down,up, and held). Metro makes it easy to define them and an attach a course of action to take when the event happens.
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 much more mature libraries with a
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
- With Metro the focus is on a smaller set of features with an emphasis on an
49
- implementation that leads to joyful development. An emphasis has been applied to creating elegant solutions which have documentation and examples.
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**) that allows you to explicitly reload the game and the current scene.
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
- > All scenes can have their visual component layout re-adjusted through an edit
59
- mode. The edit mode layout works for all labels, images, and menus.
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 dependencies with your game. This means if you are using a gem that is not already defined by Metro you will run into trouble when running it on alternate systems. This will likely be addressed in the future when more demand arises.
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. However, work is being made to bring some simple packaging to Metro games to make them stand-along executables.
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 directory if no *gamefilename* has been provided.
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 scene. The game allows the player to start the game.
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 scene generator:
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
@@ -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
- offset_x, offset_y = offset_from_last_event(event)
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
- offset_x, offset_y = offset_from_last_event(event)
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
- [ (event.mouse_x - @last_event.mouse_x).to_i, (event.mouse_y - @last_event.mouse_y).to_i ]
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)
@@ -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.
@@ -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
- [ width, height ]
60
+ Units::Dimensions.of width, height
57
61
  end
58
62
 
59
63
  def center
@@ -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
- def saveable?
134
- true
135
- end
136
-
137
- # Belongs to positionable items only
138
- def contains?(x,y)
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] or Dimensions.of(16.0,16.0)
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
- if block
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: "rgba(255,0,255,1.0)"
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