@@ -113,51 +113,56 @@ fn main() {
113
113
let mut last_frame_time = time:: Instant :: now ( ) ;
114
114
let mut last_input_handled = time:: Instant :: now ( ) ;
115
115
116
- const BOARD_RECT : Rect = Rect {
117
- left : 1 ,
118
- top : 1 ,
119
- width : 10 ,
116
+ // standard tetris board size
117
+ const BOARD_WIDTH : i32 = 10 ;
118
+ const BOARD_HEIGHT : i32 = 20 ;
119
+
120
+ let ( window_height, window_width) = window. get_max_yx ( ) ;
121
+ let board_rect: Rect = Rect {
122
+ left : ( window_width / 2 ) - BOARD_WIDTH - 2 , // arrange the board on the left side of the middle of the screen
123
+ top : ( window_height - BOARD_HEIGHT ) / 2 , // center the board within the window
124
+ width : BOARD_WIDTH ,
120
125
height : 20 ,
121
126
} ;
122
127
123
- const BOARD_FRAME_RECT : Rect = Rect {
124
- left : BOARD_RECT . left - 1 ,
125
- top : BOARD_RECT . top - 1 ,
126
- width : BOARD_RECT . width + 2 ,
127
- height : BOARD_RECT . height + 2 ,
128
+ let board_frame_rect : Rect = Rect {
129
+ left : board_rect . left - 1 ,
130
+ top : board_rect . top - 1 ,
131
+ width : board_rect . width + 2 ,
132
+ height : board_rect . height + 2 ,
128
133
} ;
129
134
130
- const TITLE_RECT : Rect = Rect {
131
- left : BOARD_FRAME_RECT . right ( ) + 2 ,
132
- top : BOARD_FRAME_RECT . top ,
135
+ let title_rect : Rect = Rect {
136
+ left : board_frame_rect . right ( ) + 2 ,
137
+ top : board_frame_rect . top ,
133
138
width : ( TITLE . len ( ) + 4 ) as i32 ,
134
139
height : 3 ,
135
140
} ;
136
141
137
- const PREVIEW_FRAME_RECT : Rect = Rect {
138
- left : TITLE_RECT . left ,
139
- top : TITLE_RECT . bottom ( ) + 2 ,
142
+ let preview_frame_rect : Rect = Rect {
143
+ left : title_rect . left ,
144
+ top : title_rect . bottom ( ) + 2 ,
140
145
width : 6 ,
141
146
height : 6 ,
142
147
} ;
143
148
144
- const PREVIEW_RECT : Rect = Rect {
145
- left : PREVIEW_FRAME_RECT . left + 1 ,
146
- top : PREVIEW_FRAME_RECT . top + 1 ,
147
- width : PREVIEW_FRAME_RECT . width - 2 ,
148
- height : PREVIEW_FRAME_RECT . height - 2 ,
149
+ let preview_rect : Rect = Rect {
150
+ left : preview_frame_rect . left + 1 ,
151
+ top : preview_frame_rect . top + 1 ,
152
+ width : preview_frame_rect . width - 2 ,
153
+ height : preview_frame_rect . height - 2 ,
149
154
} ;
150
155
151
- const SCORE_FRAME_RECT : Rect = Rect {
152
- left : PREVIEW_FRAME_RECT . left ,
153
- top : PREVIEW_FRAME_RECT . bottom ( ) + 2 ,
156
+ let score_frame_rect : Rect = Rect {
157
+ left : preview_frame_rect . left ,
158
+ top : preview_frame_rect . bottom ( ) + 2 ,
154
159
width : 14 ,
155
160
height : 4 ,
156
161
} ;
157
162
158
163
let mut game_state = GameState :: new (
159
- BOARD_RECT . width ,
160
- BOARD_RECT . height ,
164
+ board_rect . width ,
165
+ board_rect . height ,
161
166
Box :: new ( ThreadRangeRng :: new ( ) ) ,
162
167
) ;
163
168
@@ -166,13 +171,15 @@ fn main() {
166
171
move_right : bool ,
167
172
rot_left : bool ,
168
173
rot_right : bool ,
174
+ drop : bool ,
169
175
}
170
176
171
177
let mut inputs = Inputs {
172
178
move_left : false ,
173
179
move_right : false ,
174
180
rot_left : false ,
175
181
rot_right : false ,
182
+ drop : false ,
176
183
} ;
177
184
178
185
let mut game_over_blit_timer = Option :: < time:: Instant > :: None ;
@@ -189,6 +196,7 @@ fn main() {
189
196
// check for movement inputs
190
197
'a' => inputs. move_left = true ,
191
198
'd' => inputs. move_right = true ,
199
+ 's' => inputs. drop = true ,
192
200
'j' => inputs. rot_left = true ,
193
201
'l' => inputs. rot_right = true ,
194
202
@@ -211,7 +219,7 @@ fn main() {
211
219
if inputs. move_right {
212
220
horizontal_motion += 1 ;
213
221
}
214
- game_state. move_block_horizontal ( horizontal_motion) ;
222
+ game_state. move_active_block_horizontal ( horizontal_motion) ;
215
223
216
224
let mut relative_rotation: i32 = 0 ;
217
225
if inputs. rot_left {
@@ -222,11 +230,16 @@ fn main() {
222
230
}
223
231
game_state. rotate_block ( relative_rotation) ;
224
232
233
+ if inputs. drop {
234
+ game_state. quick_drop ( ) ;
235
+ }
236
+
225
237
inputs = Inputs {
226
238
move_left : false ,
227
239
move_right : false ,
228
240
rot_left : false ,
229
241
rot_right : false ,
242
+ drop : false ,
230
243
} ;
231
244
}
232
245
@@ -239,53 +252,65 @@ fn main() {
239
252
window. erase ( ) ;
240
253
241
254
// Render the tetris title
242
- draw_frame ( & window, & TITLE_RECT ) ;
243
- draw_text_centered ( & window, TITLE , TITLE_RECT . center_x ( ) , TITLE_RECT . center_y ( ) ) ;
255
+ draw_frame ( & window, & title_rect ) ;
256
+ draw_text_centered ( & window, TITLE , title_rect . center_x ( ) , title_rect . center_y ( ) ) ;
244
257
245
258
// Render next piece preview
246
259
draw_text_centered (
247
260
& window,
248
261
"Next" ,
249
- PREVIEW_FRAME_RECT . center_x ( ) ,
250
- PREVIEW_FRAME_RECT . top - 1 ,
262
+ preview_frame_rect . center_x ( ) ,
263
+ preview_frame_rect . top - 1 ,
251
264
) ;
252
- draw_frame ( & window, & PREVIEW_FRAME_RECT ) ;
265
+ draw_frame ( & window, & preview_frame_rect ) ;
253
266
render_block (
254
267
& window,
255
268
Vec2 :: zero ( ) ,
256
- PREVIEW_RECT . left ,
257
- PREVIEW_RECT . top ,
269
+ preview_rect . left ,
270
+ preview_rect . top ,
258
271
game_state. preview_block ( ) ,
259
272
) ;
260
273
261
274
// Render the score pane
262
275
draw_text_centered (
263
276
& window,
264
277
& format ! ( "Level: {:05}" , game_state. level( ) ) ,
265
- SCORE_FRAME_RECT . center_x ( ) ,
266
- SCORE_FRAME_RECT . center_y ( ) - 1 ,
278
+ score_frame_rect . center_x ( ) ,
279
+ score_frame_rect . center_y ( ) - 1 ,
267
280
) ;
268
281
draw_text_centered (
269
282
& window,
270
283
& format ! ( "Score: {:05}" , game_state. score( ) ) ,
271
- SCORE_FRAME_RECT . center_x ( ) ,
272
- SCORE_FRAME_RECT . center_y ( ) ,
284
+ score_frame_rect . center_x ( ) ,
285
+ score_frame_rect . center_y ( ) ,
273
286
) ;
274
- draw_frame ( & window, & SCORE_FRAME_RECT ) ;
287
+ draw_frame ( & window, & score_frame_rect) ;
288
+
289
+ // Render the board frame
290
+ draw_frame ( & window, & board_frame_rect) ;
275
291
276
292
// Render the active piece
277
- draw_frame ( & window, & BOARD_FRAME_RECT ) ;
278
293
if let Some ( ( block, block_pos) ) = game_state. active_block ( ) {
279
- render_block ( & window, block_pos, BOARD_RECT . left , BOARD_RECT . top , block) ;
294
+ // TOOD: mayhaps refactor this into its own helper?
295
+ // render the active piece's drop trail
296
+ for cell in & block. cells ( ) {
297
+ let start_row = cell. y + block_pos. y ;
298
+ let col = cell. x + block_pos. x ;
299
+ for row in start_row..board_rect. height {
300
+ window. mvaddch ( row + board_rect. top , col + board_rect. left , '-' ) ;
301
+ }
302
+ }
303
+
304
+ render_block ( & window, block_pos, board_rect. left , board_rect. top , block) ;
280
305
}
281
306
282
307
// Render the settled pieces
283
308
game_state. for_each_settled_piece ( |block_type : BlockType , cell_pos : Vec2 | {
284
309
render_cell (
285
310
& window,
286
311
cell_pos,
287
- BOARD_RECT . left ,
288
- BOARD_RECT . top ,
312
+ board_rect . left ,
313
+ board_rect . top ,
289
314
block_type,
290
315
) ;
291
316
} ) ;
@@ -306,8 +331,8 @@ fn main() {
306
331
draw_text_centered (
307
332
& window,
308
333
"Game Over" ,
309
- BOARD_RECT . center_x ( ) ,
310
- BOARD_RECT . center_y ( ) ,
334
+ board_rect . center_x ( ) ,
335
+ board_rect . center_y ( ) ,
311
336
) ;
312
337
window. attroff ( pancurses:: A_BLINK ) ;
313
338
}
@@ -317,8 +342,8 @@ fn main() {
317
342
draw_text_centered (
318
343
& window,
319
344
"PAUSE" ,
320
- BOARD_RECT . center_x ( ) ,
321
- BOARD_RECT . center_y ( ) ,
345
+ board_rect . center_x ( ) ,
346
+ board_rect . center_y ( ) ,
322
347
) ;
323
348
window. attroff ( pancurses:: A_BLINK ) ;
324
349
}
0 commit comments