metro 0.3.3 → 0.3.4

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.
Files changed (40) hide show
  1. data/changelog.md +8 -1
  2. data/lib/core_ext/class.rb +14 -0
  3. data/lib/metro.rb +1 -0
  4. data/lib/metro/events/event_data.rb +3 -4
  5. data/lib/metro/events/event_state_manager.rb +63 -0
  6. data/lib/metro/events/events.rb +3 -0
  7. data/lib/metro/events/hit_list.rb +4 -5
  8. data/lib/metro/events/unknown_sender.rb +1 -1
  9. data/lib/metro/models/model.rb +14 -25
  10. data/lib/metro/models/model_factory.rb +1 -1
  11. data/lib/metro/models/models.rb +62 -0
  12. data/lib/metro/models/properties/position_property.rb +1 -1
  13. data/lib/metro/models/ui/animated_sprite.rb +85 -0
  14. data/lib/metro/models/ui/border.rb +44 -18
  15. data/lib/metro/models/ui/fps.rb +1 -1
  16. data/lib/metro/models/ui/generic.rb +24 -3
  17. data/lib/metro/models/ui/model_label.rb +1 -1
  18. data/lib/metro/models/ui/model_labeler.rb +2 -2
  19. data/lib/metro/models/ui/rectangle.rb +1 -1
  20. data/lib/metro/models/ui/sprite.rb +79 -0
  21. data/lib/metro/models/ui/ui.rb +12 -0
  22. data/lib/metro/scene.rb +13 -61
  23. data/lib/metro/scenes.rb +11 -13
  24. data/lib/metro/transitions/edit_transition_scene.rb +2 -2
  25. data/lib/metro/units/calculation_validations.rb +74 -0
  26. data/lib/metro/units/dimensions.rb +11 -19
  27. data/lib/metro/units/point.rb +6 -22
  28. data/lib/metro/units/rectangle_bounds.rb +10 -6
  29. data/lib/metro/units/scale.rb +7 -0
  30. data/lib/metro/units/units.rb +1 -0
  31. data/lib/metro/version.rb +1 -1
  32. data/lib/metro/window.rb +7 -3
  33. data/lib/setup_handlers/reload_game_on_game_file_changes.rb +6 -6
  34. data/lib/templates/game/models/hero.rb +35 -6
  35. data/lib/templates/model.rb.tt +1 -1
  36. data/spec/core_ext/string_spec.rb +0 -20
  37. data/spec/metro/units/point_spec.rb +132 -0
  38. data/spec/setup_handlers/exit_if_dry_run_spec.rb +27 -0
  39. data/spec/setup_handlers/reload_game_on_game_file_changes_spec.rb +68 -0
  40. metadata +21 -9
@@ -5,6 +5,7 @@ module Metro
5
5
  # Represents and object that contains the x, y, and z position.
6
6
  #
7
7
  class Point < Struct.new(:x,:y,:z)
8
+ include CalculationValidations
8
9
 
9
10
  #
10
11
  # Generate a point at 0,0,0.
@@ -18,7 +19,7 @@ module Metro
18
19
  # all inputs to floating point and assumes that the z-value is
19
20
  # zero (as this is a 2D universe).
20
21
  #
21
- def self.at(x,y,z=0.0)
22
+ def self.at(x=0.0,y=0.0,z=0.0)
22
23
  new x.to_f, y.to_f, z.to_f
23
24
  end
24
25
 
@@ -28,7 +29,7 @@ module Metro
28
29
  # either "x,y" or "x,y,z".
29
30
  #
30
31
  def self.parse(string)
31
- at *string.split(",",3).map(&:to_f)
32
+ at *string.to_s.split(",",3).map(&:to_f)
32
33
  end
33
34
 
34
35
  # As this is a 2D world, the Z is often refered to as a the z-ordering
@@ -39,27 +40,10 @@ module Metro
39
40
  "#{x},#{y},#{z}"
40
41
  end
41
42
 
42
- #
43
- # Add this point to another another point-like structure. A point like structure
44
- # is anything has the methods x, y, and z.
45
- #
46
- # @return a new point which is the sum of the point and the provided value.
47
- #
48
- def +(value)
49
- raise "Unable to add point to #{value} #{value.class}" if [ :x, :y, :z ].find { |method| ! value.respond_to?(method) }
50
- self.class.at (x + value.x.to_f), (y + value.y.to_f), (z + value.z.to_f)
51
- end
43
+ private
52
44
 
53
- #
54
- # Subtract the point-like structure from this point. A point like structure
55
- # is anything has the methods x, y, and z.
56
- #
57
- # @return a new point which is the difference of the point and the
58
- # provided value.
59
- #
60
- def -(value)
61
- raise "Unable to subtract from this point with #{value} #{value.class}" if [ :x, :y, :z ].find { |method| ! value.respond_to?(method) }
62
- self.class.at (x - value.x.to_f), (y - value.y.to_f), (z - value.z.to_f)
45
+ def calculation_requirements
46
+ [ :x, :y, :z ]
63
47
  end
64
48
 
65
49
  end
@@ -5,9 +5,7 @@ module Metro
5
5
  # An object that represents a rectanglar bounds.
6
6
  #
7
7
  class RectangleBounds
8
-
9
- # Allow the ability to refer to the min, max values with their
10
- # other alternate names.
8
+ include CalculationValidations
11
9
 
12
10
  attr_accessor :left, :right, :top, :bottom
13
11
 
@@ -46,15 +44,15 @@ module Metro
46
44
  end
47
45
 
48
46
  def ==(value)
49
- return if [ :left, :right, :top, :bottom ].find { |method| ! value.respond_to?(method) }
47
+ check_calculation_requirements(value)
50
48
  left == value.left and right == value.right and top == value.top and bottom == value.bottom
51
49
  end
52
50
 
53
51
  #
54
52
  # Does this bounds contain the following point?
55
53
  #
56
- def contains?(x,y)
57
- x > left and x < right and y > top and y < bottom
54
+ def contains?(point)
55
+ point.x > left and point.x < right and point.y > top and point.y < bottom
58
56
  end
59
57
 
60
58
  #
@@ -68,6 +66,12 @@ module Metro
68
66
  "(#{left},#{top}) to (#{right},#{bottom})"
69
67
  end
70
68
 
69
+ private
70
+
71
+ def calculation_requirements
72
+ [ :left, :right, :top, :bottom ]
73
+ end
74
+
71
75
  end
72
76
 
73
77
  end
@@ -5,6 +5,7 @@ module Metro
5
5
  # Represents an object that contains the x scale factor, and y scale factor.
6
6
  #
7
7
  class Scale < Struct.new(:x_factor,:y_factor)
8
+ include CalculationValidations
8
9
 
9
10
  #
10
11
  # Create a scale that is 1:1.
@@ -34,6 +35,12 @@ module Metro
34
35
  "#{x_factor},#{y_factor}"
35
36
  end
36
37
 
38
+ private
39
+
40
+ def calculation_requirements
41
+ [ :x_factor, :y_factor ]
42
+ end
43
+
37
44
  end
38
45
  end
39
46
  end
@@ -1,3 +1,4 @@
1
+ require_relative 'calculation_validations'
1
2
  require_relative 'point'
2
3
  require_relative 'dimensions'
3
4
  require_relative 'scale'
@@ -1,5 +1,5 @@
1
1
  module Metro
2
- VERSION = "0.3.3"
2
+ VERSION = "0.3.4"
3
3
  WEBSITE = "https://github.com/burtlo/metro"
4
4
  CONTACT_EMAILS = ["dev@rubymetro.com"]
5
5
 
@@ -13,6 +13,10 @@ module Metro
13
13
  #
14
14
  attr_accessor :scene
15
15
 
16
+ def state
17
+ scene.state
18
+ end
19
+
16
20
  #
17
21
  # @param [Fixnum] width the width of the game window
18
22
  # @param [Fixnum] height the height of the game window
@@ -32,7 +36,7 @@ module Metro
32
36
  # This is called every update interval while the window is being shown.
33
37
  #
34
38
  def update
35
- scene.fire_events_for_held_buttons
39
+ state.fire_events_for_held_buttons
36
40
  scene.base_update
37
41
  end
38
42
 
@@ -49,7 +53,7 @@ module Metro
49
53
  # has focus.
50
54
  #
51
55
  def button_up(id)
52
- scene.button_up(id)
56
+ state.fire_button_up(id)
53
57
  end
54
58
 
55
59
  #
@@ -57,7 +61,7 @@ module Metro
57
61
  # has focus.
58
62
  #
59
63
  def button_down(id)
60
- scene.button_down(id)
64
+ state.fire_button_down(id)
61
65
  end
62
66
 
63
67
  #
@@ -8,6 +8,10 @@ module Metro
8
8
  #
9
9
  class ReloadGameOnGameFileChanges
10
10
 
11
+ def watched_filepaths
12
+ source_filepaths + view_filepaths + asset_filepaths
13
+ end
14
+
11
15
  #
12
16
  # @NOTE this is duplication of the paths is also defined in LoadGameFiles.
13
17
  # @see Metro::SetupHandlers::LoadGameFiles
@@ -24,21 +28,17 @@ module Metro
24
28
  [ 'assets' ]
25
29
  end
26
30
 
27
- def all_filepaths
28
- source_filepaths + view_filepaths + asset_filepaths
29
- end
30
-
31
31
  #
32
32
  # @param [Metro::Parameters::Options] options the options that the game
33
33
  # was provided when it was launched.
34
34
  #
35
35
  def setup(options)
36
- start_watcher if Game.debug?
36
+ start_watcher if Game.debug? and not options.packaged?
37
37
  end
38
38
 
39
39
  def start_watcher
40
40
  Thread.abort_on_exception = true
41
- Thread.new { watch_filepaths(all_filepaths) }
41
+ Thread.new { watch_filepaths(watched_filepaths) }
42
42
  end
43
43
 
44
44
  #
@@ -1,9 +1,23 @@
1
- class Hero < Metro::Model
1
+ class Hero < Metro::UI::Sprite
2
+
3
+ # A Metro::UI::Sprite predefines a number of commmon properties:
4
+ #
5
+ # * position
6
+ # * dimensions
7
+ # * color
8
+ # * angle
9
+ # * scale
10
+ #
11
+ # These properties add getter and setter methods of the following:
12
+ #
13
+ # * position, x, y, z and z_order (both z and z_order are the same)
14
+ # * dimensions, width, and height
15
+ # * color, red, green, blue, alpha
16
+ # * angle
17
+ # * scale, x_factor, y_factor
2
18
 
3
19
  property :image, path: "hero.png"
4
20
 
5
- property :position
6
- property :angle
7
21
  property :move_amount, default: 1.5
8
22
  property :turn_amount, default: 90.0
9
23
 
@@ -27,7 +41,22 @@ class Hero < Metro::Model
27
41
  self.angle += turn_amount
28
42
  end
29
43
 
30
- def draw
31
- image.draw_rot(x,y,z_order,angle.to_f)
32
- end
44
+ # By default a Metro::UI::Sprite defines a #draw method which will
45
+ # draw the associated image with the position, rotation, and scale.
46
+ #
47
+ # If you would like to maintain the current draw functionality but augment
48
+ # it, you can define a draw method which calls to super.
49
+ #
50
+ # def draw
51
+ # super
52
+ # # custom drawing alongside the image
53
+ # end
54
+ #
55
+ # You may find it necessary to replace the existing draw functionality.
56
+ # Here you could define your own draw that overrides the original.
57
+ #
58
+ # def draw
59
+ # # custom drawing without the original image draw
60
+ # end
61
+
33
62
  end
@@ -1,4 +1,4 @@
1
- class <%= model_name %> < GameModel
1
+ class <%= model_name %> < Metro::Model
2
2
 
3
3
  #
4
4
  # Properties
@@ -30,24 +30,4 @@ describe String do
30
30
  its(:underscore) { should eq expected_value }
31
31
  end
32
32
  end
33
-
34
- describe "#classify" do
35
- context "when given a regular string" do
36
- subject { "string" }
37
- let(:expected_value) { "String" }
38
- its(:classify) { should eq expected_value }
39
- end
40
-
41
- context "when given a underscored string" do
42
- subject { "camel_cased" }
43
- let(:expected_value) { "CamelCased" }
44
- its(:classify) { should eq expected_value }
45
- end
46
-
47
- context "when given a partial camel_CasedString" do
48
- subject { "camel_CasedString" }
49
- let(:expected_value) { "CamelCasedString" }
50
- its(:classify) { should eq expected_value }
51
- end
52
- end
53
33
  end
@@ -0,0 +1,132 @@
1
+ require 'spec_helper'
2
+
3
+ describe Metro::Units::Point do
4
+
5
+ subject { described_class.new x, y, z }
6
+
7
+ let(:x) { 12 }
8
+ let(:y) { 24 }
9
+ let(:z) { 36 }
10
+
11
+ its(:x) { should eq x }
12
+ its(:y) { should eq y }
13
+ its(:z) { should eq z }
14
+ its(:z_order) { should eq z }
15
+
16
+ let(:expected_string) { "#{x},#{y},#{z}" }
17
+ its(:to_s) { should eq expected_string }
18
+
19
+ describe "#+" do
20
+ context "when adding it to another point" do
21
+ let(:point) { described_class.at 1, 2, 3 }
22
+ let(:summed_point) { described_class.at 13, 26, 39 }
23
+
24
+ it "should be a sum of the two points" do
25
+ sum = subject + point
26
+ sum.should eq summed_point
27
+ end
28
+ end
29
+
30
+ context "when adding it to another point-like object" do
31
+ let(:point) { stub('Point Like',x: 1, y: 2, z: 3) }
32
+ let(:summed_point) { described_class.at 13, 26, 39 }
33
+
34
+ it "should be a sum of the two points" do
35
+ sum = subject + point
36
+ sum.should eq summed_point
37
+ end
38
+ end
39
+
40
+ context "when adding it to something not like a point" do
41
+ let(:point) { stub('Not Point Like') }
42
+ let(:summed_point) { described_class.at 13, 26, 39 }
43
+
44
+ it "should raise an error" do
45
+ expect { subject + point }.to raise_error
46
+ end
47
+ end
48
+ end
49
+
50
+ describe "#-" do
51
+ context "when adding it to another point" do
52
+ let(:point) { described_class.at 1, 2, 3 }
53
+ let(:summed_point) { described_class.at 11, 22, 33 }
54
+
55
+ it "should be a sum of the two points" do
56
+ sum = subject - point
57
+ sum.should eq summed_point
58
+ end
59
+ end
60
+
61
+ context "when adding it to another point-like object" do
62
+ let(:point) { stub('Point Like',x: 1, y: 2, z: 3) }
63
+ let(:summed_point) { described_class.at 11, 22, 33 }
64
+
65
+ it "should be a sum of the two points" do
66
+ sum = subject - point
67
+ sum.should eq summed_point
68
+ end
69
+ end
70
+
71
+ context "when adding it to something not like a point" do
72
+ let(:point) { stub('Not Point Like') }
73
+ let(:summed_point) { described_class.at 13, 26, 39 }
74
+
75
+ it "should raise an error" do
76
+ expect { subject - point }.to raise_error
77
+ end
78
+ end
79
+ end
80
+
81
+ describe "Class Methods" do
82
+
83
+ subject { described_class }
84
+
85
+ describe "#zero" do
86
+ let(:expected_point) { Point.new 0,0,0 }
87
+
88
+ it "should create a zero point" do
89
+ subject.zero.should == expected_point
90
+ end
91
+ end
92
+
93
+ describe "#at" do
94
+ let(:expected_point) { Point.new 1,2,3 }
95
+
96
+ it "should be equal to a new created point" do
97
+ subject.at(1,2,3).should == expected_point
98
+ end
99
+ end
100
+
101
+ describe "#parse" do
102
+ context "when the input string is defined with 'x,y,z'" do
103
+ let(:input) { "1,2,3" }
104
+ let(:expected_value) { Point.at(1,2,3) }
105
+
106
+ it "should create the expected point" do
107
+ subject.parse(input).should eq expected_value
108
+ end
109
+ end
110
+
111
+ context "when the input string is defined with 'x,y'" do
112
+ let(:input) { "1,2" }
113
+ let(:expected_value) { Point.at(1,2,0) }
114
+
115
+ it "should create the expected point" do
116
+ subject.parse(input).should eq expected_value
117
+ end
118
+ end
119
+
120
+ context "when the input is a nil" do
121
+ let(:input) { nil }
122
+ let(:expected_value) { Point.at(0,0,0) }
123
+
124
+ it "should create the expected point" do
125
+ subject.parse(input).should eq expected_value
126
+ end
127
+ end
128
+ end
129
+
130
+ end
131
+
132
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Metro::SetupHandlers::ExitIfDryRun do
4
+
5
+ describe "#setup" do
6
+ context "when the options specify that this is a dry run" do
7
+
8
+ let(:options) { stub('Options', dry_run?: true) }
9
+
10
+ it "should exit the game" do
11
+ subject.should_receive(:exit)
12
+ subject.setup(options)
13
+ end
14
+ end
15
+
16
+ context "when the options DO NOT specify that this is a dry run" do
17
+
18
+ let(:options) { stub('Options', dry_run?: false) }
19
+
20
+ it "should not exit the game" do
21
+ subject.should_not_receive(:exit)
22
+ subject.setup(options)
23
+ end
24
+ end
25
+ end
26
+
27
+ end