pentix 1.0.0

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/lib/status.rb ADDED
@@ -0,0 +1,110 @@
1
+ #
2
+ # This class handles the game status and things like
3
+ # the next figure, the score and so one
4
+ #
5
+ # Copyright (C) 2011 Nikolay Nemshilov
6
+ #
7
+ class Status
8
+ attr_accessor :figure, :pos_x, :pos_y, :level, :lines, :figures, :score
9
+
10
+ HEAD_FONT = ['Courier', Block::SIZE + 5, Color::GRAY].freeze
11
+ TEXT_FONT = ['Courier New', Block::SIZE, Color::GRAY].freeze
12
+ TEXT_WIDTH = 22 # chars
13
+
14
+ SCORING_SYSTEM = {
15
+ 1 => 100,
16
+ 2 => 300,
17
+ 3 => 500,
18
+ 4 => 800,
19
+ 5 => 1200
20
+ }
21
+
22
+ LEVELUP = 10 # the number of lines to level up
23
+
24
+ def initialize(window, x, y)
25
+ @pos_x = x
26
+ @pos_y = y
27
+
28
+ @head_font = Font.new(window, HEAD_FONT[0], HEAD_FONT[1])
29
+ @text_font = Font.new(window, TEXT_FONT[0], TEXT_FONT[1])
30
+
31
+ reset!
32
+ end
33
+
34
+ def draw
35
+ draw_head "Next:", 0
36
+ @figure.pos_x = @pos_x
37
+ @figure.pos_y = @pos_y + 2
38
+ @figure.draw
39
+
40
+ draw_head "Score:", 9
41
+ draw_text "Level", @level, 10
42
+ draw_text "Score", @score, 11
43
+ draw_text "Lines", @lines, 12
44
+ draw_text "Figures", @figures, 13
45
+
46
+ draw_head "Winnars:", 18
47
+ @records.each_with_index do |entry, i|
48
+ draw_text entry[0], entry[1], 19 + i
49
+ end
50
+ end
51
+
52
+ def reset!
53
+ @level = 1
54
+ @lines = 0
55
+ @score = 0
56
+ @figures = 0
57
+
58
+ # the next levelup lines num
59
+ @levelup = LEVELUP
60
+
61
+ @records = Records.top(6)
62
+ end
63
+
64
+ def count_drop(figure)
65
+ if figure.distance > 0
66
+ @score += figure.distance * @level
67
+ @figures += 1
68
+ end
69
+ end
70
+
71
+ def count_kill(lines)
72
+ if lines.size > 0
73
+ @score += SCORING_SYSTEM[lines.size] * @level
74
+ @lines += lines.size
75
+
76
+ if @lines >= @levelup
77
+ @level += 1
78
+ @levelup = @lines + LEVELUP - @lines % LEVELUP
79
+ end
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ #
86
+ # A shortcut to draw a header text
87
+ #
88
+ def draw_head(text, pos)
89
+ @head_font.draw(
90
+ text, @pos_x * Block::SIZE,
91
+ (@pos_y + pos) * Block::SIZE - 5, # -5 is to shift the too large font a bit
92
+ 0, 1.0, 1.0, HEAD_FONT[2]
93
+ )
94
+ end
95
+
96
+ #
97
+ # A shortcut to draw a normal text
98
+ #
99
+ def draw_text(text, value, pos)
100
+ value = "..#{value}"
101
+ text = text.slice(0, TEXT_WIDTH - value.size)
102
+
103
+ @text_font.draw(
104
+ text.ljust(TEXT_WIDTH - value.size, '.') + value,
105
+ @pos_x * Block::SIZE, (@pos_y + pos) * Block::SIZE,
106
+ 0, 1.0, 1.0, TEXT_FONT[2]
107
+ )
108
+ end
109
+
110
+ end
data/media/block.png ADDED
Binary file
data/pentix.rb ADDED
@@ -0,0 +1,22 @@
1
+ #
2
+ # The main script
3
+ #
4
+ # Copyright (C) 2011 Nikolay Nemshilov
5
+ #
6
+
7
+ $LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
8
+
9
+ require 'gosu'
10
+ include Gosu
11
+
12
+ require 'block'
13
+ require 'figure'
14
+ require 'glass'
15
+ require 'status'
16
+ require 'controls'
17
+ require 'records'
18
+ require 'finish'
19
+ require 'game'
20
+
21
+
22
+ Game.new.show if $0 == __FILE__
@@ -0,0 +1,32 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ describe Block do
4
+ before :all do
5
+ @window = DummyWindow.new
6
+ @i_args = [@window, 'media/block.png', true]
7
+ @image = Image.new(*@i_args)
8
+ end
9
+
10
+ it "should instance only one image" do
11
+ Image.should_receive(:new).with(*@i_args).once.and_return(@image)
12
+
13
+ @block1 = Block.new(@window, Color::WHITE)
14
+ @block2 = Block.new(@window, Color::WHITE)
15
+ @block3 = Block.new(@window, Color::WHITE)
16
+ end
17
+
18
+ it "should allow access to the block color" do
19
+ Block.new(@window, Color::WHITE).color.should == Color::WHITE
20
+ Block.new(@window, Color::GREEN).color.should == Color::GREEN
21
+ end
22
+
23
+ it "should draw the block in the given position with assigned color" do
24
+ @color = Color::BLUE
25
+ @pos_x = 10
26
+ @pos_y = 20
27
+
28
+ @image.should_receive(:draw).with(@pos_x * Block::SIZE, @pos_y * Block::SIZE, 0, 1.0, 1.0, @color)
29
+
30
+ Block.new(@window, @color).draw(@pos_x, @pos_y)
31
+ end
32
+ end
@@ -0,0 +1,13 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ describe Controls do
4
+ before :all do
5
+ @controls = Controls.new($test_window)
6
+ end
7
+
8
+ Controls::BUTTONS.each do |command, button|
9
+ it "should recognize the '#{command}' command" do
10
+ @controls.command_for(button).should == command
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,318 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ class DummyWindow
4
+ def show_next_figure
5
+ end
6
+ end
7
+
8
+ describe Figure do
9
+ before :all do
10
+ @window = DummyWindow.new
11
+
12
+ @window.glass = @glass = Glass.new(@window, 1, 2)
13
+ @window.status = @status = Status.new(@window, 20, 2)
14
+ end
15
+
16
+ describe "initialization" do
17
+
18
+ describe "by name" do
19
+ before do
20
+ @name = :stairs
21
+ @color = Figure::COLORS[Figure::FIGURES[@name].split('|').last.to_sym]
22
+ @figure = Figure.new(@window, @name)
23
+ end
24
+
25
+ it "should assign the figure name" do
26
+ @figure.name.should == @name
27
+ end
28
+
29
+ it "should set the right color" do
30
+ @figure.color.should == @color
31
+ end
32
+
33
+ it "should assign a correct matrix" do
34
+ @figure.should have_matrix(%Q{
35
+ |x. . |
36
+ |x.x. |
37
+ | .x.x|
38
+ })
39
+ end
40
+
41
+ it "should preset initial position 0:0" do
42
+ @figure.pos_x.should == 0
43
+ @figure.pos_y.should == 0
44
+ end
45
+
46
+ it "should preset the figure sizes" do
47
+ @figure.size_x.should == 3
48
+ @figure.size_y.should == 3
49
+ end
50
+ end
51
+
52
+ it "should instance random figures if called without a name" do
53
+ [
54
+ Figure.new(@window),
55
+ Figure.new(@window),
56
+ Figure.new(@window),
57
+ Figure.new(@window),
58
+ Figure.new(@window)
59
+ ].map(&:name).uniq.size.should > 1
60
+ end
61
+
62
+ end
63
+
64
+ describe "#draw" do
65
+
66
+ it "should correctly render the cross figure" do
67
+ Figure.new(@window, :cross).should render_blocks(%Q{
68
+ | .x. |
69
+ |x.x.x|
70
+ | .x. |
71
+ })
72
+ end
73
+
74
+ it "should correctly render the stairs figure" do
75
+ Figure.new(@window, :stairs).should render_blocks(%Q{
76
+ |x. . |
77
+ |x.x. |
78
+ | .x.x|
79
+ })
80
+ end
81
+ end
82
+
83
+ describe "manipulations" do
84
+ before do
85
+ @pos_x = @glass.pos_x + 4
86
+ @pos_y = @glass.pos_y
87
+
88
+ @figure = Figure.new(@window, :l_crutch)
89
+ @figure.move_to(@pos_x, @pos_y)
90
+
91
+ @distance = 10
92
+ @glass.stub!(:spaces_below).and_return(@distance)
93
+ end
94
+
95
+ describe "#move_to" do
96
+ before do
97
+ @figure.move_to(10, 20)
98
+ end
99
+
100
+ it "should set the x-position" do
101
+ @figure.pos_x.should == 10
102
+ end
103
+
104
+ it "should set the y-position" do
105
+ @figure.pos_y.should == 20
106
+ end
107
+
108
+ it "should recalc the distance" do
109
+ @figure.distance.should == @distance
110
+ end
111
+ end
112
+
113
+ describe "#move_left" do
114
+ before do
115
+ @figure.move_left
116
+ end
117
+
118
+ it "should decrease the x-position by 1" do
119
+ @figure.pos_x.should == @pos_x - 1
120
+ end
121
+
122
+ it "should set the figure's distance" do
123
+ @figure.distance.should == @distance
124
+ end
125
+
126
+ it "should not move the figure beyond the left border" do
127
+ @pos_x = @figure.pos_x = @glass.pos_x + 1
128
+ @figure.move_left
129
+ @figure.pos_x.should == @pos_x
130
+ end
131
+ end
132
+
133
+ describe "#move_right" do
134
+ before do
135
+ @figure.move_right
136
+ end
137
+
138
+ it "should increase the x-position by 1" do
139
+ @figure.pos_x.should == @pos_x + 1
140
+ end
141
+
142
+ it "should set the figure's distance" do
143
+ @figure.distance.should == @distance
144
+ end
145
+
146
+ it "should not move the figure beyond the right border" do
147
+ @pos_x = @figure.pos_x = @glass.pos_x + Glass::WIDTH + 2 - @figure.size_x
148
+ @figure.move_right
149
+ @figure.pos_x.should == @pos_x
150
+ end
151
+ end
152
+
153
+ describe "#rotate_left" do
154
+ before do
155
+ @figure.turn_left
156
+ end
157
+
158
+ it "should rotate the matrix contr-clockwise" do
159
+ @figure.should have_matrix(%Q{
160
+ | .x. . |
161
+ |x.x.x.x|
162
+ })
163
+ @figure.turn_left
164
+ @figure.should have_matrix(%Q{
165
+ | .x|
166
+ | .x|
167
+ |x.x|
168
+ | .x|
169
+ })
170
+ @figure.turn_left
171
+ @figure.should have_matrix(%Q{
172
+ |x.x.x.x|
173
+ | . .x. |
174
+ })
175
+ @figure.turn_left
176
+ @figure.should have_matrix(%Q{
177
+ |x. |
178
+ |x.x|
179
+ |x. |
180
+ |x. |
181
+ })
182
+ end
183
+
184
+ it "should recalculate the matrix size" do
185
+ @figure.size_x.should == 4
186
+ @figure.size_y.should == 2
187
+
188
+ @figure.turn_left
189
+ @figure.size_x.should == 2
190
+ @figure.size_y.should == 4
191
+ end
192
+
193
+ it "should adjust figure's position to make it look centered" do
194
+ @figure.pos_x.should == @pos_x - 1
195
+ @figure.turn_left #making it vertical again
196
+ @figure.pos_x.should == @pos_x
197
+ end
198
+
199
+ it "should set the figure's distance" do
200
+ @figure.distance.should == @distance
201
+ end
202
+
203
+ it "should not turn the figure if there is no space for that" do
204
+ figure = Figure.new(@window, :h_stick)
205
+
206
+ # setting it vertically
207
+ figure.move_to(@glass.pos_x + 1, @glass.pos_y)
208
+ figure.turn_left
209
+ figure.should have_matrix(%Q{
210
+ |x|
211
+ |x|
212
+ |x|
213
+ |x|
214
+ |x|
215
+ })
216
+
217
+ # moving it to the left border
218
+ figure.move_to(@glass.pos_x + 1, @glass.pos_y)
219
+ figure.turn_left
220
+ figure.should have_matrix(%Q{
221
+ |x|
222
+ |x|
223
+ |x|
224
+ |x|
225
+ |x|
226
+ })
227
+ end
228
+ end
229
+
230
+ describe "#rotate_right" do
231
+ before do
232
+ @figure.turn_right
233
+ end
234
+
235
+ it "should rotate the matrix clockwise" do
236
+ @figure.should have_matrix(%Q{
237
+ |x.x.x.x|
238
+ | . .x. |
239
+ })
240
+ @figure.turn_right
241
+ @figure.should have_matrix(%Q{
242
+ | .x|
243
+ | .x|
244
+ |x.x|
245
+ | .x|
246
+ })
247
+ @figure.turn_right
248
+ @figure.should have_matrix(%Q{
249
+ | .x. . |
250
+ |x.x.x.x|
251
+ })
252
+ @figure.turn_right
253
+ @figure.should have_matrix(%Q{
254
+ |x. |
255
+ |x.x|
256
+ |x. |
257
+ |x. |
258
+ })
259
+ end
260
+
261
+ it "should recalculate the matrix size" do
262
+ @figure.size_x.should == 4
263
+ @figure.size_y.should == 2
264
+
265
+ @figure.turn_right
266
+ @figure.size_x.should == 2
267
+ @figure.size_y.should == 4
268
+ end
269
+
270
+ it "should adjust figure's position to make it look centered" do
271
+ @figure.pos_x.should == @pos_x - 1
272
+ @figure.turn_left #making it vertical again
273
+ @figure.pos_x.should == @pos_x
274
+ end
275
+
276
+ it "should set the figure's distance" do
277
+ @figure.distance.should == @distance
278
+ end
279
+
280
+ it "should not turn the figure if there is no space for that" do
281
+ figure = Figure.new(@window, :h_stick)
282
+
283
+ # setting it vertically
284
+ figure.move_to(@glass.pos_x + 1, @glass.pos_y)
285
+ figure.turn_right
286
+
287
+ # moving it to the left border
288
+ figure.move_to(@glass.pos_x + 1, @glass.pos_y)
289
+ figure.turn_right
290
+
291
+ figure.should have_matrix(%Q{
292
+ |x|
293
+ |x|
294
+ |x|
295
+ |x|
296
+ |x|
297
+ })
298
+ end
299
+ end
300
+ end
301
+
302
+ describe "#drop" do
303
+ before do
304
+ @figure = Figure.new(@window)
305
+ @figure.move_to(@glass.pos_x + 1, @glass.pos_y)
306
+ end
307
+
308
+ it "should call the glass to #glue_in the figure" do
309
+ @glass.should_receive(:glue_in).with(@figure)
310
+ @figure.drop
311
+ end
312
+
313
+ it "should call the @window to #show_next_figure" do
314
+ @window.should_receive(:show_next_figure)
315
+ @figure.drop
316
+ end
317
+ end
318
+ end
@@ -0,0 +1,4 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ describe Game do
4
+ end