diff --git a/source/main.cpp b/source/main.cpp index 69fc0ebe7dbdda1ede5b9b062666c90680ed8b7a..fd9ab95c3ff3e581f4d5a7846d2e9f12b43ba920 100755 --- a/source/main.cpp +++ b/source/main.cpp @@ -39,7 +39,7 @@ MicroBit ubit; /** - * @brief An (X,Y) tuple type for storing 2D cartesian quantities + * @brief An (X,Y) tuple type for storing 2D Cartesian quantities */ struct Tuple { int x; @@ -123,7 +123,8 @@ enum class RotationDirection : uint8_t { /* * we store the sprites for our different block shapes in FLASH, i.e. read-only - * storage. This requires manual data-packing as follows + * storage. This requires manual data-packing as follows. + * For most of them, we store four different orientations. */ const uint8_t FLAT_L_NORTH_SPRITE[] __attribute__ ((aligned (4))) = { 0xff, 0xff, // magic number requesting data to be stored in FLASH @@ -358,43 +359,6 @@ MicroBitImage Block::image() const { } -void debug_test() { - // XXX: simple debug test to check my FLASH images were stored correctly - // for accurately-timed animations irrespective of framerate, track time - unsigned long stopwatch = ubit.systemTime(); - unsigned long move_speed = 1000; // move down one block every 350ms - // set up event handlers - // ubit.messageBus.listen( - // MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK, a_button_pressed - // ); - // ubit.messageBus.listen( - // MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, b_button_pressed - // ); - while (true) { - // scroll random blocks down the screen - Block block; // make a new random Block - // starting positions: - int x = 1; - int y = -3; - // print image until scrolled down off the screen - while (y < 6) { - ubit.display.clear(); - ubit.display.print(block.image(), x, y); - { - // check if enough time has elapsed to move the block - unsigned long stopwatch_now = ubit.systemTime(); - if ((stopwatch_now - stopwatch) >= move_speed) { - y++; - // update the "stopwatch" - stopwatch = stopwatch_now; - } - } - ubit.sleep(50); // 50ms sleep for 20 FPS - } - } -} - - /** * @brief Uses collision-detection to decide whether the given Block can move * along the provided translation Vector. @@ -424,7 +388,11 @@ bool can_shape_move( destination.x < 0 or destination.x > 4 or destination.y > 4 - // NOTE: there is no check for negative Y since we allow it + /* + * NOTE: there is no check for negative Y since we allow + * shapes to poke out of the top of the screen as they + * descend into play. + */ ) { return false; } @@ -434,7 +402,7 @@ bool can_shape_move( } // check if the translated position of this pixel is not free if (stacked.getPixelValue(destination.x, destination.y) != 0) { - return false; + return false; // can't move because space is obstructed } } } @@ -476,7 +444,7 @@ bool can_shape_rotate( } // check if this pixel position is free in the stacked image if (stacked.getPixelValue(destination.x, destination.y) != 0) { - return false; + return false; // space is obstructed so can't rotate } } } @@ -485,9 +453,11 @@ bool can_shape_rotate( return true; } + +/* begin game state variables */ + // this image contains all stacked shapes --it covers the entire screen MicroBitImage stacked_shapes(5, 5); -// game state variables bool game_over; // player left/right shift request tracker int move_command = 0; // 0 = do nothing, -1 = shift left, +1 = shift right @@ -496,6 +466,8 @@ int rotate_command = 0; // 0 = do nothing, -1 = rotate acw, +1 = rotate cw // player's score int score = 0; +/* end game state variables */ + /* * our event handler functions take the name of the in-game command they @@ -506,14 +478,17 @@ void move_left(MicroBitEvent) { move_command = -1; } + void move_right(MicroBitEvent) { move_command = +1; } + void rotate_acw(MicroBitEvent) { rotate_command = -1; } + void rotate_cw(MicroBitEvent) { rotate_command = +1; } @@ -521,7 +496,7 @@ void rotate_cw(MicroBitEvent) { /** * @brief Returns true/false for whether the given row of the given image is - * contiquous or not, that is, if it is full of non-clear pixels. + * contiguous or not, that is, if it is full of non-clear pixels. */ bool is_row_contiquous(MicroBitImage stacked_shapes, int row) { for (int x = 0; x < 5; x++) { @@ -534,9 +509,10 @@ bool is_row_contiquous(MicroBitImage stacked_shapes, int row) { return true; } + /** * @brief Given a reference to a MicroBitImage of stacked shapes, remove any - * contiquous rows of pixels, shifting contents above them down. + * contiguous rows of pixels, shifting contents above them down. * @returns the number of rows that were eliminated */ int eliminate_rows(MicroBitImage& stacked_shapes) { @@ -546,7 +522,7 @@ int eliminate_rows(MicroBitImage& stacked_shapes) { do { if (is_row_contiquous(stacked_shapes, row)) { eliminated++; - // optimisaton: if on the last row, just shift entire image down + // optimisation: if on the last row, just shift entire image down if (row == 4) { stacked_shapes.shiftDown(1); } else { @@ -557,12 +533,20 @@ int eliminate_rows(MicroBitImage& stacked_shapes) { stacked_shapes.setPixelValue(x, above + 1, value); } } + // TODO: we don't clear the top row, but perhaps we should? } } else { - // only go up the image when the current row is no longer contiguous + /* + * only go up the image when the current row is no longer contiguous + * --we do this because if we have just eliminated a row, we need + * to check that same row again because everything will have shifted + * down by one and the next row (the new row now in this place) + * might also be full and can be eliminated. + */ row--; } } while (row > 0); + // TODO: we don't check if the top row can be eliminated, perhaps we should? // return the number of eliminated rows return eliminated; } @@ -683,7 +667,6 @@ void start_new_game() { score += (1 + eliminated_count * 5); } } - // TODO: clean up game state // remove event-handlers ubit.messageBus.ignore( MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK, rotate_acw