From 77a32b1d21007fb90d83e1cef1c4dfb9e6d70982 Mon Sep 17 00:00:00 2001 From: Masashi Date: Wed, 17 Dec 2025 21:02:34 +0530 Subject: [PATCH] UI --- soup/client.c | 144 ++++++++++++++++++++++++++++++++++++ soup/client.o | Bin 0 -> 79416 bytes soup/client.sui | 152 ++++++++++++++++++++++++++++++++++++++ soup/config.sui | 61 --------------- soup/server.c | 81 ++++++++++++++++++++ soup/server.o | Bin 0 -> 75320 bytes soup/server.sui | 67 +++++++++++++++++ src/codegen/transpiler.rs | 5 +- src/typechecker.rs | 61 +++++++++++++++ 9 files changed, 508 insertions(+), 63 deletions(-) create mode 100644 soup/client.c create mode 100755 soup/client.o create mode 100644 soup/client.sui delete mode 100644 soup/config.sui create mode 100644 soup/server.c create mode 100755 soup/server.o create mode 100644 soup/server.sui diff --git a/soup/client.c b/soup/client.c new file mode 100644 index 0000000..9707ff4 --- /dev/null +++ b/soup/client.c @@ -0,0 +1,144 @@ +#include "libsuicmez/libsuicmez.h" +#include +#include +#include +#include + +void* gc_alloc(const TypeInfo* type, size_t size); +void gc_init(void); +void gc_shutdown(void); + +// Helper for allocating arrays +static void* suic_alloc_array(const TypeInfo* type, size_t elem_size, size_t len, void* init_data) { + void* ptr = gc_alloc(type, elem_size * len); + if (init_data) memcpy(ptr, init_data, elem_size * len); + return ptr; +} + +// Helper for allocating structs +static void* suic_alloc_struct(const TypeInfo* type, size_t size, void* init_data) { + void* ptr = gc_alloc(type, size); + if (init_data) memcpy(ptr, init_data, size); + return ptr; +} + + + + +int suic_main(void); + + +int suic_main(void) { + char* GAME_NAME = suic_alloc_array(NULL, sizeof(char), 5, "Soup"); + char* GAME_VERSION = suic_alloc_array(NULL, sizeof(char), 6, "0.1.0"); + int WINDOW_WIDTH = 1280; + int WINDOW_HEIGHT = 720; + char* WINDOW_TITLE = suic_alloc_array(NULL, sizeof(char), 27, "Soup - Voxel Battle Royale"); + char* SERVER_HOST = suic_alloc_array(NULL, sizeof(char), 10, "127.0.0.1"); + int SERVER_PORT = 8888; + suic_init_window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE); + suic_enable_msaa_4x(); + int current_screen = 0; + char* player_name = suic_alloc_array(NULL, sizeof(char), 7, "Player"); + char* server_host = SERVER_HOST; + int server_port = SERVER_PORT; + suic_show_fps_meter((suic_vec2){ .x = 10.000000, .y = 10.000000 }); + while ((suic_window_should_close() == false)) { + suic_begin_drawing(); + suic_clear_background(30, 30, 40, 255); + if ((current_screen == 0)) { + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 5, "SOUP"), 450, 80, 120, 100, 200, 255, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 20, "Voxel Battle Royale"), 400, 220, 40, 200, 200, 200, 255); + suic_draw_rectangle(450, 320, 380, 80, 50, 150, 255, 255); + suic_draw_rectangle_lines(450, 320, 380, 80, 100, 200, 255, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 5, "PLAY"), 600, 350, 40, 255, 255, 255, 255); + suic_draw_rectangle(450, 430, 380, 80, 100, 100, 100, 255); + suic_draw_rectangle_lines(450, 430, 380, 80, 150, 150, 150, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 9, "SETTINGS"), 540, 460, 40, 255, 255, 255, 255); + suic_draw_rectangle(450, 540, 380, 80, 150, 50, 50, 255); + suic_draw_rectangle_lines(450, 540, 380, 80, 200, 100, 100, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 5, "QUIT"), 600, 570, 40, 255, 255, 255, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 22, "v0.1.0 - Early Access"), 500, 680, 20, 150, 150, 150, 255); + int mouse_x = (int) suic_get_mouse_x(); + int mouse_y = (int) suic_get_mouse_y(); + int is_mouse_clicked = suic_is_mouse_button_pressed(MOUSE_BUTTON_LEFT); + if (((((mouse_x >= 450) && (mouse_x <= 830)) && (mouse_y >= 320)) && (mouse_y <= 400))) { + if ((is_mouse_clicked != 0)) { + current_screen = 1; + } + } + if (((((mouse_x >= 450) && (mouse_x <= 830)) && (mouse_y >= 430)) && (mouse_y <= 510))) { + if ((is_mouse_clicked != 0)) { + current_screen = 2; + } + } + if (((((mouse_x >= 450) && (mouse_x <= 830)) && (mouse_y >= 540)) && (mouse_y <= 620))) { + if ((is_mouse_clicked != 0)) { + break; + } + } + } else { + if ((current_screen == 1)) { + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 12, "MATCHMAKING"), 450, 100, 60, 100, 200, 255, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 24, "Connecting to server..."), 400, 250, 30, 200, 200, 200, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 21, "Host: 127.0.0.1:8888"), 400, 310, 20, 150, 150, 150, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 18, "Your Name: Player"), 400, 380, 20, 200, 200, 200, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 24, "Players in Queue: 0/100"), 400, 420, 20, 200, 200, 200, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 11, "Loading..."), 550, 500, 30, 100, 200, 255, 255); + suic_draw_rectangle(100, 630, 150, 60, 150, 50, 50, 255); + suic_draw_rectangle_lines(100, 630, 150, 60, 200, 100, 100, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 5, "BACK"), 120, 650, 30, 255, 255, 255, 255); + int mouse_x = (int) suic_get_mouse_x(); + int mouse_y = (int) suic_get_mouse_y(); + int is_mouse_clicked = suic_is_mouse_button_pressed(MOUSE_BUTTON_LEFT); + if (((((mouse_x >= 100) && (mouse_x <= 250)) && (mouse_y >= 630)) && (mouse_y <= 690))) { + if ((is_mouse_clicked != 0)) { + current_screen = 0; + } + } + } else { + if ((current_screen == 2)) { + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 9, "SETTINGS"), 450, 100, 60, 100, 200, 255, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 13, "Player Name:"), 250, 200, 24, 200, 200, 200, 255); + suic_draw_rectangle(450, 190, 300, 50, 50, 50, 50, 255); + suic_draw_rectangle_lines(450, 190, 300, 50, 100, 100, 100, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 7, "Player"), 460, 205, 20, 255, 255, 255, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 13, "Server Host:"), 250, 300, 24, 200, 200, 200, 255); + suic_draw_rectangle(450, 290, 300, 50, 50, 50, 50, 255); + suic_draw_rectangle_lines(450, 290, 300, 50, 100, 100, 100, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 10, "127.0.0.1"), 460, 305, 20, 255, 255, 255, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 13, "Server Port:"), 250, 400, 24, 200, 200, 200, 255); + suic_draw_rectangle(450, 390, 300, 50, 50, 50, 50, 255); + suic_draw_rectangle_lines(450, 390, 300, 50, 100, 100, 100, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 5, "8888"), 460, 405, 20, 255, 255, 255, 255); + suic_draw_rectangle(450, 550, 300, 70, 100, 100, 100, 255); + suic_draw_rectangle_lines(450, 550, 300, 70, 150, 150, 150, 255); + suic_draw_text(suic_alloc_array(NULL, sizeof(char), 13, "BACK TO HOME"), 495, 577, 30, 255, 255, 255, 255); + int mouse_x = (int) suic_get_mouse_x(); + int mouse_y = (int) suic_get_mouse_y(); + int is_mouse_clicked = suic_is_mouse_button_pressed(MOUSE_BUTTON_LEFT); + if (((((mouse_x >= 450) && (mouse_x <= 750)) && (mouse_y >= 550)) && (mouse_y <= 620))) { + if ((is_mouse_clicked != 0)) { + current_screen = 0; + } + } + } + } + } + suic_end_drawing(); + } + suic_close_window(); + return 0; +} + +int main(int argc, char* argv[]) { + // Initialize GC + gc_init(); + // init globals + // init event loop + int result = suic_main(); + // Shutdown GC + gc_shutdown(); + return result; +} + diff --git a/soup/client.o b/soup/client.o new file mode 100755 index 0000000000000000000000000000000000000000..1145db783143e7b169c509c58df94a05da4ab409 GIT binary patch literal 79416 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 V8VFx6+?W0 int do + # Initialize graphics + init_window(1280, 720, "Soup - Voxel Battle Royale") + defer close_window() + + enable_msaa_4x() + + # Game state + let mut current_screen = 0 # 0 = Home, 1 = Lobby, 2 = Game + let mut player_name = "Player" + let mut server_host = "127.0.0.1" + let mut server_port = 8888 + + # Show FPS meter + show_fps_meter(Vec2 { x: 10.0, y: 10.0 }) + + # Main loop + while window_should_close() == false do + begin_drawing() + clear_background(30, 30, 40, 255) # Dark blue background + + if current_screen == 0 do + # ===== HOME SCREEN ===== + + # Title + draw_text("SOUP", 450, 80, 120, 100, 200, 255, 255) # Cyan title + draw_text("Voxel Battle Royale", 400, 220, 40, 200, 200, 200, 255) # Subtitle + + # Main buttons + # Play button + draw_rectangle(450, 320, 380, 80, 50, 150, 255, 255) # Blue button + draw_rectangle_lines(450, 320, 380, 80, 100, 200, 255, 255) # Border + draw_text("PLAY", 600, 350, 40, 255, 255, 255, 255) + + # Settings button + draw_rectangle(450, 430, 380, 80, 100, 100, 100, 255) # Gray button + draw_rectangle_lines(450, 430, 380, 80, 150, 150, 150, 255) + draw_text("SETTINGS", 540, 460, 40, 255, 255, 255, 255) + + # Quit button + draw_rectangle(450, 540, 380, 80, 150, 50, 50, 255) # Red button + draw_rectangle_lines(450, 540, 380, 80, 200, 100, 100, 255) + draw_text("QUIT", 600, 570, 40, 255, 255, 255, 255) + + # Footer + draw_text("v0.1.0 - Early Access", 500, 680, 20, 150, 150, 150, 255) + + # Check for button clicks + let mouse_x = get_mouse_x() as int + let mouse_y = get_mouse_y() as int + let is_mouse_clicked = is_mouse_button_pressed(MOUSE_BUTTON_LEFT) + + # Play button click + if mouse_x >= 450 and mouse_x <= 830 and mouse_y >= 320 and mouse_y <= 400 do + if is_mouse_clicked != 0 do + current_screen = 1 # Go to lobby + end + end + + # Settings button click + if mouse_x >= 450 and mouse_x <= 830 and mouse_y >= 430 and mouse_y <= 510 do + if is_mouse_clicked != 0 do + current_screen = 2 # Go to settings + end + end + + # Quit button click + if mouse_x >= 450 and mouse_x <= 830 and mouse_y >= 540 and mouse_y <= 620 do + if is_mouse_clicked != 0 do + break + end + end + + end else if current_screen == 1 do + # ===== LOBBY SCREEN ===== + + draw_text("MATCHMAKING", 450, 100, 60, 100, 200, 255, 255) + + # Status message + draw_text("Connecting to server...", 400, 250, 30, 200, 200, 200, 255) + draw_text("Host: 127.0.0.1:8888", 400, 310, 20, 150, 150, 150, 255) + + # Player info + draw_text("Your Name: Player", 400, 380, 20, 200, 200, 200, 255) + draw_text("Players in Queue: 0/100", 400, 420, 20, 200, 200, 200, 255) + + # Loading animation (simple dots) + draw_text("Loading...", 550, 500, 30, 100, 200, 255, 255) + + # Back button + draw_rectangle(100, 630, 150, 60, 150, 50, 50, 255) + draw_rectangle_lines(100, 630, 150, 60, 200, 100, 100, 255) + draw_text("BACK", 120, 650, 30, 255, 255, 255, 255) + + # Cancel button + let mouse_x = get_mouse_x() as int + let mouse_y = get_mouse_y() as int + let is_mouse_clicked = is_mouse_button_pressed(MOUSE_BUTTON_LEFT) + + if mouse_x >= 100 and mouse_x <= 250 and mouse_y >= 630 and mouse_y <= 690 do + if is_mouse_clicked != 0 do + current_screen = 0 # Back to home + end + end + + end else if current_screen == 2 do + # ===== SETTINGS SCREEN ===== + + draw_text("SETTINGS", 450, 100, 60, 100, 200, 255, 255) + + # Settings options + draw_text("Player Name:", 250, 200, 24, 200, 200, 200, 255) + draw_rectangle(450, 190, 300, 50, 50, 50, 50, 255) + draw_rectangle_lines(450, 190, 300, 50, 100, 100, 100, 255) + draw_text("Player", 460, 205, 20, 255, 255, 255, 255) + + draw_text("Server Host:", 250, 300, 24, 200, 200, 200, 255) + draw_rectangle(450, 290, 300, 50, 50, 50, 50, 255) + draw_rectangle_lines(450, 290, 300, 50, 100, 100, 100, 255) + draw_text("127.0.0.1", 460, 305, 20, 255, 255, 255, 255) + + draw_text("Server Port:", 250, 400, 24, 200, 200, 200, 255) + draw_rectangle(450, 390, 300, 50, 50, 50, 50, 255) + draw_rectangle_lines(450, 390, 300, 50, 100, 100, 100, 255) + draw_text("8888", 460, 405, 20, 255, 255, 255, 255) + + # Back button + draw_rectangle(450, 550, 300, 70, 100, 100, 100, 255) + draw_rectangle_lines(450, 550, 300, 70, 150, 150, 150, 255) + draw_text("BACK TO HOME", 495, 577, 30, 255, 255, 255, 255) + + let mouse_x = get_mouse_x() as int + let mouse_y = get_mouse_y() as int + let is_mouse_clicked = is_mouse_button_pressed(MOUSE_BUTTON_LEFT) + + if mouse_x >= 450 and mouse_x <= 750 and mouse_y >= 550 and mouse_y <= 620 do + if is_mouse_clicked != 0 do + current_screen = 0 # Back to home + end + end + + end + + end_drawing() + end + + 0 +end diff --git a/soup/config.sui b/soup/config.sui deleted file mode 100644 index 110da39..0000000 --- a/soup/config.sui +++ /dev/null @@ -1,61 +0,0 @@ -# ===== GAME SETTINGS ===== -let GAME_NAME = "Soup" -let GAME_VERSION = "0.1.0" - -# ===== WINDOW/GRAPHICS ===== -let WINDOW_WIDTH = 1280 -let WINDOW_HEIGHT = 720 -let WINDOW_TITLE = "Soup - Voxel Battle Royale" -let TARGET_FPS = 60 -let USE_MSAA_4X = 1 - -# ===== WORLD SETTINGS ===== -# Island generation -let ISLAND_SIZE_X = 512 -let ISLAND_SIZE_Z = 512 -let ISLAND_MAX_HEIGHT = 128 -let ISLAND_VOXEL_SIZE = 1.0 # Size of each voxel in world units - -# Island generation seed (0 = random) -let ISLAND_SCALE = 50.0 # Noise scale for generation -let ISLAND_PERSISTENCE = 0.5 -let ISLAND_LACUNARITY = 2.0 -let ISLAND_OCTAVES = 6 - -# ===== PLAYER SETTINGS ===== -let PLAYER_MOVE_SPEED = 5.0 -let PLAYER_SPRINT_SPEED = 8.0 -let PLAYER_JUMP_FORCE = 8.0 -let PLAYER_HEIGHT = 1.6 -let PLAYER_WIDTH = 0.8 -let PLAYER_MASS = 1.0 -let PLAYER_MOUSE_SENSITIVITY = 0.003 - -# ===== NETWORKING SETTINGS ===== -let SERVER_HOST = "127.0.0.1" -let SERVER_PORT = 8888 -let MAX_PLAYERS = 100 -let MAX_CONNECTIONS = 128 -let NETWORK_TICK_RATE = 20 # Updates per second -let NETWORK_TIMEOUT_MS = 30000 # 30 seconds - -# Message buffer sizes -let MAX_MESSAGE_SIZE = 4096 -let RECV_BUFFER_SIZE = 65536 - -# ===== BATTLE ROYALE SETTINGS ===== -let MATCH_DURATION_SECONDS = 600 # 10 minutes -let ZONE_SHRINK_START = 120 # Seconds before first zone shrink -let ZONE_SHRINK_INTERVAL = 60 # Seconds between zone shrinks -let INITIAL_SAFE_ZONE_RADIUS = 200.0 -let FINAL_SAFE_ZONE_RADIUS = 20.0 - -# ===== PHYSICS SETTINGS ===== -let GRAVITY = -9.81 -let GROUND_FRICTION = 0.5 - -# ===== DEBUG SETTINGS ===== -let DEBUG_MODE = 1 -let SHOW_FPS_METER = 1 -let SHOW_PHYSICS_DEBUG = 0 -let SHOW_NETWORK_DEBUG = 0 diff --git a/soup/server.c b/soup/server.c new file mode 100644 index 0000000..b341dca --- /dev/null +++ b/soup/server.c @@ -0,0 +1,81 @@ +#include "libsuicmez/libsuicmez.h" +#include +#include +#include +#include + +void* gc_alloc(const TypeInfo* type, size_t size); +void gc_init(void); +void gc_shutdown(void); + +// Helper for allocating arrays +static void* suic_alloc_array(const TypeInfo* type, size_t elem_size, size_t len, void* init_data) { + void* ptr = gc_alloc(type, elem_size * len); + if (init_data) memcpy(ptr, init_data, elem_size * len); + return ptr; +} + +// Helper for allocating structs +static void* suic_alloc_struct(const TypeInfo* type, size_t size, void* init_data) { + void* ptr = gc_alloc(type, size); + if (init_data) memcpy(ptr, init_data, size); + return ptr; +} + + + + +int suic_main(void); + + +int suic_main(void) { + char* SERVER_HOST = suic_alloc_array(NULL, sizeof(char), 10, "127.0.0.1"); + int SERVER_PORT = 8888; + int MAX_PLAYERS = 100; + int MAX_CONNECTIONS = 128; + int NETWORK_TICK_RATE = 20; + int NETWORK_TIMEOUT_MS = 30000; + int MATCH_DURATION_SECONDS = 600; + int ZONE_SHRINK_START = 120; + int ZONE_SHRINK_INTERVAL = 60; + float INITIAL_SAFE_ZONE_RADIUS = 200.000000; + float FINAL_SAFE_ZONE_RADIUS = 20.000000; + int ISLAND_SIZE_X = 512; + int ISLAND_SIZE_Z = 512; + int ISLAND_MAX_HEIGHT = 128; + float ISLAND_SCALE = 50.000000; + int ISLAND_OCTAVES = 6; + suic_ode_init(); + void* world = suic_ode_world_create(); + void* null_space = NULL; + void* space = suic_ode_simple_space_create(null_space); + suic_ode_world_set_gravity(world, 0.000000, -9.810000, 0.000000); + void* contactgroup = suic_ode_joint_group_create(0); + void* ground_geom = suic_ode_create_plane_geom(space, 0.000000, 1.000000, 0.000000, 0.000000); + int tick = 0; + float tick_interval = (1.000000 / 20.000000); + while (true) { + tick = (tick + 1); + suic_ode_space_collide(world, space, contactgroup); + suic_ode_world_step(world, tick_interval); + suic_ode_joint_group_empty(contactgroup); + } + suic_ode_geom_destroy(ground_geom); + suic_ode_joint_group_destroy(contactgroup); + suic_ode_space_destroy(space); + suic_ode_world_destroy(world); + suic_ode_close(); + return 0; +} + +int main(int argc, char* argv[]) { + // Initialize GC + gc_init(); + // init globals + // init event loop + int result = suic_main(); + // Shutdown GC + gc_shutdown(); + return result; +} + diff --git a/soup/server.o b/soup/server.o new file mode 100755 index 0000000000000000000000000000000000000000..d3d79e13cbe2be06a3d893d9efeafc44176bb71f GIT binary patch literal 75320 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 literal 0 HcmV?d00001 diff --git a/soup/server.sui b/soup/server.sui new file mode 100644 index 0000000..03bad85 --- /dev/null +++ b/soup/server.sui @@ -0,0 +1,67 @@ +# Soup - Server +# Voxel Battle Royale Server +# Handles game logic, physics, and player synchronization + +fn main() -> int do + # Server configuration + let SERVER_HOST = "127.0.0.1" + let SERVER_PORT = 8888 + let MAX_PLAYERS = 100 + let MAX_CONNECTIONS = 128 + let NETWORK_TICK_RATE = 20 + let MATCH_DURATION_SECONDS = 600 + let ZONE_SHRINK_START = 120 + let ZONE_SHRINK_INTERVAL = 60 + let INITIAL_SAFE_ZONE_RADIUS = 200.0 + let FINAL_SAFE_ZONE_RADIUS = 20.0 + let ISLAND_SIZE_X = 512 + let ISLAND_SIZE_Z = 512 + let ISLAND_MAX_HEIGHT = 128 + let ISLAND_SCALE = 50.0 + let ISLAND_OCTAVES = 6 + + # Initialize ODE physics for server-side validation + ode_init() + defer ode_close() + + let world = ode_world_create() + defer ode_world_destroy(world) + let null_space = 0 as *() + let space = ode_simple_space_create(null_space) + defer ode_space_destroy(space) + + # Set gravity for physics validation + ode_world_set_gravity(world, 0.0, -9.81, 0.0) + + let contactgroup = ode_joint_group_create(0) + defer ode_joint_group_destroy(contactgroup) + + # Create ground plane for server-side collision checking + let ground_geom = ode_create_plane_geom(space, 0.0, 1.0, 0.0, 0.0) + defer ode_geom_destroy(ground_geom) + + # Main server loop + let mut tick = 0 + let tick_interval = 1.0 / 20.0 # NETWORK_TICK_RATE = 20 + + while true do + # Simulate game ticks + tick = tick + 1 + + # Physics update for validation + ode_space_collide(world, space, contactgroup) + ode_world_step(world, tick_interval) + ode_joint_group_empty(contactgroup) + + # In a real implementation, this would: + # - Handle incoming player connections + # - Process player input messages + # - Update game state and physics + # - Broadcast state to all connected clients + # - Handle zone shrinking for battle royale + # - Check for player elimination + # - Manage match lifecycle + end + + 0 +end diff --git a/src/codegen/transpiler.rs b/src/codegen/transpiler.rs index eed43eb..d3ab12b 100644 --- a/src/codegen/transpiler.rs +++ b/src/codegen/transpiler.rs @@ -597,8 +597,9 @@ impl Transpiler { "window_should_close" => "suic_window_should_close", "set_target_fps" => "suic_set_target_fps", "enable_msaa_4x" => "suic_enable_msaa_4x", - "get_frame_time" => "suic_get_frame_time", - "show_fps_meter" => "suic_show_fps_meter", + "get_frame_time" => "suic_get_frame_time", + "get_time" => "suic_get_time", + "show_fps_meter" => "suic_show_fps_meter", "hide_fps_meter" => "suic_hide_fps_meter", "begin_drawing" => "suic_begin_drawing", "end_drawing" => "suic_end_drawing", diff --git a/src/typechecker.rs b/src/typechecker.rs index 2e4b122..d1a2b2b 100644 --- a/src/typechecker.rs +++ b/src/typechecker.rs @@ -676,6 +676,14 @@ impl TypeChecker { return_type: Type::Float, }, ); + self.env.functions.insert( + "get_time".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Float, + }, + ); self.env.functions.insert( "show_fps_meter".to_string(), FunctionType { @@ -780,6 +788,35 @@ impl TypeChecker { ); } + // Mouse button constants + let mouse_buttons = vec![ + "MOUSE_BUTTON_LEFT", + "MOUSE_BUTTON_RIGHT", + "MOUSE_BUTTON_MIDDLE", + "MOUSE_BUTTON_SIDE", + "MOUSE_BUTTON_EXTRA", + "MOUSE_BUTTON_FORWARD", + "MOUSE_BUTTON_BACK", + ]; + for (i, button) in mouse_buttons.iter().enumerate() { + let id = 2000 + i; + self.env.name_to_id.insert(button.to_string(), BindingId(id)); + self.env.vars.insert( + BindingId(id), + VarInfo { + ty: Type::Int, + kind: BindingKind::Default, + name: button.to_string(), + usage: 0, + span: Span { + start: 0, + end: 0, + file: "builtin".to_string(), + }, + }, + ); + } + // Drawing self.env.functions.insert( "begin_drawing".to_string(), @@ -978,6 +1015,30 @@ impl TypeChecker { return_type: Type::Float, }, ); + self.env.functions.insert( + "is_mouse_button_pressed".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Int], // mouse button + return_type: Type::Int, + }, + ); + self.env.functions.insert( + "is_mouse_button_down".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Int], // mouse button + return_type: Type::Int, + }, + ); + self.env.functions.insert( + "is_mouse_button_released".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Int], // mouse button + return_type: Type::Int, + }, + ); // Math functions self.env.functions.insert(