metro-ld25 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.
Files changed (177) hide show
  1. data/.gitignore +17 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +12 -0
  6. data/Guardfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +189 -0
  9. data/Rakefile +18 -0
  10. data/bin/metro +16 -0
  11. data/changelog.md +157 -0
  12. data/lib/assets/menu-movement.wav +0 -0
  13. data/lib/assets/menu-selection.wav +0 -0
  14. data/lib/assets/missing.ogg +0 -0
  15. data/lib/assets/missing.png +0 -0
  16. data/lib/assets/missing.wav +0 -0
  17. data/lib/assets/missing_animation.png +0 -0
  18. data/lib/commands/generate_game.rb +13 -0
  19. data/lib/commands/generate_model.rb +25 -0
  20. data/lib/commands/generate_scene.rb +36 -0
  21. data/lib/commands/generate_view.rb +21 -0
  22. data/lib/commands/thor.rb +83 -0
  23. data/lib/core_ext/class.rb +14 -0
  24. data/lib/core_ext/numeric.rb +59 -0
  25. data/lib/gosu_ext/color.rb +62 -0
  26. data/lib/gosu_ext/gosu_constants.rb +53 -0
  27. data/lib/locale/en.yml +35 -0
  28. data/lib/locale/locale.rb +1 -0
  29. data/lib/metro.rb +140 -0
  30. data/lib/metro/animation.rb +135 -0
  31. data/lib/metro/animation/after_interval_factory.rb +12 -0
  32. data/lib/metro/animation/animation_factory.rb +15 -0
  33. data/lib/metro/animation/easing/ease_in.rb +15 -0
  34. data/lib/metro/animation/easing/easing.rb +51 -0
  35. data/lib/metro/animation/easing/linear.rb +15 -0
  36. data/lib/metro/animation/has_animations.rb +70 -0
  37. data/lib/metro/animation/implicit_animation.rb +100 -0
  38. data/lib/metro/animation/on_update_operation.rb +96 -0
  39. data/lib/metro/animation/scene_animation.rb +16 -0
  40. data/lib/metro/asset_path.rb +97 -0
  41. data/lib/metro/events/control_definition.rb +11 -0
  42. data/lib/metro/events/controls.rb +42 -0
  43. data/lib/metro/events/event_data.rb +60 -0
  44. data/lib/metro/events/event_dictionary.rb +52 -0
  45. data/lib/metro/events/event_factory.rb +17 -0
  46. data/lib/metro/events/event_relay.rb +300 -0
  47. data/lib/metro/events/event_state_manager.rb +63 -0
  48. data/lib/metro/events/events.rb +3 -0
  49. data/lib/metro/events/has_events.rb +108 -0
  50. data/lib/metro/events/hit_list.rb +75 -0
  51. data/lib/metro/events/unknown_sender.rb +5 -0
  52. data/lib/metro/font.rb +69 -0
  53. data/lib/metro/game.rb +102 -0
  54. data/lib/metro/game/dsl.rb +68 -0
  55. data/lib/metro/image.rb +68 -0
  56. data/lib/metro/logging.rb +33 -0
  57. data/lib/metro/missing_scene.rb +21 -0
  58. data/lib/metro/models/audio/song.rb +33 -0
  59. data/lib/metro/models/draws.rb +86 -0
  60. data/lib/metro/models/key_value_coding.rb +38 -0
  61. data/lib/metro/models/model.rb +236 -0
  62. data/lib/metro/models/model_factory.rb +32 -0
  63. data/lib/metro/models/models.rb +62 -0
  64. data/lib/metro/models/properties/animation_property.rb +115 -0
  65. data/lib/metro/models/properties/array_property.rb +24 -0
  66. data/lib/metro/models/properties/boolean_property.rb +27 -0
  67. data/lib/metro/models/properties/color_property.rb +116 -0
  68. data/lib/metro/models/properties/dimensions_property.rb +84 -0
  69. data/lib/metro/models/properties/font_property.rb +130 -0
  70. data/lib/metro/models/properties/image_property.rb +96 -0
  71. data/lib/metro/models/properties/model_property.rb +84 -0
  72. data/lib/metro/models/properties/numeric_property.rb +29 -0
  73. data/lib/metro/models/properties/options_property/no_option.rb +29 -0
  74. data/lib/metro/models/properties/options_property/options.rb +94 -0
  75. data/lib/metro/models/properties/options_property/options_property.rb +125 -0
  76. data/lib/metro/models/properties/position_property.rb +90 -0
  77. data/lib/metro/models/properties/property.rb +221 -0
  78. data/lib/metro/models/properties/property_owner.rb +137 -0
  79. data/lib/metro/models/properties/sample_property.rb +84 -0
  80. data/lib/metro/models/properties/scale_property.rb +80 -0
  81. data/lib/metro/models/properties/song_property.rb +89 -0
  82. data/lib/metro/models/properties/text_property.rb +75 -0
  83. data/lib/metro/models/ui/animated_sprite.rb +85 -0
  84. data/lib/metro/models/ui/border.rb +95 -0
  85. data/lib/metro/models/ui/fps.rb +54 -0
  86. data/lib/metro/models/ui/generic.rb +66 -0
  87. data/lib/metro/models/ui/grid_drawer.rb +74 -0
  88. data/lib/metro/models/ui/image.rb +87 -0
  89. data/lib/metro/models/ui/label.rb +175 -0
  90. data/lib/metro/models/ui/menu.rb +214 -0
  91. data/lib/metro/models/ui/model_label.rb +65 -0
  92. data/lib/metro/models/ui/model_labeler.rb +79 -0
  93. data/lib/metro/models/ui/rectangle.rb +59 -0
  94. data/lib/metro/models/ui/sprite.rb +79 -0
  95. data/lib/metro/models/ui/tile_map.rb +162 -0
  96. data/lib/metro/models/ui/ui.rb +13 -0
  97. data/lib/metro/parameters/command_line_args_parser.rb +68 -0
  98. data/lib/metro/parameters/options.rb +25 -0
  99. data/lib/metro/parameters/parameters.rb +2 -0
  100. data/lib/metro/sample.rb +40 -0
  101. data/lib/metro/scene.rb +477 -0
  102. data/lib/metro/scenes.rb +154 -0
  103. data/lib/metro/song.rb +56 -0
  104. data/lib/metro/template_message.rb +60 -0
  105. data/lib/metro/transitions/edit_transition_scene.rb +100 -0
  106. data/lib/metro/transitions/fade_transition_scene.rb +66 -0
  107. data/lib/metro/transitions/scene_transitions.rb +44 -0
  108. data/lib/metro/transitions/transition_scene.rb +19 -0
  109. data/lib/metro/units/bounds.rb +8 -0
  110. data/lib/metro/units/calculation_validations.rb +74 -0
  111. data/lib/metro/units/dimensions.rb +60 -0
  112. data/lib/metro/units/point.rb +51 -0
  113. data/lib/metro/units/rectangle_bounds.rb +85 -0
  114. data/lib/metro/units/scale.rb +46 -0
  115. data/lib/metro/units/units.rb +6 -0
  116. data/lib/metro/version.rb +32 -0
  117. data/lib/metro/views/json_view.rb +60 -0
  118. data/lib/metro/views/no_view.rb +34 -0
  119. data/lib/metro/views/parsers.rb +42 -0
  120. data/lib/metro/views/scene_view.rb +107 -0
  121. data/lib/metro/views/view.rb +133 -0
  122. data/lib/metro/views/writers.rb +43 -0
  123. data/lib/metro/views/yaml_view.rb +94 -0
  124. data/lib/metro/window.rb +94 -0
  125. data/lib/setup_handlers/exit_if_dry_run.rb +26 -0
  126. data/lib/setup_handlers/game_execution.rb +65 -0
  127. data/lib/setup_handlers/load_game_configuration.rb +65 -0
  128. data/lib/setup_handlers/load_game_files.rb +101 -0
  129. data/lib/setup_handlers/move_to_game_directory.rb +25 -0
  130. data/lib/setup_handlers/reload_game_on_game_file_changes.rb +79 -0
  131. data/lib/templates/game/README.md.tt +52 -0
  132. data/lib/templates/game/assets/brand.jpg +0 -0
  133. data/lib/templates/game/assets/hero.png +0 -0
  134. data/lib/templates/game/lib/custom_easing.rb +32 -0
  135. data/lib/templates/game/metro.tt +63 -0
  136. data/lib/templates/game/models/hero.rb +62 -0
  137. data/lib/templates/game/scenes/brand_scene.rb +19 -0
  138. data/lib/templates/game/scenes/brand_to_title_scene.rb +13 -0
  139. data/lib/templates/game/scenes/first_scene.rb +28 -0
  140. data/lib/templates/game/scenes/game_scene.rb +43 -0
  141. data/lib/templates/game/scenes/title_scene.rb +15 -0
  142. data/lib/templates/game/views/brand.yaml +4 -0
  143. data/lib/templates/game/views/brand_to_title.yaml +8 -0
  144. data/lib/templates/game/views/first.yaml +26 -0
  145. data/lib/templates/game/views/title.yaml +11 -0
  146. data/lib/templates/message.erb +23 -0
  147. data/lib/templates/model.rb.tt +111 -0
  148. data/lib/templates/scene.rb.tt +140 -0
  149. data/lib/templates/view.yaml.tt +11 -0
  150. data/lib/tmxed_ext/tile_set.rb +34 -0
  151. data/metro.gemspec +56 -0
  152. data/spec/core_ext/numeric_spec.rb +78 -0
  153. data/spec/core_ext/string_spec.rb +33 -0
  154. data/spec/gosu_ext/color_spec.rb +80 -0
  155. data/spec/metro/events/event_state_manager_spec.rb +5 -0
  156. data/spec/metro/models/key_value_coding_spec.rb +61 -0
  157. data/spec/metro/models/properties/array_property_spec.rb +60 -0
  158. data/spec/metro/models/properties/color_property_spec.rb +85 -0
  159. data/spec/metro/models/properties/dimensions_spec.rb +29 -0
  160. data/spec/metro/models/properties/font_property_spec.rb +127 -0
  161. data/spec/metro/models/properties/numeric_property_spec.rb +46 -0
  162. data/spec/metro/models/properties/options_property/no_option_spec.rb +25 -0
  163. data/spec/metro/models/properties/options_property/options_property_spec.rb +133 -0
  164. data/spec/metro/models/properties/options_property/options_spec.rb +125 -0
  165. data/spec/metro/models/properties/position_property_spec.rb +90 -0
  166. data/spec/metro/models/ui/label_spec.rb +259 -0
  167. data/spec/metro/parameters/command_line_args_parser_spec.rb +42 -0
  168. data/spec/metro/scene_spec.rb +15 -0
  169. data/spec/metro/scene_views/json_view_spec.rb +27 -0
  170. data/spec/metro/scene_views/yaml_view_spec.rb +38 -0
  171. data/spec/metro/scenes_spec.rb +77 -0
  172. data/spec/metro/units/point_spec.rb +132 -0
  173. data/spec/metro/views/view_spec.rb +53 -0
  174. data/spec/setup_handlers/exit_if_dry_run_spec.rb +27 -0
  175. data/spec/setup_handlers/reload_game_on_game_file_changes_spec.rb +68 -0
  176. data/spec/spec_helper.rb +20 -0
  177. metadata +374 -0
@@ -0,0 +1,125 @@
1
+ require 'spec_helper'
2
+
3
+ describe Metro::Model::OptionsProperty::Options do
4
+
5
+ describe "ClassMethods" do
6
+ describe "#empty" do
7
+ it "should generate an empty set of options" do
8
+ described_class.empty.should be_kind_of described_class
9
+ end
10
+ end
11
+ end
12
+
13
+ subject { described_class.new [ :a, :b ] }
14
+
15
+ describe "#current_selected_index" do
16
+ it "should by default be 0" do
17
+ subject.current_selected_index.should eq 0
18
+ end
19
+
20
+ context "when the value is set to negative value" do
21
+ let(:expected_index) { subject.count - 1 }
22
+
23
+ it "should set the current_selected_index to the last item" do
24
+ subject.current_selected_index = -1
25
+ subject.current_selected_index.should eq expected_index
26
+ end
27
+ end
28
+
29
+ context "when the value is set to a value greater than the count" do
30
+ let(:expected_index) { 0 }
31
+
32
+ it "should set the current_selected_index to the first item" do
33
+ subject.current_selected_index = 4
34
+ subject.current_selected_index.should eq expected_index
35
+ end
36
+ end
37
+ end
38
+
39
+ describe "#next!" do
40
+ before do
41
+ subject.current_selected_index = 0
42
+ end
43
+
44
+ let(:expected_index) { 1 }
45
+
46
+ it "should move the index to the next item" do
47
+ subject.next!
48
+ subject.current_selected_index.should eq expected_index
49
+ end
50
+
51
+ context "when next will pass the last item" do
52
+ before do
53
+ subject.current_selected_index = (subject.count - 1)
54
+ end
55
+
56
+ let(:expected_index) { 0 }
57
+
58
+ it "should return to the first item" do
59
+ subject.next!
60
+ subject.current_selected_index.should eq expected_index
61
+ end
62
+ end
63
+ end
64
+
65
+ describe "#previous!" do
66
+ before do
67
+ subject.current_selected_index = 1
68
+ end
69
+
70
+ let(:expected_index) { 0 }
71
+
72
+ it "should move to the item previous of the current one" do
73
+ subject.previous!
74
+ subject.current_selected_index.should eq expected_index
75
+ end
76
+
77
+ context "when previous! will move before the first item" do
78
+ let(:expected_index) { subject.count - 1 }
79
+
80
+ it "should return to the last item" do
81
+ subject.previous!
82
+ subject.previous!
83
+ subject.current_selected_index.should eq expected_index
84
+ end
85
+ end
86
+ end
87
+
88
+ describe "#selected" do
89
+ context "when their are options defined" do
90
+ let(:expected_selected) { subject[subject.current_selected_index] }
91
+
92
+ it "should return the item at the current_selected index" do
93
+ subject.selected.should eq expected_selected
94
+ end
95
+ end
96
+
97
+ context "when there are no options defined" do
98
+ subject { described_class.new [] }
99
+
100
+ it "should return a NoOption" do
101
+ subject.selected.should be_kind_of Metro::Model::OptionsProperty::NoOption
102
+ end
103
+ end
104
+ end
105
+
106
+ describe "#selected_action" do
107
+ context "when there are options defined" do
108
+ subject { described_class.new [ mock('first-option',properties: { action: expected_action }), mock('second-option') ] }
109
+ let(:expected_action) { :execute_this_action }
110
+
111
+ it "should return the action defined on the current selected item" do
112
+ subject.selected_action.should eq expected_action
113
+ end
114
+ end
115
+
116
+ context "when there are no options defined" do
117
+ subject { described_class.new [] }
118
+
119
+ it "should return the action on the NoOption" do
120
+ subject.selected_action.should eq :missing_menu_action
121
+ end
122
+ end
123
+ end
124
+
125
+ end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ describe Metro::Model::PositionProperty do
4
+
5
+ subject { described_class.new model }
6
+ let(:model) { "model" }
7
+
8
+ describe "#get" do
9
+
10
+ context "when the value is nil" do
11
+ context "when no default value has been specified" do
12
+
13
+ let(:expected_position) { Point.at 0.0, 0.0 }
14
+
15
+ it "should return the default position" do
16
+ subject.get(nil).should eq expected_position
17
+ end
18
+ end
19
+
20
+ context "when a default value has been specified" do
21
+
22
+ subject { described_class.new model, default: expected_position }
23
+ let(:expected_position) { Point.at 4.0, 3.3 }
24
+
25
+ it "should return the specified default position" do
26
+ subject.get(nil).should eq expected_position
27
+ end
28
+ end
29
+ end
30
+
31
+ context "when the value is a string" do
32
+
33
+ let(:point) { "22.0,33.0" }
34
+ let(:expected_position) { Point.at 22.0, 33.0 }
35
+
36
+ it "should return the position" do
37
+ subject.get(point).should eq expected_position
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+
44
+ describe "#set" do
45
+
46
+ context "when the value is nil" do
47
+ context "when no default value has been specified" do
48
+
49
+ let(:expected_position) { "0.0,0.0,0.0" }
50
+
51
+ it "should return the default position" do
52
+ subject.set(nil).should eq expected_position
53
+ end
54
+ end
55
+
56
+ context "when a default value has been specified" do
57
+
58
+ subject { described_class.new model, default: default_point }
59
+ let(:default_point) { Point.at 12, 24 }
60
+ let(:expected_position) { "12.0,24.0,0.0" }
61
+
62
+ it "should return the specified default position" do
63
+ subject.set(nil).should eq expected_position
64
+ end
65
+ end
66
+ end
67
+
68
+ context "when the value is a point" do
69
+
70
+ let(:point) { Point.at 10.0, 20.0 }
71
+ let(:expected_position) { "10.0,20.0,0.0" }
72
+
73
+ it "should return the same position" do
74
+ subject.set(point).should eq expected_position
75
+ end
76
+ end
77
+
78
+ context "when the value is a string" do
79
+
80
+ let(:point) { "22.0,33.0" }
81
+ let(:expected_position) { "22.0,33.0,0.0" }
82
+
83
+ it "should return the position" do
84
+ subject.set(point).should eq expected_position
85
+ end
86
+ end
87
+
88
+ end
89
+
90
+ end
@@ -0,0 +1,259 @@
1
+ require 'spec_helper'
2
+
3
+ describe Metro::UI::Label do
4
+
5
+ subject do
6
+ label = described_class.new text: expected_text
7
+ label.window = mock('window')
8
+ label
9
+ end
10
+
11
+ before do
12
+ # Reset the position of the label to the default
13
+ subject.position = nil
14
+ subject.scale = Scale.one
15
+ end
16
+
17
+ let(:expected_position) { Point.zero }
18
+ its(:position) { should eq expected_position }
19
+
20
+ its(:x) { should eq expected_position.x }
21
+ its(:y) { should eq expected_position.y }
22
+ its(:z) { should eq expected_position.z }
23
+ its(:z_order) { should eq expected_position.z_order }
24
+
25
+ context "when setting the position" do
26
+
27
+ it "should be set succesfully" do
28
+ subject.position = "10,10"
29
+ subject.position.should eq Point.at(10,10)
30
+ end
31
+
32
+ context "when setting the x property" do
33
+ let(:expected_x) { 11 }
34
+ let(:expected_y) { 0 }
35
+
36
+ it "should update successfully" do
37
+ subject.x = expected_x
38
+ subject.x.should eq expected_x
39
+ subject.position.x.should eq expected_x
40
+ end
41
+
42
+ it "should not effect the paired y property" do
43
+ subject.x = expected_x
44
+ subject.y.should eq expected_y
45
+ subject.position.y.should eq expected_y
46
+ end
47
+ end
48
+
49
+ context "when setting the y property" do
50
+ before do
51
+ subject.position = "#{expected_x},#{expected_y}"
52
+ end
53
+
54
+ let(:expected_x) { 320 }
55
+ let(:expected_y) { 66 }
56
+
57
+ it "should update successfully" do
58
+ subject.y = expected_y
59
+ subject.y.should eq expected_y
60
+ subject.position.y.should eq expected_y
61
+ end
62
+
63
+ it "should not effect the paired x property" do
64
+ subject.y = expected_y
65
+ subject.x.should eq expected_x
66
+ end
67
+ end
68
+
69
+ end
70
+
71
+ let(:expected_color) { Gosu::Color.new "rgb(255,255,255)" }
72
+ let(:expected_alpha) { 255 }
73
+
74
+ its(:color) { should eq expected_color }
75
+ its(:alpha) { should eq expected_alpha }
76
+
77
+ describe "font" do
78
+ before do
79
+ Metro::Font.stub(:find_or_create).and_return(font)
80
+ end
81
+
82
+ let(:font) { mock('font', name: expected_font_name, size: expected_font_size) }
83
+
84
+ let(:expected_font) { font }
85
+ its(:font) { should eq expected_font }
86
+
87
+ let(:expected_font_name) { 'mock_font_name' }
88
+ its(:font_name) { should eq expected_font_name }
89
+
90
+ let(:expected_font_size) { 12.0 }
91
+ its(:font_size) { should eq expected_font_size }
92
+
93
+ end
94
+
95
+ let(:expected_scale) { Scale.one }
96
+
97
+ its(:scale) { should eq expected_scale }
98
+ its(:x_factor) { should eq expected_scale.x_factor }
99
+ its(:y_factor) { should eq expected_scale.y_factor }
100
+
101
+ context "when setting the scale" do
102
+ it "should be set successfully" do
103
+ subject.x_factor = 2.0
104
+ subject.x_factor.should eq 2.0
105
+ subject.scale.x_factor.should eq 2.0
106
+ end
107
+ end
108
+
109
+ its(:align) { should eq expected_horizontal_alignment }
110
+ let(:expected_horizontal_alignment) { "left" }
111
+
112
+ its(:vertical_align) { should eq expected_vertical_alignment }
113
+ let(:expected_vertical_alignment) { "top" }
114
+
115
+ its(:text) { should eq expected_text }
116
+ let(:expected_text) { "Four Score and Seven Years Ago" }
117
+
118
+ context "when the text defines multiple lines (lines separated by newline characters)" do
119
+
120
+ let(:given_text) { "My name is something that takes\ntwo lines to express!" }
121
+ let(:first_line) { given_text.split("\n").first }
122
+ let(:last_line) { given_text.split("\n").last }
123
+
124
+ let(:x_position) { 320 }
125
+ let(:y_position) { 200 }
126
+ let(:z_order) { 12 }
127
+
128
+ let(:scale_x) { 1.0 }
129
+ let(:scale_y) { 1.0 }
130
+
131
+ let(:font) { mock('font') }
132
+
133
+ let(:line_height) { 20 }
134
+
135
+ before do
136
+ subject.text = given_text
137
+ subject.position = Point.at(x_position,y_position,z_order)
138
+ subject.scale = Scale.to(scale_x,scale_y)
139
+ subject.stub(:font).and_return(font)
140
+ subject.stub(:line_height) { line_height }
141
+ end
142
+
143
+ it "should have the font draw each of the lines" do
144
+ font.should_receive(:draw).twice
145
+ subject.draw
146
+ end
147
+
148
+ context "when the horizontal alignment is center" do
149
+
150
+ before do
151
+ subject.align = "center"
152
+ subject.vertical_align = "top"
153
+ subject.stub(:line_width).with(first_line) { 60 }
154
+ subject.stub(:line_width).with(last_line) { 42 }
155
+ end
156
+
157
+ let(:first_line_x_position) { x_position - 30 }
158
+ let(:second_line_x_position) { x_position - 21 }
159
+
160
+ let(:first_line_y_position) { y_position }
161
+ let(:second_line_y_position) { y_position + line_height }
162
+
163
+ it "should draw the lines correctly based on their on their respective widths" do
164
+ font.should_receive(:draw).with(first_line,first_line_x_position,first_line_y_position,z_order,scale_x,scale_y,an_instance_of(Gosu::Color))
165
+ font.should_receive(:draw).with(last_line,second_line_x_position,second_line_y_position,z_order,scale_x,scale_y,an_instance_of(Gosu::Color))
166
+ subject.draw
167
+ end
168
+
169
+ end
170
+
171
+ context "when the horizontal alignment is right" do
172
+
173
+ before do
174
+ subject.align = "right"
175
+ subject.vertical_align = "top"
176
+ subject.stub(:line_width).with(first_line) { 60 }
177
+ subject.stub(:line_width).with(last_line) { 42 }
178
+ end
179
+
180
+ let(:first_line_x_position) { x_position - 60 }
181
+ let(:second_line_x_position) { x_position - 42 }
182
+
183
+ let(:first_line_y_position) { y_position }
184
+ let(:second_line_y_position) { y_position + line_height }
185
+
186
+ it "should draw the lines correctly based on their on their respective widths" do
187
+ font.should_receive(:draw).with(first_line,first_line_x_position,first_line_y_position,z_order,scale_x,scale_y,an_instance_of(Gosu::Color))
188
+ font.should_receive(:draw).with(last_line,second_line_x_position,second_line_y_position,z_order,scale_x,scale_y,an_instance_of(Gosu::Color))
189
+ subject.draw
190
+ end
191
+
192
+ end
193
+
194
+ context "when the vertical alignment is top" do
195
+
196
+ before do
197
+ subject.vertical_align = "top"
198
+ end
199
+
200
+ let(:first_line_y_position) { y_position }
201
+ let(:second_line_y_position) { y_position + line_height }
202
+
203
+ it "should draw the first line at the y position" do
204
+ font.should_receive(:draw).with(first_line,x_position,first_line_y_position,z_order,scale_x,scale_y,an_instance_of(Gosu::Color))
205
+ font.should_receive(:draw).with(last_line,x_position,second_line_y_position,z_order,scale_x,scale_y,an_instance_of(Gosu::Color))
206
+ subject.draw
207
+ end
208
+
209
+ end
210
+
211
+ context "when the vertical alignment is center" do
212
+
213
+ before do
214
+ subject.text = text
215
+ subject.vertical_align = "center"
216
+ end
217
+
218
+ let(:text) { "Three Lines\nOf Text\nWill Create Fun!" }
219
+
220
+
221
+ let(:first_line) { text.split("\n")[0] }
222
+ let(:second_line) { text.split("\n")[1] }
223
+ let(:third_line) { text.split("\n")[2] }
224
+
225
+
226
+ let(:first_line_y_position) { y_position - line_height - line_height / 2 }
227
+ let(:second_line_y_position) { y_position - line_height / 2 }
228
+ let(:third_line_y_position) { y_position + line_height / 2 }
229
+
230
+ it "should draw the first line at the y position" do
231
+ font.should_receive(:draw).with(first_line,x_position,first_line_y_position,z_order,scale_x,scale_y,an_instance_of(Gosu::Color))
232
+ font.should_receive(:draw).with(second_line,x_position,second_line_y_position,z_order,scale_x,scale_y,an_instance_of(Gosu::Color))
233
+ font.should_receive(:draw).with(third_line,x_position,third_line_y_position,z_order,scale_x,scale_y,an_instance_of(Gosu::Color))
234
+ subject.draw
235
+ end
236
+
237
+ end
238
+
239
+ context "when the vertical alignment is bottom" do
240
+
241
+ before do
242
+ subject.vertical_align = "bottom"
243
+ end
244
+
245
+ let(:first_line_y_position) { y_position - line_height * 2 }
246
+ let(:second_line_y_position) { y_position - line_height }
247
+
248
+ it "should draw the first line at the y position" do
249
+ font.should_receive(:draw).with(first_line,x_position,first_line_y_position,z_order,scale_x,scale_y,an_instance_of(Gosu::Color))
250
+ font.should_receive(:draw).with(last_line,x_position,second_line_y_position,z_order,scale_x,scale_y,an_instance_of(Gosu::Color))
251
+ subject.draw
252
+ end
253
+
254
+ end
255
+
256
+ end
257
+
258
+
259
+ end