====== Step 3.3.3: The game loop ====== The game loop is the middle loop of our program where the actual gameplay happens. This loop is responsible for the following: - Put the current piece on the top of the playfield, above the ceiling - Get the next piece and display the piece preview - Display score - Do the update loop until the piece hits the bottom - Check if topped out, exit the loop if so - Otherwise check if rows must be cleared - Update the score and level if needed Let's follow the learn by coding method again. REM -- REM -- The game loop REM -- REPEAT REM -- Copy next shape to current shape shape_no! = nxt_shape_no! shape = nxt_shape shape_color! = colors![shape_no!] REM -- Get next shape and display preview nxt_shape_no! = CAST!(RND%() * 7.0) nxt_shape = get_shape(nxt_shape_no!, 0) CALL draw_preview REM -- Get current shape and put piece REM -- on top of the playfield piece_x! = 7 piece_y! = 0 piece_r! = 0 REM -- Display current score TEXTAT 27, 14, score% REM -- REM -- PASTE THE UPDATE LOOP HERE! REM -- REM -- The shape hit the bottom REM -- A little correction first - the piece is currently erased! DEC piece_y! : CALL draw_shape(shape, piece_x!, piece_y!, shape_color!, 1) REM -- Lock piece and make it part of the playfield CALL lock_piece REM -- Check if we have topped out IF piece_y! > 4 THEN REM -- ..no we haven't REM -- Check if there are rows to be cleared REM -- and remove them rows_cleared! = 0 row_no! = piece_y! + 3 : IF row_no! >= 24 THEN row_no! = 23 REPEAT REM -- Check if row is full IF playfield[row_no!] & %0011111111111100 THEN CALL clear_row(row_no!) INC rows_cleared! ELSE DEC row_no! ENDIF UNTIL row_no! = piece_y! REM -- Update score and check if it's REM -- time for next level score% = score% + bonus%[rows_cleared!] * CAST%(level!) ttl_rows_cleared! = ttl_rows_cleared! + rows_cleared! IF ttl_rows_cleared! >= 100 THEN INC level! delay! = 11 - level! TEXTAT 27, 11, level! ttl_rows_cleared! = ttl_rows_cleared! - 100 ENDIF ELSE REM -- ...yes, topped out REM -- Assigning 1 to game_status will effectively REM -- exit the loop game_status! = 1 ENDIF REM -- Everything is done, repeat for next shape REM -- or exit loop UNTIL game_status! = 1 REM -- Bonus added to the score when clearing REM -- 0, 1, 2, 3, 4 rows DATA bonus%[] = 0.0, 40.0, 100.0, 300.0, 1200.0 This loop is again a ''REPEAT ... UNTIL'' loop. It loops until ''game_status!'' becomes 1, that is, the game is over. Let's discuss what might be something new for you. There is a line somewhere near the beginning: nxt_shape_no! = CAST!(RND%() * 7.0) This is to randomly get a new shape for the next piece and there are several things in here that may not be straight forward. The first thing is the way we use the ''RND()'' function. This function is a little different in XC=BASIC as has three type variants: ''RND!()'' to get a random byte, ''RND()'' to get a random integer and ''RND%()'' to get a random float. Now the first two are not very useful for us as they return a number between 0-255 and -32768-32767, respectively. So we use the third one to get a random floating point number between 0 and 1, then multiply it with 7. But why 7.0? This is to tell the compiler that we mean 7 as a floating point number. This way the two numbers can be multiplied without type casting. After we're done with multiplying, we use the ''CAST!()'' function to cast the result as a byte. When casting from floating point to byte or integer, the number will be rounded, and that's what we actually need. The rest is comprehensive I think. There's only one step left, that is, wrapping the above code in the program loop. <- step_3.3.2|Previous page ^ start|Tetris tutorial ^ step_3.3.4|Next page ->