0.2.1 SysV ABI fix for passing certain things by struct. Fix implicitly converting to float in the case of myfloat *= -1. Prefer inferred constant over global. Allow locals to shadow global variables.

This commit is contained in:
Christoffer Lerno
2022-04-26 14:07:37 +02:00
parent 212bc7d9af
commit 22ee082d00
13 changed files with 2234 additions and 152 deletions

View File

@@ -0,0 +1,312 @@
module arkanoid;
/**
*
* raylib - classic game: arkanoid
*
* Sample game developed by Marc Palau and Ramon Santamaria
* converted to C3 by Christoffer Lerno
*
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
*/
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 450;
//----------------------------------------------------------------------------------
// Some Defines
//----------------------------------------------------------------------------------
const PLAYER_MAX_LIFE = 5;
const LINES_OF_BRICKS = 5;
const BRICKS_PER_LINE = 20;
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
enum GameScreen
{
LOGO,
TITLE,
GAMEPLAY,
ENDING
}
struct Player
{
Vector2 position;
Vector2 size;
int life;
}
struct Ball
{
Vector2 position;
Vector2 speed;
int radius;
bool active;
}
struct Brick
{
Vector2 position;
bool active;
}
//------------------------------------------------------------------------------------
// Global Variables Declaration
//------------------------------------------------------------------------------------
bool game_over = false;
bool pause = false;
Player player;
Ball ball;
Brick[BRICKS_PER_LINE][LINES_OF_BRICKS] brick;
Vector2 brick_size;
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
fn void main()
{
// Initialization (Note windowTitle is unused on Android)
//---------------------------------------------------------
raylib::init_window(SCREEN_WIDTH, SCREEN_HEIGHT, "classic game: arkanoid");
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
//--------------------------------------------------------------------------------------
}
//------------------------------------------------------------------------------------
// Module Functions Definitions (local)
//------------------------------------------------------------------------------------
// Initialize game variables
fn void init_game()
{
brick_size = { raylib::get_screen_width() / BRICKS_PER_LINE, 40 };
// Initialize player
player.position = { SCREEN_WIDTH/2, SCREEN_HEIGHT * 7 / 8 };
player.size = { SCREEN_WIDTH / 10, 20 };
player.life = PLAYER_MAX_LIFE;
// Initialize ball
ball.position = { SCREEN_WIDTH / 2, SCREEN_HEIGHT * 7 / 8 - 30 };
ball.speed = { 0, 0 };
ball.radius = 7;
ball.active = false;
// Initialize bricks
int initial_down_position = 50;
for (int i = 0; i < LINES_OF_BRICKS; i++)
{
for (int j = 0; j < BRICKS_PER_LINE; j++)
{
brick[i][j].position = { j * brick_size.x + brick_size.x / 2, i * brick_size.y + initial_down_position };
brick[i][j].active = true;
}
}
}
// Update game (one frame)
fn void update_game()
{
if (game_over)
{
if (raylib::is_key_pressed(keyboard::ENTER))
{
init_game();
game_over = false;
}
}
if (raylib::is_key_pressed((KeyboardKey)'P')) pause = !pause;
if (pause) return;
// Player movement logic
if (raylib::is_key_down(keyboard::LEFT)) player.position.x -= 5;
if ((player.position.x - player.size.x/2) <= 0) player.position.x = player.size.x/2;
if (raylib::is_key_down(keyboard::RIGHT)) player.position.x += 5;
if ((player.position.x + player.size.x/2) >= SCREEN_WIDTH) player.position.x = SCREEN_WIDTH - player.size.x/2;
// Ball launching logic
if (!ball.active)
{
if (raylib::is_key_pressed(keyboard::SPACE))
{
ball.active = true;
ball.speed = { 0, -5 };
}
}
// Ball movement logic
if (ball.active)
{
ball.position.x += ball.speed.x;
ball.position.y += ball.speed.y;
}
else
{
ball.position = { player.position.x, SCREEN_HEIGHT * 7 / 8 - 30 };
}
// Collision logic: ball vs walls
if (((ball.position.x + ball.radius) >= SCREEN_WIDTH) || ((ball.position.x - ball.radius) <= 0)) ball.speed.x *= -1;
if ((ball.position.y - ball.radius) <= 0) ball.speed.y *= -1;
if ((ball.position.y + ball.radius) >= SCREEN_HEIGHT)
{
ball.speed = { 0, 0 };
ball.active = false;
player.life--;
}
// Collision logic: ball vs player
if (raylib::check_collision_circle_rec(ball.position, ball.radius,
Rectangle{ player.position.x - player.size.x / 2, player.position.y - player.size.y / 2, player.size.x, player.size.y}))
{
if (ball.speed.y > 0)
{
ball.speed.y *= -1;
ball.speed.x = (ball.position.x - player.position.x) / (player.size.x / 2) * 5;
}
}
// Collision logic: ball vs bricks
for (int i = 0; i < LINES_OF_BRICKS; i++)
{
for (int j = 0; j < BRICKS_PER_LINE; j++)
{
if (brick[i][j].active)
{
// Hit below
if (((ball.position.y - ball.radius) <= (brick[i][j].position.y + brick_size.y / 2)) &&
((ball.position.y - ball.radius) > (brick[i][j].position.y + brick_size.y / 2 + ball.speed.y)) &&
((math::fabs((double)ball.position.x - brick[i][j].position.x)) < (double)(brick_size.x / 2 + ball.radius * 2 / 3)) && (ball.speed.y < 0))
{
brick[i][j].active = false;
ball.speed.y *= -1;
}
// Hit above
else if (((ball.position.y + ball.radius) >= (brick[i][j].position.y - brick_size.y/2)) &&
((ball.position.y + ball.radius) < (brick[i][j].position.y - brick_size.y/2 + ball.speed.y)) &&
((math::fabs((double)ball.position.x - brick[i][j].position.x)) < (double)(brick_size.x/2 + ball.radius*2/3)) && (ball.speed.y > 0))
{
brick[i][j].active = false;
ball.speed.y *= -1;
}
// Hit left
else if (((ball.position.x + ball.radius) >= (brick[i][j].position.x - brick_size.x/2)) &&
((ball.position.x + ball.radius) < (brick[i][j].position.x - brick_size.x/2 + ball.speed.x)) &&
((math::fabs((double)ball.position.y - brick[i][j].position.y)) < (double)(brick_size.y/2 + ball.radius*2/3)) && (ball.speed.x > 0))
{
brick[i][j].active = false;
ball.speed.x *= -1;
}
// Hit right
else if (((ball.position.x - ball.radius) <= (brick[i][j].position.x + brick_size.x/2)) &&
((ball.position.x - ball.radius) > (brick[i][j].position.x + brick_size.x/2 + ball.speed.x)) &&
((math::fabs((double)ball.position.y - brick[i][j].position.y)) < (double)(brick_size.y/2 + ball.radius*2/3)) && (ball.speed.x < 0))
{
brick[i][j].active = false;
ball.speed.x *= -1;
}
}
}
}
// Game over logic
if (player.life <= 0)
{
game_over = true;
}
else
{
game_over = true;
for (int i = 0; i < LINES_OF_BRICKS; i++)
{
for (int j = 0; j < BRICKS_PER_LINE; j++)
{
if (brick[i][j].active) game_over = false;
}
}
}
}
// Draw game (one frame)
fn void draw_game()
{
raylib::begin_drawing();
raylib::clear_background(raylib::RAYWHITE);
if (!game_over)
{
// Draw player bar
raylib::draw_rectangle((int)(player.position.x - player.size.x/2), (int)(player.position.y - player.size.y/2), (int)player.size.x, (int)player.size.y, raylib::BLACK);
// Draw player lives
for (int i = 0; i < player.life; i++) raylib::draw_rectangle(20 + 40*i, SCREEN_HEIGHT - 30, 35, 10, raylib::LIGHTGRAY);
// Draw ball
raylib::draw_circle_v(ball.position, ball.radius, raylib::MAROON);
// Draw bricks
for (int i = 0; i < LINES_OF_BRICKS; i++)
{
for (int j = 0; j < BRICKS_PER_LINE; j++)
{
if (brick[i][j].active)
{
if ((i + j) % 2 == 0)
{
raylib::draw_rectangle((int)(brick[i][j].position.x - brick_size.x/2), (int)(brick[i][j].position.y - brick_size.y/2), (int)brick_size.x, (int)brick_size.y, raylib::GRAY);
}
else
{
raylib::draw_rectangle((int)(brick[i][j].position.x - brick_size.x/2), (int)(brick[i][j].position.y - brick_size.y/2), (int)brick_size.x, (int)brick_size.y, raylib::DARKGRAY);
}
}
}
}
if (pause) raylib::draw_text("GAME PAUSED", SCREEN_WIDTH/2 - raylib::measure_text("GAME PAUSED", 40)/2, SCREEN_HEIGHT/2 - 40, 40, raylib::GRAY);
}
else
{
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();
}
// 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();
}

View File

@@ -0,0 +1,251 @@
module snake;
/**
*
* raylib - classic game: snake
*
* Sample game developed by Ian Eito, Albert Martos and Ramon Santamaria,
* converted to C3 and modified by Christoffer Lerno
*
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
*
*/
const SNAKE_LENGTH = 256;
const SQUARE_SIZE = 32;
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 450;
enum SnakeDirection
{
RIGHT,
DOWN,
LEFT,
UP
}
struct Snake
{
Vector2 position;
Vector2 size;
Color color;
}
struct Food
{
Vector2 position;
Vector2 size;
bool active;
Color color;
}
int frames_counter = 0;
bool game_over = false;
bool pause = false;
Food fruit;
SnakeDirection snake_direction;
Snake[SNAKE_LENGTH] snake;
Vector2[SNAKE_LENGTH] snake_position;
bool allow_move = false;
Vector2 offset;
int counter_tail = 0;
fn void main()
{
raylib::init_window(SCREEN_WIDTH, SCREEN_HEIGHT, "classic game: snake");
init_game();
raylib::set_target_fps(60);
while (!raylib::window_should_close()) // Detect window close button or ESC key
{
update_draw_frame();
}
unload_game();
raylib::close_window();
}
// Initialize game variables
fn void init_game()
{
frames_counter = 0;
game_over = false;
pause = false;
counter_tail = 1;
allow_move = false;
snake_direction = SnakeDirection.RIGHT;
offset.x = SCREEN_WIDTH % SQUARE_SIZE;
offset.y = SCREEN_HEIGHT % SQUARE_SIZE;
for (int i = 0; i < SNAKE_LENGTH; i++)
{
snake[i].position = { offset.x / 2, offset.y / 2 };
snake[i].size = { SQUARE_SIZE, SQUARE_SIZE };
if (i == 0)
{
snake[i].color = raylib::DARKBLUE;
}
else
{
snake[i].color = raylib::BLUE;
}
}
for (int i = 0; i < SNAKE_LENGTH; i++)
{
snake_position[i] = { 0.0f, 0.0f };
}
fruit.size = { SQUARE_SIZE, SQUARE_SIZE };
fruit.color = raylib::SKYBLUE;
fruit.active = false;
}
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 (raylib::is_key_pressed(keyboard::RIGHT) && allow_move)
{
snake_direction = (SnakeDirection)((snake_direction + 1) % 4);
allow_move = false;
}
if (raylib::is_key_pressed(keyboard::LEFT) && allow_move)
{
snake_direction = (SnakeDirection)((snake_direction + 3) % 4);
allow_move = false;
}
// Snake movement
for (int i = 0; i < counter_tail; i++) snake_position[i] = snake[i].position;
if (frames_counter++ % 5 != 0) return;
allow_move = true;
switch (snake_direction)
{
case RIGHT:
snake[0].position.x += SQUARE_SIZE;
snake[0].position.y += 0;
case UP:
snake[0].position.x += 0;
snake[0].position.y += -SQUARE_SIZE;
case DOWN:
snake[0].position.x += 0;
snake[0].position.y += SQUARE_SIZE;
case LEFT:
snake[0].position.x += -SQUARE_SIZE;
snake[0].position.y += 0;
default:
@unreachable();
}
for (int i = 1; i < counter_tail; i++)
{
snake[i].position = snake_position[i - 1];
}
// Wall behaviour
if (((snake[0].position.x) > (SCREEN_WIDTH - offset.x)) ||
((snake[0].position.y) > (SCREEN_HEIGHT - offset.y)) ||
(snake[0].position.x < 0) || (snake[0].position.y < 0))
{
game_over = true;
}
// Collision with yourself
for (int i = 1; i < counter_tail; i++)
{
if ((snake[0].position.x == snake[i].position.x) && (snake[0].position.y == snake[i].position.y)) game_over = true;
}
// Fruit position calculation
if (!fruit.active)
{
fruit.active = true;
fruit.position = { raylib::get_random_value(0, (SCREEN_WIDTH / SQUARE_SIZE) - 1) * SQUARE_SIZE + offset.x/2, raylib::get_random_value(0, (SCREEN_HEIGHT / SQUARE_SIZE) - 1) * SQUARE_SIZE + offset.y / 2 };
for (int i = 0; i < counter_tail; i++)
{
while ((fruit.position.x == snake[i].position.x) && (fruit.position.y == snake[i].position.y))
{
fruit.position = { raylib::get_random_value(0, (SCREEN_WIDTH / SQUARE_SIZE) - 1) * SQUARE_SIZE + offset.x/2, raylib::get_random_value(0, (SCREEN_HEIGHT / SQUARE_SIZE) - 1) * SQUARE_SIZE + offset.y / 2 };
i = 0;
}
}
}
// Collision
if ((snake[0].position.x < (fruit.position.x + fruit.size.x) && (snake[0].position.x + snake[0].size.x) > fruit.position.x) &&
(snake[0].position.y < (fruit.position.y + fruit.size.y) && (snake[0].position.y + snake[0].size.y) > fruit.position.y))
{
snake[counter_tail].position = snake_position[counter_tail - 1];
counter_tail += 1;
fruit.active = false;
}
}
// Draw game (one frame)
fn void draw_game()
{
raylib::begin_drawing();
raylib::clear_background(raylib::RAYWHITE);
if (!game_over)
{
// Draw grid lines
for (int i = 0; i < SCREEN_WIDTH / SQUARE_SIZE + 1; i++)
{
raylib::draw_line_v({SQUARE_SIZE * i + offset.x/2, offset.y/2}, {SQUARE_SIZE * i + offset.x/2, SCREEN_HEIGHT - offset.y/2}, raylib::LIGHTGRAY);
}
for (int i = 0; i < SCREEN_HEIGHT/SQUARE_SIZE + 1; i++)
{
raylib::draw_line_v({offset.x/2, SQUARE_SIZE * i + offset.y / 2 }, { SCREEN_WIDTH - offset.x/2, SQUARE_SIZE * i + offset.y / 2 }, raylib::LIGHTGRAY);
}
// Draw snake
for (int i = 0; i < counter_tail; i++) raylib::draw_rectangle_v(snake[i].position, snake[i].size, snake[i].color);
// Draw fruit to pick
raylib::draw_rectangle_v(fruit.position, fruit.size, fruit.color);
if (pause) raylib::draw_text("GAME PAUSED", SCREEN_WIDTH/2 - raylib::measure_text("GAME PAUSED", 40)/2, SCREEN_HEIGHT / 2 - 40, 40, raylib::GRAY);
}
else
{
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();
}
// 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();
}

View File

@@ -0,0 +1,793 @@
module tetris;
/**
* 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
if (check_detection()) detection = true;
// 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 bool check_detection()
{
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))) return true;
}
}
return false;
}
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;
}

View File

@@ -1,167 +1,791 @@
module foo;
extern fn void printf(char*, ...);
module tetris;
/**
* 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)
*/
enum Foo : int (int offset, char* extra_name, double x)
//----------------------------------------------------------------------------------
// 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
{
BAZ(12, "hello", 3.0),
BOO(33, "oekfe", 4.0) = 3,
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()
{
int screenWidth = 800;
int screenHeight = 450;
// Initialization (Note windowTitle is unused on Android)
//---------------------------------------------------------
raylib::init_window(SCREEN_WIDTH, SCREEN_HEIGHT, "classic game: tetris");
raylib::init_window(screenWidth, screenHeight, "raylib [core] example - keyboard input");
init_game();
Vector2 ballPosition = { (float)screenWidth/2, (float)screenHeight/2 };
raylib::set_target_fps(60); // Set our game to run at 60 frames-per-second
raylib::set_target_fps(60);
//--------------------------------------------------------------------------------------
foo2::tester(screenHeight);
// Main game loop
while (!raylib::window_should_close()) // Detect window close button or ESC key
{
// Update
// Update and Draw
//----------------------------------------------------------------------------------
if (raylib::is_key_down(KeyboardKey.RIGHT)) ballPosition.x += 2.0f;
if (raylib::is_key_down(KeyboardKey.LEFT)) ballPosition.x -= 2.0f;
if (raylib::is_key_down(KeyboardKey.UP)) ballPosition.y -= 2.0f;
if (raylib::is_key_down(KeyboardKey.DOWN)) ballPosition.y += 2.0f;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
raylib::begin_drawing();
raylib::clear_background(raylib::RAYWHITE);
raylib::draw_text("move the ball with arrow keys", 10, 10, 20, raylib::DARKGRAY);
raylib::draw_circle_v(ballPosition, 50, raylib::MAROON);
raylib::end_drawing();
update_draw_frame();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
unload_game(); // Unload loaded data (textures, sounds, models...)
raylib::close_window(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
}
/*
struct Game
//--------------------------------------------------------------------------------------
// Game Module Functions Definition
//--------------------------------------------------------------------------------------
// Initialize game variables
fn void init_game()
{
int answer;
bool done;
int guesses;
int high;
// 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;
}
}
}
int err_count = 0;
import "core:bufio"
import "core:fmt"
import "core:io"
import "core:mem"
import "core:os"
import "core:strconv"
import "core:time"
import "core:math/rand"
Game :: struct {
answer: int,
done: bool,
guesses: int,
high: int,
}
int err_count = 0;
*/
/*
fn int ask_guess(int high)
// Update game (one frame)
fn void update_game()
{
libc::printf("Guess a number between 1 and %d: ", high);
}
ask_guess :: proc(high: int) -> (result: int, ok: bool) {
fmt.printf("Guess a number between 1 and %d: ", high)
if text, ok := read_line(); ok {
defer mem.delete(text)
return strconv.parse_int(s = text, base = 10)
if (game_over)
{
if (raylib::is_key_pressed(keyboard::ENTER))
{
init_game();
game_over = false;
}
return;
}
return
}
if (raylib::is_key_pressed((KeyboardKey)'P')) pause = !pause;
ask_guess_multi :: proc(high: int) -> int {
for {
if result, ok := ask_guess(high); ok {
return result
}
fmt.println("I didn't understand")
err_count += 1
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;
}
}
}
}
pick_answer :: proc(high: int, r: ^rand.Rand) -> int {
return rand.int_max(high, r) + 1
}
play :: proc(game: ^Game) {
for !game.done {
guess := ask_guess_multi(game.high)
report(game^, guess)
game^ = update(game^, guess)
}
}
read_line :: proc() -> (result: string, ok: bool) {
// See also:
// - https://github.com/odin-lang/Odin/issues/1214
// - https://p.teknik.io/Raw/IT996
s := os.stream_from_handle(os.stdin)
r: bufio.Reader
bufio.reader_init(&r, io.Reader{s})
defer bufio.reader_destroy(&r)
if line, err := bufio.reader_read_string(&r, '\n'); err == .None {
return line[:len(line) - 1], true
}
return
}
report :: proc(game: Game, guess: int) {
// game.done = true
// fmt.println(&game)
description := (
"too low" if guess < game.answer else
"too high" if guess > game.answer else
"the answer!"
)
fmt.println(guess, "is", description)
}
update :: proc(game: Game, guess: int) -> (next: Game) {
next = game
next.done = guess == game.answer
next.guesses += 1
return
}
main :: proc() {
high :: 100
r := rand.create(transmute(u64)time.now())
// Or use nil for default random.
answer := pick_answer(high, &r)
game := Game {answer = answer, done = false, guesses = 0, high = high}
play(&game)
fmt.println("Finished in", game.guesses, "guesses");
fmt.println("Total input errors:", err_count)
}
*/
module foo2;
fn void tester(int x)
// Draw game (one frame)
fn void draw_game()
{
assert(x > 1000, "Shit!");
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;
}

View File

@@ -164,7 +164,7 @@ LLVMValueRef llvm_emit_coerce_alignment(GenContext *c, BEValue *be_value, LLVMTy
LLVMValueRef target = LLVMBuildBitCast(c->builder, cast, LLVMPointerType(coerce_type, 0), "");
llvm_store_value_aligned(c, target, be_value, target_alignment);
*resulting_alignment = target_alignment;
return cast;
return target;
}
*resulting_alignment = be_value->alignment;
return LLVMBuildBitCast(c->builder, be_value->value, LLVMPointerType(coerce_type, 0), "");

View File

@@ -191,6 +191,7 @@ bool float_const_fits_type(const ExprConst *expr_const, TypeKind kind)
default:
UNREACHABLE
}
assert(expr_const->const_kind == CONST_FLOAT);
return expr_const->fxx.f >= -lo_limit && expr_const->fxx.f <= hi_limit;
}

View File

@@ -671,6 +671,16 @@ bool may_convert_float_const_implicit(Expr *expr, Type *to_type)
bool may_convert_int_const_implicit(Expr *expr, Type *to_type)
{
Type *to_type_flat = type_flatten(to_type);
switch (to_type_flat->type_kind)
{
case ALL_FLOATS:
case TYPE_BOOL:
return true;
case ALL_INTS:
break;
default:
return false;
}
if (expr_const_will_overflow(&expr->const_expr, to_type_flat->type_kind))
{
sema_error_const_int_out_of_range(expr, expr, to_type);

View File

@@ -883,15 +883,17 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to,
Decl *private_symbol = NULL;
DEBUG_LOG("Now resolving %s", expr->identifier_expr.ident);
// Just start with inference
if (!expr->identifier_expr.path && to)
{
if (find_possible_inferred_identifier(to, expr)) return true;
}
Decl *decl = sema_find_path_symbol(context, expr->identifier_expr.ident, expr->identifier_expr.path);
// Is this a broken decl?
if (!decl_ok(decl)) return false;
// Just no real way to find it, try inference
if (!decl && !expr->identifier_expr.path && to)
{
if (find_possible_inferred_identifier(to, expr)) return true;
}
// Rerun if we can't do inference.
if (!decl)
@@ -3051,6 +3053,7 @@ static inline void expr_replace_with_enum_array(Expr *enum_array_expr, Decl *enu
Expr *expr = expr_new(EXPR_CONST, span);
expr->const_expr.const_kind = CONST_ENUM;
expr->const_expr.enum_val = decl;
assert(decl_ok(decl));
expr->type = kind;
expr->resolve_status = RESOLVE_DONE;
vec_add(element_values, expr);

View File

@@ -187,13 +187,8 @@ static Decl *sema_resolve_path_symbol(SemaContext *context, NameResolve *name_re
return decl ? decl : sema_find_decl_in_global(&global_context.symbols, global_context.module_list, name_resolve, false);
}
static Decl *sema_resolve_no_path_symbol(SemaContext *context, NameResolve *name_resolve)
static inline Decl *sema_find_local(SemaContext *context, const char *symbol)
{
Decl *decl = NULL;
const char *symbol = name_resolve->symbol;
assert(name_resolve->path == NULL);
Decl **locals = context->locals;
if (context->active_scope.current_local > 0)
{
@@ -210,7 +205,7 @@ static Decl *sema_resolve_no_path_symbol(SemaContext *context, NameResolve *name
VarDeclKind kind = cur->var.kind;
// In this case, we erase the value from parent scopes, so it isn't visible here.
if (kind == VARDECL_ERASE) goto JUMP_ERASED;
if (kind == VARDECL_ERASE) return NULL;
if (kind == VARDECL_REWRAPPED) return cur->var.alias;
}
return cur;
@@ -218,7 +213,18 @@ static Decl *sema_resolve_no_path_symbol(SemaContext *context, NameResolve *name
current--;
}
}
JUMP_ERASED:;
return NULL;
}
static Decl *sema_resolve_no_path_symbol(SemaContext *context, NameResolve *name_resolve)
{
Decl *decl = NULL;
const char *symbol = name_resolve->symbol;
assert(name_resolve->path == NULL);
Decl *found = sema_find_local(context, symbol);
if (found) return found;
CompilationUnit *unit = context->unit;
@@ -507,7 +513,8 @@ bool sema_add_local(SemaContext *context, Decl *decl)
// Ignore synthetic locals.
if (!decl->name) return true;
if (decl->decl_kind == DECL_VAR && decl->var.shadow) goto ADD_VAR;
Decl *other = sema_find_symbol(context, decl->name);
Decl *other = sema_find_local(context, decl->name);
assert(!other || other->module);
if (other && (other->module == current_module || other->is_autoimport))
{

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.2.0"
#define COMPILER_VERSION "0.2.1"

View File

@@ -0,0 +1,47 @@
// #target: macos-x64
module foo;
struct Rectangle
{
float x; // Rectangle top-left corner position x
float y; // Rectangle top-left corner position y
float width; // Rectangle width
float height; // Rectangle height
}
fn void test(Rectangle r)
{
test(Rectangle { 1, 2, 3, 4 });
}
/* #expect: foo.ll
define void @foo.test(<2 x float> %0, <2 x float> %1) #0 {
entry:
%r = alloca %Rectangle, align 4
%literal = alloca %Rectangle, align 4
%coerce = alloca %Rectangle, align 8
%pair = bitcast %Rectangle* %r to { <2 x float>, <2 x float> }*
%2 = getelementptr inbounds { <2 x float>, <2 x float> }, { <2 x float>, <2 x float> }* %pair, i32 0, i32 0
store <2 x float> %0, <2 x float>* %2, align 4
%3 = getelementptr inbounds { <2 x float>, <2 x float> }, { <2 x float>, <2 x float> }* %pair, i32 0, i32 1
store <2 x float> %1, <2 x float>* %3, align 4
%4 = getelementptr inbounds %Rectangle, %Rectangle* %literal, i32 0, i32 0
store float 1.000000e+00, float* %4, align 4
%5 = getelementptr inbounds %Rectangle, %Rectangle* %literal, i32 0, i32 1
store float 2.000000e+00, float* %5, align 4
%6 = getelementptr inbounds %Rectangle, %Rectangle* %literal, i32 0, i32 2
store float 3.000000e+00, float* %6, align 4
%7 = getelementptr inbounds %Rectangle, %Rectangle* %literal, i32 0, i32 3
store float 4.000000e+00, float* %7, align 4
%8 = bitcast %Rectangle* %coerce to { <2 x float>, <2 x float> }*
%9 = bitcast { <2 x float>, <2 x float> }* %8 to i8*
%10 = bitcast %Rectangle* %literal to i8*
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %9, i8* align 4 %10, i32 16, i1 false)
%11 = getelementptr inbounds { <2 x float>, <2 x float> }, { <2 x float>, <2 x float> }* %8, i32 0, i32 0
%lo = load <2 x float>, <2 x float>* %11, align 8
%12 = getelementptr inbounds { <2 x float>, <2 x float> }, { <2 x float>, <2 x float> }* %8, i32 0, i32 1
%hi = load <2 x float>, <2 x float>* %12, align 8
call void @foo.test(<2 x float> %lo, <2 x float> %hi)
ret void
}

View File

@@ -0,0 +1,24 @@
// #target: macos-x64
module foo;
fn void test()
{
float x = 12;
x *= -1;
double y = x;
}
/* #expect: foo.ll
define void @foo.test() #0 {
entry:
%x = alloca float, align 4
%y = alloca double, align 8
store float 1.200000e+01, float* %x, align 4
%0 = load float, float* %x, align 4
%fmul = fmul float %0, -1.000000e+00
store float %fmul, float* %x, align 4
%1 = load float, float* %x, align 4
%fpfpext = fpext float %1 to double
store double %fpfpext, double* %y, align 8
ret void
}

View File

@@ -0,0 +1,10 @@
int foo;
fn void x()
{
double foo = 123;
}
fn void y(int foo)
{
}