-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathplayfield.e
396 lines (356 loc) · 10.3 KB
/
playfield.e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
note
description : "Manage the playing area of the game."
author : "Louis Marchand"
date : "July 19 2012"
revision : "1.0"
class
PLAYFIELD
create
make,
make_with_anim
feature {NONE} -- Initialization
make(l_x,l_y:INTEGER;l_block_width,l_block_height:NATURAL)
-- Initialization for `Current' starting at (`l_x',`l_y') and
-- of dimension `l_block_width' by `l_block_height' blocks.
local
i,j:INTEGER
line:ARRAYED_LIST[BLOCK]
do
x:=l_x
y:=l_y
block_height:=l_block_height.to_integer_32
block_width:=l_block_width.to_integer_32
create {ARRAYED_LIST[LIST[BLOCK]]} blocks_matrix.make(height.to_integer_32)
from
i:=1
until
i>height.to_integer_32
loop
create line.make (width.to_integer_32)
from
j:=1
until
j>width.to_integer_32
loop
line.extend (Void)
j:=j+1
end
blocks_matrix.extend (line)
i:=i+1
end
create {ARRAYED_LIST[INTEGER]} full_lines_index.make_filled (4)
nb_full_lines:=0
is_anim_enable:=false
end
make_with_anim(l_x,l_y:INTEGER;l_block_width,l_block_height:NATURAL;l_anim_surface:GAME_SURFACE;l_max_anim_value:NATURAL)
-- Initialization for `Current' starting at (`l_x',`l_y') and
-- of dimension `l_block_width' by `l_block_height' blocks,
-- used for automatic animation on `l_anim_surface' with
-- `l_max_anim_value' maximum update of the `Current'.
do
make(l_x,l_y,l_block_width,l_block_height)
anim_surface:=l_anim_surface
is_anim_enable:=true
max_anim_value:=l_max_anim_value
med_anim_value:=max_anim_value//2
end
feature -- Access
x:INTEGER
-- Horizontal coordinate of `Current'
y:INTEGER
-- Vertical coordinate of `Current'
width:NATURAL
-- The horizontal dimension of `Current'
once
Result:=10
end
height:NATURAL
-- The vertical dimension of `Current'
once
Result:=20
end
freeze_tetromino(l_tetromino:TETROMINO)
-- When `l_tetromino' is place on `Current', freeze it if
-- it cannot move anymore.
local
i,j,pos_y,pos_x:INTEGER
do
from
i:=1
until
i>4
loop
from
j:=1
until
j>4
loop
pos_y:=l_tetromino.y-(i-1)
pos_x:=l_tetromino.x+j-1
if l_tetromino.blocks_matrix.at (i).at (j)/=Void and then pos_y>0 and then pos_y<=height.to_integer_32 and then pos_x>0 and then pos_x<=width.to_integer_32 then
blocks_matrix.at (pos_y).at (pos_x):=l_tetromino.blocks_matrix.at (i).at (j)
end
j:=j+1
end
i:=i+1
end
end
print_playfield_with_tetromino(l_tetromino:TETROMINO;l_surface:GAME_SURFACE)
-- Show `Current' and the `l_tetromino' on `l_surface'
local
do
print_playfield(l_surface)
print_tetromino(l_tetromino,l_surface)
end
print_playfield_with_tetromino_and_ghost(l_tetromino,l_ghost:TETROMINO;l_surface:GAME_SURFACE)
-- Show `Current', the `l_tetromino' and the tetromino `l_ghost' on `l_surface'
local
do
print_playfield(l_surface)
print_tetromino(l_ghost,l_surface)
print_tetromino(l_tetromino,l_surface)
end
print_playfield_with_anim (l_surface: GAME_SURFACE;value:NATURAL)
-- Show the `value' iteration of the automatic animation
-- of `Current' in `l_surface'
require
Print_Playfield_With_Anim_Precent_Valid: value<=max_anim_value
Print_Playfield_With_Anim_List_Not_Void: anim_List/=Void
Print_Playfield_With_Anim_Enable: is_anim_enable
local
temp_x:INTEGER
do
print_playfield(l_surface)
if value>0 and value<max_anim_value then
from
anim_list.start
until
anim_list.exhausted
loop
if value<med_anim_value then
l_surface.draw_sub_surface (anim_list.item.surface, 0, 0, x, (height.to_integer_32-anim_list.item.line)*block_height+y, ((anim_list.item.surface.width.to_natural_32//med_anim_value)*value).to_integer_32, anim_list.item.surface.height)
else
temp_x:=((anim_list.item.surface.width.to_natural_32//med_anim_value)*(value-med_anim_value)).to_integer_32
l_surface.draw_sub_surface (anim_list.item.surface, temp_x, 0, x+temp_x, (height.to_integer_32-anim_list.item.line)*block_height+y, anim_list.item.surface.width-temp_x, anim_list.item.surface.height)
end
anim_list.forth
end
end
end
print_playfield(l_surface:GAME_SURFACE)
-- Show `Current' on `l_surface'
local
i,j:INTEGER
do
from
i:=1
until
i>height.to_integer_32
loop
from
j:=1
until
j>width.to_integer_32
loop
if blocks_matrix.at (i).at (j)/=Void then
l_surface.draw_surface (blocks_matrix.at (i).at (j).surface, (j-1)*block_width+x, (height.to_integer_32-i)*block_height+y)
end
j:=j+1
end
i:=i+1
end
end
print_tetromino(l_tetromino:TETROMINO;l_surface:GAME_SURFACE)
-- Show `l_tetromino' on `l_surface'
local
i,j,pos_y,pos_x:INTEGER
do
from
i:=1
until
i>4
loop
from
j:=1
until
j>4
loop
pos_y:=l_tetromino.y-(i-1)
pos_x:=j+l_tetromino.x-1
if l_tetromino.blocks_matrix.at (i).at (j)/=Void and then pos_x>0 and then pos_x<=width.to_integer_32 and then pos_y>0 and then pos_y<=height.to_integer_32 then
l_surface.draw_surface (l_tetromino.blocks_matrix.at (i).at (j).surface,(pos_x-1)*block_width+x,(height.to_integer_32-pos_y)*block_height+y)
end
j:=j+1
end
i:=i+1
end
end
detect_collision(l_tetromino:TETROMINO):BOOLEAN
-- `True' if `l_tetromino' has a collision with a {TETROMINO} of `Current' or
-- The edge of `Current'
local
i,j,pos_y,pos_x:INTEGER
do
Result:=false
from
i:=1
until
i>4 or else
Result=true
loop
from
j:=1
until
j>4 or else
Result=true
loop
pos_y:=l_tetromino.y-(i-1)
pos_x:=l_tetromino.x+j-1
if l_tetromino.blocks_matrix.at (i).at (j)/=Void and then
((pos_y<1) or else (pos_x>width.to_integer_32) or else (pos_x<1) or else
((pos_y<=height.to_integer_32) and then blocks_matrix.at (pos_y).at (pos_x)/=Void)) then
Result:=true
end
j:=j+1
end
i:=i+1
end
end
check_full_lines
local
i,j:INTEGER
is_hole:BOOLEAN
do
nb_full_lines:=0
from
i:=1
until
i>height.to_integer_32
loop
from
j:=1
is_hole:=false
until
is_hole or else
j>width.to_integer_32
loop
if blocks_matrix.at (i).at (j)=Void then
is_hole:=true
end
j:=j+1
end
if not is_hole then
nb_full_lines:=nb_full_lines+1
full_lines_index.at (nb_full_lines):=i
end
i:=i+1
end
end
remove_full_lines_block
-- Remove every block of a single line of `Current' if this one is
-- full.
local
i:INTEGER
do
from
i:=1
until
i>nb_full_lines
loop
blocks_matrix.go_i_th (full_lines_index.at (i))
from
blocks_matrix.item.start
until
blocks_matrix.item.exhausted
loop
blocks_matrix.item.replace (Void)
blocks_matrix.item.forth
end
i:=i+1
end
end
delete_full_line
-- Detect full lines of {BOLCK} and animate the suppression of this line.
local
i,j:INTEGER
line:ARRAYED_LIST[BLOCK]
do
from
i:=nb_full_lines
until
i<1
loop
blocks_matrix.go_i_th (full_lines_index.at (i))
blocks_matrix.remove
create line.make (width.to_integer_32)
from
j:=1
until
j>width.to_integer_32
loop
line.extend (Void)
j:=j+1
end
blocks_matrix.extend (line)
i:=i-1
end
nb_full_lines:=0
end
prepare_anim
-- Prepare the animation of the suppression of a full line of {BLOCK}
require
Prepare_Anim_Enable: is_anim_enable
do
create {LINKED_LIST[TUPLE[surface:GAME_SURFACE;line:INTEGER]]} anim_List.make
if nb_full_lines=1 then
anim_list.extend ([anim_surface.sub_surface (0, 0, block_width*width.to_integer_32, block_height),full_lines_index.first])
elseif nb_full_lines=2 then
if full_lines_index.at (1)+1=full_lines_index.at (2) then
anim_list.extend ([anim_surface.sub_surface (0, block_height, block_width*width.to_integer_32, block_height*2),full_lines_index.at(2)])
else
anim_list.extend ([anim_surface.sub_surface (0, block_height*3, block_width*width.to_integer_32, block_height),full_lines_index.at(2)])
anim_list.extend ([anim_surface.sub_surface (0, block_height*4, block_width*width.to_integer_32, block_height),full_lines_index.at(1)])
end
elseif nb_full_lines=3 then
if full_lines_index.at (1)+2=full_lines_index.at (3) then
anim_list.extend ([anim_surface.sub_surface (0, block_height*5, block_width*width.to_integer_32, block_height*3),full_lines_index.at(3)])
elseif full_lines_index.at (1)+1=full_lines_index.at (2) then
anim_list.extend ([anim_surface.sub_surface (0, block_height*8, block_width*width.to_integer_32, block_height),full_lines_index.at(3)])
anim_list.extend ([anim_surface.sub_surface (0, block_height*9, block_width*width.to_integer_32, block_height*2),full_lines_index.at(2)])
else
anim_list.extend ([anim_surface.sub_surface (0, block_height*11, block_width*width.to_integer_32, block_height*2),full_lines_index.at(3)])
anim_list.extend ([anim_surface.sub_surface (0, block_height*13, block_width*width.to_integer_32, block_height),full_lines_index.at(1)])
end
elseif nb_full_lines=4 then
anim_list.extend ([anim_surface.sub_surface (0, block_height*14, block_width*width.to_integer_32, block_height*4),full_lines_index.last])
end
end
clear_anim
-- Stop the `Current' full line animation.
require
Clear_Anim_Enable: is_anim_enable
do
anim_List:=Void
end
blocks_matrix:LIST[LIST[BLOCK]]
-- Every fixed {BOLCK} of `Current'
nb_full_lines:INTEGER
-- The number of line full of {BLOCK}
full_lines_index:LIST[INTEGER]
-- The indexes of every lines full of {BLOCK}
is_anim_enable:BOOLEAN
-- Is `Current' performing an automatic animation
anim_List:LIST[TUPLE[surface:GAME_SURFACE;line:INTEGER]]
-- The list of line to show in the automatic animation of `Current'
max_anim_value:NATURAL
-- Maximum number of iteration to show `Current'
med_anim_value:NATURAL
-- Medium number of iteration to show `Current'
feature {NONE} -- Implementation - Variables
block_width:INTEGER
-- The number of {BLOCK} in a line of `Current'
block_height:INTEGER
-- The number of {BLOCK} in a column of `Current'
anim_surface:GAME_SURFACE
-- The image used to draw `Current' when on automatic animation
end