mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
793 lines
26 KiB
Plaintext
793 lines
26 KiB
Plaintext
module tetris;
|
|
import raylib;
|
|
/**
|
|
* raylib - classic game: tetris
|
|
*
|
|
* Sample game developed by Marc Palau and Ramon Santamaria,
|
|
* converted to C3 by Christoffer Lerno.
|
|
*
|
|
* This game has been created using raylib v1.3 (www.raylib.com)
|
|
*
|
|
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
|
|
*/
|
|
|
|
//----------------------------------------------------------------------------------
|
|
// Some Defines
|
|
//----------------------------------------------------------------------------------
|
|
const SQUARE_SIZE = 20;
|
|
const GRID_HORIZONTAL_SIZE = 12;
|
|
const GRID_VERTICAL_SIZE = 20;
|
|
|
|
const LATERAL_SPEED = 10;
|
|
const TURNING_SPEED = 12;
|
|
const FAST_FALL_AWAIT_COUNTER = 30;
|
|
const FADING_TIME = 33;
|
|
|
|
//----------------------------------------------------------------------------------
|
|
// Types and Structures Definition
|
|
//----------------------------------------------------------------------------------
|
|
enum GridSquare { EMPTY, MOVING, FULL, BLOCK, FADING }
|
|
|
|
//------------------------------------------------------------------------------------
|
|
// Global Variables Declaration
|
|
//------------------------------------------------------------------------------------
|
|
const int SCREEN_WIDTH = 800;
|
|
const int SCREEN_HEIGHT = 450;
|
|
|
|
bool game_over = false;
|
|
bool pause = false;
|
|
|
|
// Matrices
|
|
GridSquare[GRID_VERTICAL_SIZE][GRID_HORIZONTAL_SIZE] grid;
|
|
GridSquare[4][4] piece;
|
|
GridSquare[4][4] incoming_piece;
|
|
|
|
struct IntVec
|
|
{
|
|
int x;
|
|
int y;
|
|
}
|
|
// These variables keep track of the active piece position
|
|
int piece_position_x = 0;
|
|
int piece_position_y = 0;
|
|
|
|
// Game parameters
|
|
Color fading_color;
|
|
//int fallingSpeed; // In frames
|
|
|
|
bool begin_play = true; // This var is only true at the begining of the game, used for the first matrix creations
|
|
bool piece_active = false;
|
|
bool detection = false;
|
|
bool line_to_delete = false;
|
|
|
|
// Statistics
|
|
int level = 1;
|
|
int lines = 0;
|
|
|
|
// Counters
|
|
int gravity_movement_counter = 0;
|
|
int lateral_movement_counter = 0;
|
|
int turn_movement_counter = 0;
|
|
int fast_fall_movement_counter = 0;
|
|
|
|
int fade_line_counter = 0;
|
|
|
|
// Based on level
|
|
int gravity_speed = 30;
|
|
|
|
|
|
//------------------------------------------------------------------------------------
|
|
// Program main entry point
|
|
//------------------------------------------------------------------------------------
|
|
fn void main()
|
|
{
|
|
// Initialization (Note windowTitle is unused on Android)
|
|
//---------------------------------------------------------
|
|
raylib::init_window(SCREEN_WIDTH, SCREEN_HEIGHT, "classic game: tetris");
|
|
|
|
init_game();
|
|
|
|
raylib::set_target_fps(60);
|
|
//--------------------------------------------------------------------------------------
|
|
|
|
// Main game loop
|
|
while (!raylib::window_should_close()) // Detect window close button or ESC key
|
|
{
|
|
// Update and Draw
|
|
//----------------------------------------------------------------------------------
|
|
update_draw_frame();
|
|
//----------------------------------------------------------------------------------
|
|
}
|
|
// De-Initialization
|
|
//--------------------------------------------------------------------------------------
|
|
unload_game(); // Unload loaded data (textures, sounds, models...)
|
|
|
|
raylib::close_window(); // Close window and OpenGL context
|
|
//--------------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Game Module Functions Definition
|
|
//--------------------------------------------------------------------------------------
|
|
|
|
// Initialize game variables
|
|
fn void init_game()
|
|
{
|
|
// Initialize game statistics
|
|
level = 1;
|
|
lines = 0;
|
|
|
|
fading_color = raylib::GRAY;
|
|
|
|
piece_position_x = 0;
|
|
piece_position_y = 0;
|
|
|
|
pause = false;
|
|
|
|
begin_play = true;
|
|
piece_active = false;
|
|
detection = false;
|
|
line_to_delete = false;
|
|
|
|
// Counters
|
|
gravity_movement_counter = 0;
|
|
lateral_movement_counter = 0;
|
|
turn_movement_counter = 0;
|
|
fast_fall_movement_counter = 0;
|
|
|
|
fade_line_counter = 0;
|
|
gravity_speed = 30;
|
|
|
|
// Initialize grid matrices
|
|
for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++)
|
|
{
|
|
for (int j = 0; j < GRID_VERTICAL_SIZE; j++)
|
|
{
|
|
if ((j == GRID_VERTICAL_SIZE - 1) || (i == 0) || (i == GRID_HORIZONTAL_SIZE - 1))
|
|
{
|
|
grid[i][j] = BLOCK;
|
|
}
|
|
else
|
|
{
|
|
grid[i][j] = EMPTY;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialize incoming piece matrices
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
for (int j = 0; j< 4; j++)
|
|
{
|
|
incoming_piece[i][j] = EMPTY;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update game (one frame)
|
|
fn void update_game()
|
|
{
|
|
if (game_over)
|
|
{
|
|
if (raylib::is_key_pressed(keyboard::ENTER))
|
|
{
|
|
init_game();
|
|
game_over = false;
|
|
}
|
|
return;
|
|
}
|
|
if (raylib::is_key_pressed((KeyboardKey)'P')) pause = !pause;
|
|
|
|
if (pause) return;
|
|
if (line_to_delete)
|
|
{
|
|
// Animation when deleting lines
|
|
fade_line_counter++;
|
|
|
|
fading_color = fade_line_counter % 8 < 4 ? raylib::MAROON : raylib::GRAY;
|
|
|
|
if (fade_line_counter >= FADING_TIME)
|
|
{
|
|
lines += delete_complete_lines();
|
|
fade_line_counter = 0;
|
|
line_to_delete = false;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!piece_active)
|
|
{
|
|
// Get another piece
|
|
piece_active = create_piece();
|
|
|
|
// We leave a little time before starting the fast falling down
|
|
fast_fall_movement_counter = 0;
|
|
}
|
|
else // Piece falling
|
|
{
|
|
// Counters update
|
|
fast_fall_movement_counter++;
|
|
gravity_movement_counter++;
|
|
lateral_movement_counter++;
|
|
turn_movement_counter++;
|
|
|
|
// We make sure to move if we've pressed the key this frame
|
|
if (raylib::is_key_pressed(keyboard::LEFT) || raylib::is_key_pressed(keyboard::RIGHT)) lateral_movement_counter = LATERAL_SPEED;
|
|
if (raylib::is_key_pressed(keyboard::UP)) turn_movement_counter = TURNING_SPEED;
|
|
|
|
// Fall down
|
|
if (raylib::is_key_down(keyboard::DOWN) && (fast_fall_movement_counter >= FAST_FALL_AWAIT_COUNTER))
|
|
{
|
|
// We make sure the piece is going to fall this frame
|
|
gravity_movement_counter += gravity_speed;
|
|
}
|
|
|
|
if (gravity_movement_counter >= gravity_speed)
|
|
{
|
|
// Basic falling movement
|
|
check_detection(&detection);
|
|
|
|
// Check if the piece has collided with another piece or with the boundings
|
|
resolve_falling_movement(&detection, &piece_active);
|
|
|
|
// Check if we fullfilled a line and if so, erase the line and pull down the the lines above
|
|
check_completion(&line_to_delete);
|
|
|
|
gravity_movement_counter = 0;
|
|
}
|
|
|
|
// Move laterally at player's will
|
|
if (lateral_movement_counter >= LATERAL_SPEED)
|
|
{
|
|
// Update the lateral movement and if success, reset the lateral counter
|
|
if (!resolve_lateral_movement()) lateral_movement_counter = 0;
|
|
}
|
|
|
|
// Turn the piece at player's will
|
|
if (turn_movement_counter >= TURNING_SPEED)
|
|
{
|
|
// Update the turning movement and reset the turning counter
|
|
if (resolve_turn_movement()) turn_movement_counter = 0;
|
|
}
|
|
}
|
|
|
|
// Game over logic
|
|
for (int j = 0; j < 2; j++)
|
|
{
|
|
for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
{
|
|
if (grid[i][j] == GridSquare.FULL)
|
|
{
|
|
game_over = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Draw game (one frame)
|
|
fn void draw_game()
|
|
{
|
|
raylib::begin_drawing();
|
|
|
|
raylib::clear_background(raylib::RAYWHITE);
|
|
|
|
if (game_over)
|
|
{
|
|
raylib::draw_text("PRESS [ENTER] TO PLAY AGAIN", raylib::get_screen_width() / 2 - raylib::measure_text("PRESS [ENTER] TO PLAY AGAIN", 20) / 2, raylib::get_screen_height() / 2 - 50, 20, raylib::GRAY);
|
|
raylib::end_drawing();
|
|
return;
|
|
}
|
|
|
|
// Draw gameplay area
|
|
IntVec offset = {
|
|
SCREEN_WIDTH / 2 - (GRID_HORIZONTAL_SIZE * SQUARE_SIZE / 2) - 50,
|
|
SCREEN_HEIGHT / 2 - ((GRID_VERTICAL_SIZE - 1) * SQUARE_SIZE / 2) + SQUARE_SIZE * 2
|
|
};
|
|
offset.y -= 50; // NOTE: Harcoded position!
|
|
|
|
int controller = offset.x;
|
|
|
|
for (int j = 0; j < GRID_VERTICAL_SIZE; j++)
|
|
{
|
|
for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++)
|
|
{
|
|
// Draw each square of the grid
|
|
switch (grid[i][j])
|
|
{
|
|
case EMPTY:
|
|
raylib::draw_line(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, raylib::LIGHTGRAY );
|
|
raylib::draw_line(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, raylib::LIGHTGRAY );
|
|
raylib::draw_line(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, raylib::LIGHTGRAY );
|
|
raylib::draw_line(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, raylib::LIGHTGRAY );
|
|
offset.x += SQUARE_SIZE;
|
|
case FULL:
|
|
raylib::draw_rectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, raylib::GRAY);
|
|
offset.x += SQUARE_SIZE;
|
|
case MOVING:
|
|
raylib::draw_rectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, raylib::DARKGRAY);
|
|
offset.x += SQUARE_SIZE;
|
|
case BLOCK:
|
|
raylib::draw_rectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, raylib::LIGHTGRAY);
|
|
offset.x += SQUARE_SIZE;
|
|
case FADING:
|
|
raylib::draw_rectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, fading_color);
|
|
offset.x += SQUARE_SIZE;
|
|
default:
|
|
}
|
|
}
|
|
|
|
offset.x = controller;
|
|
offset.y += SQUARE_SIZE;
|
|
}
|
|
|
|
// Draw incoming piece (hardcoded)
|
|
offset.x = 500;
|
|
offset.y = 45;
|
|
|
|
controller = offset.x;
|
|
|
|
for (int j = 0; j < 4; j++)
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
switch (incoming_piece[i][j])
|
|
{
|
|
case EMPTY:
|
|
raylib::draw_line(offset.x, offset.y, offset.x + SQUARE_SIZE, offset.y, raylib::LIGHTGRAY);
|
|
raylib::draw_line(offset.x, offset.y, offset.x, offset.y + SQUARE_SIZE, raylib::LIGHTGRAY);
|
|
raylib::draw_line(offset.x + SQUARE_SIZE, offset.y, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, raylib::LIGHTGRAY);
|
|
raylib::draw_line(offset.x, offset.y + SQUARE_SIZE, offset.x + SQUARE_SIZE, offset.y + SQUARE_SIZE, raylib::LIGHTGRAY);
|
|
offset.x += SQUARE_SIZE;
|
|
case MOVING:
|
|
raylib::draw_rectangle(offset.x, offset.y, SQUARE_SIZE, SQUARE_SIZE, raylib::GRAY);
|
|
offset.x += SQUARE_SIZE;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
offset.x = controller;
|
|
offset.y += SQUARE_SIZE;
|
|
}
|
|
|
|
raylib::draw_text("INCOMING:", offset.x, offset.y - 100, 10, raylib::GRAY);
|
|
raylib::draw_text(raylib::text_format("LINES: %04i", lines), offset.x, offset.y + 20, 10, raylib::GRAY);
|
|
|
|
if (pause)
|
|
{
|
|
raylib::draw_text("GAME PAUSED", SCREEN_WIDTH / 2 - raylib::measure_text("GAME PAUSED", 40)/2, SCREEN_HEIGHT/2 - 40, 40, raylib::GRAY);
|
|
}
|
|
raylib::end_drawing();
|
|
}
|
|
|
|
// Unload game variables
|
|
fn void unload_game()
|
|
{
|
|
// TODO: Unload all dynamic loaded data (textures, sounds, models...)
|
|
}
|
|
|
|
// Update and Draw (one frame)
|
|
fn void update_draw_frame()
|
|
{
|
|
update_game();
|
|
draw_game();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Additional module functions
|
|
//--------------------------------------------------------------------------------------
|
|
fn bool create_piece()
|
|
{
|
|
piece_position_x = (int)((GRID_HORIZONTAL_SIZE - 4)/2);
|
|
piece_position_y = 0;
|
|
|
|
// If the game is starting and you are going to create the first piece, we create an extra one
|
|
if (begin_play)
|
|
{
|
|
get_random_piece();
|
|
begin_play = false;
|
|
}
|
|
|
|
// We assign the incoming piece to the actual piece
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
for (int j = 0; j< 4; j++)
|
|
{
|
|
piece[i][j] = incoming_piece[i][j];
|
|
}
|
|
}
|
|
|
|
// We assign a random piece to the incoming one
|
|
get_random_piece();
|
|
|
|
// Assign the piece to the grid
|
|
for (int i = piece_position_x; i < piece_position_x + 4; i++)
|
|
{
|
|
for (int j = 0; j < 4; j++)
|
|
{
|
|
if (piece[i - (int)piece_position_x][j] == GridSquare.MOVING) grid[i][j] = MOVING;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
fn void get_random_piece()
|
|
{
|
|
int random = raylib::get_random_value(0, 6);
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
for (int j = 0; j < 4; j++)
|
|
{
|
|
incoming_piece[i][j] = EMPTY;
|
|
}
|
|
}
|
|
|
|
switch (random)
|
|
{
|
|
case 0:
|
|
incoming_piece[1][1] = MOVING;
|
|
incoming_piece[2][1] = MOVING;
|
|
incoming_piece[1][2] = MOVING;
|
|
incoming_piece[2][2] = MOVING; //Cube
|
|
case 1:
|
|
incoming_piece[1][0] = MOVING;
|
|
incoming_piece[1][1] = MOVING;
|
|
incoming_piece[1][2] = MOVING;
|
|
incoming_piece[2][2] = MOVING; //L
|
|
case 2:
|
|
incoming_piece[1][2] = MOVING;
|
|
incoming_piece[2][0] = MOVING;
|
|
incoming_piece[2][1] = MOVING;
|
|
incoming_piece[2][2] = MOVING; //L inversa
|
|
case 3:
|
|
incoming_piece[0][1] = MOVING;
|
|
incoming_piece[1][1] = MOVING;
|
|
incoming_piece[2][1] = MOVING;
|
|
incoming_piece[3][1] = MOVING; //Recta
|
|
case 4:
|
|
incoming_piece[1][0] = MOVING;
|
|
incoming_piece[1][1] = MOVING;
|
|
incoming_piece[1][2] = MOVING;
|
|
incoming_piece[2][1] = MOVING; //Creu tallada
|
|
case 5:
|
|
incoming_piece[1][1] = MOVING;
|
|
incoming_piece[2][1] = MOVING;
|
|
incoming_piece[2][2] = MOVING;
|
|
incoming_piece[3][2] = MOVING; //S
|
|
case 6:
|
|
incoming_piece[1][2] = MOVING;
|
|
incoming_piece[2][2] = MOVING;
|
|
incoming_piece[2][1] = MOVING;
|
|
incoming_piece[3][1] = MOVING; //S inversa
|
|
default:
|
|
unreachable();
|
|
}
|
|
}
|
|
|
|
fn void resolve_falling_movement(bool* detection_ref, bool* piece_active_ref)
|
|
{
|
|
// If we finished moving this piece, we stop it
|
|
if (*detection_ref)
|
|
{
|
|
for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
{
|
|
for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
{
|
|
if (grid[i][j] == GridSquare.MOVING)
|
|
{
|
|
grid[i][j] = FULL;
|
|
*detection_ref = false;
|
|
*piece_active_ref = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else // We move down the piece
|
|
{
|
|
for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
{
|
|
for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
{
|
|
if (grid[i][j] == GridSquare.MOVING)
|
|
{
|
|
grid[i][j+1] = MOVING;
|
|
grid[i][j] = EMPTY;
|
|
}
|
|
}
|
|
}
|
|
|
|
piece_position_y++;
|
|
}
|
|
}
|
|
|
|
fn bool resolve_lateral_movement()
|
|
{
|
|
bool collision = false;
|
|
|
|
// Piece movement
|
|
if (raylib::is_key_down(keyboard::LEFT)) // Move left
|
|
{
|
|
// Check if is possible to move to left
|
|
for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
{
|
|
for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
{
|
|
if (grid[i][j] == GridSquare.MOVING)
|
|
{
|
|
// Check if we are touching the left wall or we have a full square at the left
|
|
if ((i-1 == 0) || (grid[i-1][j] == GridSquare.FULL)) collision = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If able, move left
|
|
if (!collision)
|
|
{
|
|
for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
{
|
|
for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) // We check the matrix from left to right
|
|
{
|
|
// Move everything to the left
|
|
if (grid[i][j] == GridSquare.MOVING)
|
|
{
|
|
grid[i-1][j] = MOVING;
|
|
grid[i][j] = EMPTY;
|
|
}
|
|
}
|
|
}
|
|
|
|
piece_position_x--;
|
|
}
|
|
}
|
|
else if (raylib::is_key_down(keyboard::RIGHT)) // Move right
|
|
{
|
|
// Check if is possible to move to right
|
|
for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
{
|
|
for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
{
|
|
if (grid[i][j] == GridSquare.MOVING)
|
|
{
|
|
// Check if we are touching the right wall or we have a full square at the right
|
|
if ((i+1 == GRID_HORIZONTAL_SIZE - 1) || (grid[i+1][j] == GridSquare.FULL))
|
|
{
|
|
collision = true;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// If able move right
|
|
if (!collision)
|
|
{
|
|
for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
{
|
|
for (int i = GRID_HORIZONTAL_SIZE - 1; i >= 1; i--) // We check the matrix from right to left
|
|
{
|
|
// Move everything to the right
|
|
if (grid[i][j] == GridSquare.MOVING)
|
|
{
|
|
grid[i+1][j] = MOVING;
|
|
grid[i][j] = EMPTY;
|
|
}
|
|
}
|
|
}
|
|
|
|
piece_position_x++;
|
|
}
|
|
}
|
|
|
|
return collision;
|
|
}
|
|
|
|
fn bool resolve_turn_movement()
|
|
{
|
|
// Input for turning the piece
|
|
if (raylib::is_key_down(keyboard::UP))
|
|
{
|
|
GridSquare aux;
|
|
bool checker = false;
|
|
|
|
// Check all turning possibilities
|
|
if ((grid[piece_position_x + 3][piece_position_y] == GridSquare.MOVING) &&
|
|
(grid[piece_position_x][piece_position_y] != GridSquare.EMPTY) &&
|
|
(grid[piece_position_x][piece_position_y] != GridSquare.MOVING)) checker = true;
|
|
|
|
if ((grid[piece_position_x + 3][piece_position_y + 3] == GridSquare.MOVING) &&
|
|
(grid[piece_position_x + 3][piece_position_y] != GridSquare.EMPTY) &&
|
|
(grid[piece_position_x + 3][piece_position_y] != GridSquare.MOVING)) checker = true;
|
|
|
|
if ((grid[piece_position_x][piece_position_y + 3] == GridSquare.MOVING) &&
|
|
(grid[piece_position_x + 3][piece_position_y + 3] != GridSquare.EMPTY) &&
|
|
(grid[piece_position_x + 3][piece_position_y + 3] != GridSquare.MOVING)) checker = true;
|
|
|
|
if ((grid[piece_position_x][piece_position_y] == GridSquare.MOVING) &&
|
|
(grid[piece_position_x][piece_position_y + 3] != GridSquare.EMPTY) &&
|
|
(grid[piece_position_x][piece_position_y + 3] != GridSquare.MOVING)) checker = true;
|
|
|
|
if ((grid[piece_position_x + 1][piece_position_y] == GridSquare.MOVING) &&
|
|
(grid[piece_position_x][piece_position_y + 2] != GridSquare.EMPTY) &&
|
|
(grid[piece_position_x][piece_position_y + 2] != GridSquare.MOVING)) checker = true;
|
|
|
|
if ((grid[piece_position_x + 3][piece_position_y + 1] == GridSquare.MOVING) &&
|
|
(grid[piece_position_x + 1][piece_position_y] != GridSquare.EMPTY) &&
|
|
(grid[piece_position_x + 1][piece_position_y] != GridSquare.MOVING)) checker = true;
|
|
|
|
if ((grid[piece_position_x + 2][piece_position_y + 3] == GridSquare.MOVING) &&
|
|
(grid[piece_position_x + 3][piece_position_y + 1] != GridSquare.EMPTY) &&
|
|
(grid[piece_position_x + 3][piece_position_y + 1] != GridSquare.MOVING)) checker = true;
|
|
|
|
if ((grid[piece_position_x][piece_position_y + 2] == GridSquare.MOVING) &&
|
|
(grid[piece_position_x + 2][piece_position_y + 3] != GridSquare.EMPTY) &&
|
|
(grid[piece_position_x + 2][piece_position_y + 3] != GridSquare.MOVING)) checker = true;
|
|
|
|
if ((grid[piece_position_x + 2][piece_position_y] == GridSquare.MOVING) &&
|
|
(grid[piece_position_x][piece_position_y + 1] != GridSquare.EMPTY) &&
|
|
(grid[piece_position_x][piece_position_y + 1] != GridSquare.MOVING)) checker = true;
|
|
|
|
if ((grid[piece_position_x + 3][piece_position_y + 2] == GridSquare.MOVING) &&
|
|
(grid[piece_position_x + 2][piece_position_y] != GridSquare.EMPTY) &&
|
|
(grid[piece_position_x + 2][piece_position_y] != GridSquare.MOVING)) checker = true;
|
|
|
|
if ((grid[piece_position_x + 1][piece_position_y + 3] == GridSquare.MOVING) &&
|
|
(grid[piece_position_x + 3][piece_position_y + 2] != GridSquare.EMPTY) &&
|
|
(grid[piece_position_x + 3][piece_position_y + 2] != GridSquare.MOVING)) checker = true;
|
|
|
|
if ((grid[piece_position_x][piece_position_y + 1] == GridSquare.MOVING) &&
|
|
(grid[piece_position_x + 1][piece_position_y + 3] != GridSquare.EMPTY) &&
|
|
(grid[piece_position_x + 1][piece_position_y + 3] != GridSquare.MOVING)) checker = true;
|
|
|
|
if ((grid[piece_position_x + 1][piece_position_y + 1] == GridSquare.MOVING) &&
|
|
(grid[piece_position_x + 1][piece_position_y + 2] != GridSquare.EMPTY) &&
|
|
(grid[piece_position_x + 1][piece_position_y + 2] != GridSquare.MOVING)) checker = true;
|
|
|
|
if ((grid[piece_position_x + 2][piece_position_y + 1] == GridSquare.MOVING) &&
|
|
(grid[piece_position_x + 1][piece_position_y + 1] != GridSquare.EMPTY) &&
|
|
(grid[piece_position_x + 1][piece_position_y + 1] != GridSquare.MOVING)) checker = true;
|
|
|
|
if ((grid[piece_position_x + 2][piece_position_y + 2] == GridSquare.MOVING) &&
|
|
(grid[piece_position_x + 2][piece_position_y + 1] != GridSquare.EMPTY) &&
|
|
(grid[piece_position_x + 2][piece_position_y + 1] != GridSquare.MOVING)) checker = true;
|
|
|
|
if ((grid[piece_position_x + 1][piece_position_y + 2] == GridSquare.MOVING) &&
|
|
(grid[piece_position_x + 2][piece_position_y + 2] != GridSquare.EMPTY) &&
|
|
(grid[piece_position_x + 2][piece_position_y + 2] != GridSquare.MOVING)) checker = true;
|
|
|
|
if (!checker)
|
|
{
|
|
aux = piece[0][0];
|
|
piece[0][0] = piece[3][0];
|
|
piece[3][0] = piece[3][3];
|
|
piece[3][3] = piece[0][3];
|
|
piece[0][3] = aux;
|
|
|
|
aux = piece[1][0];
|
|
piece[1][0] = piece[3][1];
|
|
piece[3][1] = piece[2][3];
|
|
piece[2][3] = piece[0][2];
|
|
piece[0][2] = aux;
|
|
|
|
aux = piece[2][0];
|
|
piece[2][0] = piece[3][2];
|
|
piece[3][2] = piece[1][3];
|
|
piece[1][3] = piece[0][1];
|
|
piece[0][1] = aux;
|
|
|
|
aux = piece[1][1];
|
|
piece[1][1] = piece[2][1];
|
|
piece[2][1] = piece[2][2];
|
|
piece[2][2] = piece[1][2];
|
|
piece[1][2] = aux;
|
|
}
|
|
|
|
for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
{
|
|
for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
{
|
|
if (grid[i][j] == GridSquare.MOVING)
|
|
{
|
|
grid[i][j] = EMPTY;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = piece_position_x; i < piece_position_x + 4; i++)
|
|
{
|
|
for (int j = piece_position_y; j < piece_position_y + 4; j++)
|
|
{
|
|
if (piece[i - piece_position_x][j - piece_position_y] == GridSquare.MOVING)
|
|
{
|
|
grid[i][j] = MOVING;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
fn void check_detection(bool *detection_ref)
|
|
{
|
|
for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
{
|
|
for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
{
|
|
if ((grid[i][j] == GridSquare.MOVING) && ((grid[i][j+1] == GridSquare.FULL) || (grid[i][j+1] == GridSquare.BLOCK))) *detection_ref = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
fn void check_completion(bool *line_to_delete_ref)
|
|
{
|
|
int calculator = 0;
|
|
|
|
for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
{
|
|
calculator = 0;
|
|
for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
{
|
|
// Count each square of the line
|
|
if (grid[i][j] == GridSquare.FULL)
|
|
{
|
|
calculator++;
|
|
}
|
|
|
|
// Check if we completed the whole line
|
|
if (calculator == GRID_HORIZONTAL_SIZE - 2)
|
|
{
|
|
*line_to_delete_ref = true;
|
|
calculator = 0;
|
|
// points++;
|
|
|
|
// Mark the completed line
|
|
for (int z = 1; z < GRID_HORIZONTAL_SIZE - 1; z++)
|
|
{
|
|
grid[z][j] = FADING;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn int delete_complete_lines()
|
|
{
|
|
int lines_to_erase = 0;
|
|
// Erase the completed line
|
|
for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--)
|
|
{
|
|
while (grid[1][j] == GridSquare.FADING)
|
|
{
|
|
lines_to_erase++;
|
|
for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++)
|
|
{
|
|
grid[i][j] = GridSquare.EMPTY;
|
|
}
|
|
|
|
for (int j2 = j-1; j2 >= 0; j2--)
|
|
{
|
|
for (int i2 = 1; i2 < GRID_HORIZONTAL_SIZE - 1; i2++)
|
|
{
|
|
switch (grid[i2][j2])
|
|
{
|
|
case FULL:
|
|
grid[i2][j2+1] = GridSquare.FULL;
|
|
grid[i2][j2] = GridSquare.EMPTY;
|
|
case FADING:
|
|
grid[i2][j2+1] = GridSquare.FADING;
|
|
grid[i2][j2] = GridSquare.EMPTY;
|
|
default:
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return lines_to_erase;
|
|
}
|
|
|