From 7b73c861132dd4f512990765ec5cfde1d8c28e48 Mon Sep 17 00:00:00 2001 From: Masashi Date: Wed, 17 Dec 2025 15:38:06 +0530 Subject: [PATCH] added anti aliasing. new fps game --- README.md | 88 --- compile.sh | 24 +- compile_and_run.sh | 22 +- fishsoup/main | Bin 0 -> 43560 bytes fishsoup/main.c | 141 ++++ fishsoup/main.o | Bin 0 -> 43560 bytes fishsoup/main.sui | 158 ++++ fps_game | Bin 0 -> 49256 bytes libsuicmez/libsuicmez.c | 939 ++++++++++++++---------- libsuicmez/libsuicmez.h | 93 ++- libsuicmez/suicmez_gc.c | 20 +- libsuicmez/suicmez_gc.h | 1 + src/c_ir.rs | 18 +- src/c_lowerer/declaration_transpiler.rs | 1 + src/c_lowerer/statements_transpiler.rs | 14 + src/codegen/transpiler.rs | 185 ++++- src/lexer/mod.rs | 4 +- src/lexer/tests.rs | 4 +- src/main.rs | 12 +- src/typechecker.rs | 201 +++++ test_player.c | 46 ++ test_player.sui | 1 + test_window | Bin 0 -> 44536 bytes test_window.c | 53 ++ test_window.sui | 1 + tests/basic_types.c | 49 ++ tests/basic_types.o | Bin 0 -> 39184 bytes tests/control_flow.c | 50 ++ tests/fps_game.c | 216 ++++++ tests/fps_game.o | Bin 0 -> 49432 bytes tests/fps_game.sui | 271 +++++++ tests/functions.c | 52 ++ tests/game_3d_improved.c | 89 +++ tests/game_3d_improved.o | Bin 0 -> 45248 bytes tests/ode_test.c | 51 ++ tests/ode_test.o | Bin 0 -> 45240 bytes tests/ode_voxel_example.c | 64 ++ tests/ode_voxel_example.o | Bin 0 -> 45248 bytes tests/structs.c | 68 ++ tests/structs.o | Bin 0 -> 45488 bytes 40 files changed, 2379 insertions(+), 557 deletions(-) delete mode 100644 README.md create mode 100755 fishsoup/main create mode 100644 fishsoup/main.c create mode 100755 fishsoup/main.o create mode 100644 fishsoup/main.sui create mode 100755 fps_game create mode 100644 test_player.c create mode 100644 test_player.sui create mode 100755 test_window create mode 100644 test_window.c create mode 100644 test_window.sui create mode 100644 tests/basic_types.c create mode 100755 tests/basic_types.o create mode 100644 tests/control_flow.c create mode 100644 tests/fps_game.c create mode 100755 tests/fps_game.o create mode 100644 tests/fps_game.sui create mode 100644 tests/functions.c create mode 100644 tests/game_3d_improved.c create mode 100755 tests/game_3d_improved.o create mode 100644 tests/ode_test.c create mode 100755 tests/ode_test.o create mode 100644 tests/ode_voxel_example.c create mode 100755 tests/ode_voxel_example.o create mode 100644 tests/structs.c create mode 100755 tests/structs.o diff --git a/README.md b/README.md deleted file mode 100644 index 33bb998..0000000 --- a/README.md +++ /dev/null @@ -1,88 +0,0 @@ -# ODE Physics Engine Integration - -## ✅ ODE Integration Complete - -Full Open Dynamics Engine (ODE) support has been integrated into suicmez for 3D physics simulation, perfect for voxel games! - -## Available ODE Functions - -### Initialization and Cleanup -- `ode_init()` - Initialize the ODE library -- `ode_close()` - Clean up ODE resources - -### World Management -- `ode_world_create()` - Create a new physics world -- `ode_world_destroy(world)` - Destroy a physics world -- `ode_world_set_gravity(world, x, y, z)` - Set world gravity -- `ode_world_step(world, stepsize)` - Advance physics simulation - -### Rigid Bodies -- `ode_body_create(world)` - Create a new rigid body -- `ode_body_destroy(body)` - Destroy a rigid body -- `ode_body_set_position(body, x, y, z)` - Set body position -- `ode_body_set_linear_vel(body, x, y, z)` - Set linear velocity - -### Mass and Geometry -- `ode_body_set_box_mass(body, density, lx, ly, lz)` - Set box-shaped mass -- `ode_create_box_geom(space, lx, ly, lz)` - Create box collision geometry -- `ode_geom_set_body(geom, body)` - Attach geometry to body -- `ode_geom_destroy(geom)` - Destroy geometry - -### Collision Spaces -- `ode_simple_space_create(parent)` - Create collision space -- `ode_space_destroy(space)` - Destroy collision space - -## Example Usage - -```sui -# Initialize physics -ode_init() - -# Create world with gravity -let world = ode_world_create() -let space = ode_simple_space_create(0 as *()) # null parent -ode_world_set_gravity(world, 0.0, -9.81, 0.0) - -# Create a falling voxel/box -let body = ode_body_create(world) -ode_body_set_box_mass(body, 1.0, 1.0, 1.0, 1.0) # 1x1x1 meter box -ode_body_set_position(body, 0.0, 5.0, 0.0) # Start 5 units up - -let geom = ode_create_box_geom(space, 1.0, 1.0, 1.0) -ode_geom_set_body(geom, body) - -# Simulate physics -let mut i = 0 -while i < 100 do - ode_world_step(world, 0.016) # 60 FPS - i = i + 1 -end - -# Cleanup -ode_geom_destroy(geom) -ode_body_destroy(body) -ode_space_destroy(space) -ode_world_destroy(world) -ode_close() -``` - -## Compilation - -Use the updated compile scripts which now include ODE: - -```bash -./compile.sh tests/your_ode_program.sui -./compile_and_run.sh tests/your_ode_program.sui -``` - -## ODE Version - -Currently using: **ODE 0.16.6** - -- Real-time rigid body dynamics -- Collision detection -- Joint constraints -- Stable simulation for games - -All ODE features are now available through suicmez for building physics-based voxel games! -ODE_INTEGRATION.md \ No newline at end of file diff --git a/compile.sh b/compile.sh index 17832da..692994e 100755 --- a/compile.sh +++ b/compile.sh @@ -1,17 +1,27 @@ #!/bin/bash # Simple helper script to compile Sui code and link with libsuicmez +DEBUG_FLAG="" +if [ "$1" = "--debug" ]; then + DEBUG_FLAG="--debug" + shift +fi + if [ $# -eq 0 ]; then - echo "Usage: ./compile.sh [output_name]" + echo "Usage: ./compile.sh [--debug] [output_name]" echo "" - echo "Example:" + echo "Options:" + echo " --debug Generate debug printf statements in the C output" + echo "" + echo "Examples:" echo " ./compile.sh tests/structs.sui" + echo " ./compile.sh --debug tests/structs.sui" echo " ./compile.sh tests/structs.sui my_program" exit 1 fi INPUT_SUI="$1" -OUTPUT_NAME="${2:-${INPUT_NAME%.sui}}" +OUTPUT_NAME="${2:-${INPUT_SUI%.sui}}" if [ ! -f "$INPUT_SUI" ]; then echo "Error: File not found: $INPUT_SUI" @@ -20,7 +30,11 @@ fi # Compile Sui to C echo "Compiling $INPUT_SUI to C..." -cargo run "$INPUT_SUI" || exit 1 +if [ -n "$DEBUG_FLAG" ]; then + cargo run -- "$DEBUG_FLAG" "$INPUT_SUI" || exit 1 +else + cargo run -- "$INPUT_SUI" || exit 1 +fi # Get the C file name (should be next to the .sui file) C_FILE="${INPUT_SUI%.sui}.c" @@ -45,7 +59,7 @@ ODE_LIBS=$(pkg-config --libs ode 2>/dev/null || echo "-lode -lm") # Compile C to executable with raylib and ODE support echo "Compiling C code and linking with libsuicmez, raylib, and ODE..." -gcc "$C_FILE" libsuicmez/libsuicmez.c $RAYLIB_CFLAGS $RAYLIB_LIBS $ODE_CFLAGS $ODE_LIBS -o "$OUTPUT_BINARY" || exit 1 +gcc "$C_FILE" libsuicmez/libsuicmez.c libsuicmez/suicmez_gc.c $RAYLIB_CFLAGS $RAYLIB_LIBS $ODE_CFLAGS $ODE_LIBS -lm -o "$OUTPUT_BINARY" || exit 1 echo "✓ Successfully created: $OUTPUT_BINARY" echo " Run with: ./$OUTPUT_BINARY" diff --git a/compile_and_run.sh b/compile_and_run.sh index 008b47d..478cdc0 100755 --- a/compile_and_run.sh +++ b/compile_and_run.sh @@ -1,11 +1,21 @@ #!/bin/bash # Compile Sui source to C, then compile and run the executable +DEBUG_FLAG="" +if [ "$1" = "--debug" ]; then + DEBUG_FLAG="--debug" + shift +fi + if [ $# -eq 0 ]; then - echo "Usage: ./compile_and_run.sh [program_args...]" + echo "Usage: ./compile_and_run.sh [--debug] [program_args...]" + echo "" + echo "Options:" + echo " --debug Generate debug printf statements in the C output" echo "" echo "Examples:" echo " ./compile_and_run.sh tests/structs.sui" + echo " ./compile_and_run.sh --debug tests/structs.sui" echo " ./compile_and_run.sh tests/myprogram.sui arg1 arg2" exit 1 fi @@ -28,7 +38,13 @@ echo "━━━━━━━━━━━━━━━━━━━━━━━━ echo "Step 1: Compiling Sui to C..." echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -if ! cargo run "$INPUT_SUI" > /dev/null 2>&1; then +if [ -n "$DEBUG_FLAG" ]; then + CARGO_CMD="cargo run -- \"$DEBUG_FLAG\" \"$INPUT_SUI\"" +else + CARGO_CMD="cargo run -- \"$INPUT_SUI\"" +fi + +if ! eval "$CARGO_CMD" > /dev/null 2>&1; then echo "" echo "✗ Sui compilation failed" exit 1 @@ -54,7 +70,7 @@ RAYLIB_LIBS=$(pkg-config --libs raylib 2>/dev/null || echo "-lraylib -lm") ODE_CFLAGS=$(pkg-config --cflags ode 2>/dev/null || echo "-I/usr/include") ODE_LIBS=$(pkg-config --libs ode 2>/dev/null || echo "-lode -lm") -if ! gcc "$C_FILE" libsuicmez/libsuicmez.c $RAYLIB_CFLAGS $RAYLIB_LIBS $ODE_CFLAGS $ODE_LIBS -o "$OUTPUT_BINARY" 2>&1; then +if ! gcc "$C_FILE" libsuicmez/libsuicmez.c libsuicmez/suicmez_gc.c $RAYLIB_CFLAGS $RAYLIB_LIBS $ODE_CFLAGS $ODE_LIBS -lm -o "$OUTPUT_BINARY" 2>&1; then echo "" echo "✗ C compilation failed" exit 1 diff --git a/fishsoup/main b/fishsoup/main new file mode 100755 index 0000000000000000000000000000000000000000..2a5d72124fff864969cda6ef9c7f95d8781210c5 GIT binary patch literal 43560 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 +#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; +} + + +struct Vec2 { + float x; + float y; +}; + +static const uint8_t sui_bitmap_Vec2[] = { 0, 0 }; +static const TypeInfo sui_typeinfo_Vec2 = { + .field_count = 2, + .pointer_count = 0, + .pointer_bitmap = sui_bitmap_Vec2 +}; + +int suic_main(void); + + +int suic_main(void) { + suic_init_window(800, 600, suic_alloc_array(NULL, sizeof(char), 31, "Fishsoup - Basic 3D Platformer")); + suic_set_target_fps(60); + suic_ode_init(); + void* world = suic_ode_world_create(); + void* null_space = (struct unit**) 0; + 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* player_body = suic_ode_body_create(world); + suic_ode_body_set_box_mass(player_body, 1.000000, 1.000000, 1.000000, 1.000000); + suic_ode_body_set_position(player_body, 0.000000, 1.000000, 0.000000); + void* player_geom = suic_ode_create_box_geom(space, 1.000000, 1.000000, 1.000000); + suic_ode_geom_set_body(player_geom, player_body); + void* ground_geom = suic_ode_create_plane_geom(space, 0.000000, 1.000000, 0.000000, 0.500000); + suic_ode_body_set_linear_vel(player_body, 0.000000, 0.000000, 0.000000); + float player_x = 0.000000; + float player_y = 0.000000; + float player_z = 0.000000; + float player_angle = 0.000000; + float camera_distance = 5.000000; + float camera_height = 2.000000; + float mouse_x = 0.000000; + float mouse_y = 0.000000; + float last_mouse_x = 0.000000; + float last_mouse_y = 0.000000; + float vel_x = 0.000000; + float vel_y = 0.000000; + float vel_z = 0.000000; + while ((suic_window_should_close() == false)) { + mouse_x = suic_get_mouse_x(); + mouse_y = suic_get_mouse_y(); + float mouse_delta_x = (mouse_x - last_mouse_x); + float mouse_delta_y = (mouse_y - last_mouse_y); + last_mouse_x = mouse_x; + last_mouse_y = mouse_y; + float mouse_sensitivity = 0.005000; + player_angle = (player_angle - (mouse_delta_x * mouse_sensitivity)); + suic_ode_space_collide(world, space, contactgroup); + suic_ode_world_step(world, (1.000000 / 60.000000)); + suic_ode_joint_group_empty(contactgroup); + suic_ode_body_get_linear_vel(player_body, &vel_x, &vel_y, &vel_z); + float move_speed = 5.000000; + bool w_pressed = suic_is_key_down(87); + bool s_pressed = suic_is_key_down(83); + bool a_pressed = suic_is_key_down(65); + bool d_pressed = suic_is_key_down(68); + if (w_pressed) { + vel_x = (sin(player_angle) * move_speed); + vel_z = (cos(player_angle) * move_speed); + suic_ode_body_set_linear_vel(player_body, vel_x, vel_y, vel_z); + } + if (s_pressed) { + vel_x = (-sin(player_angle) * move_speed); + vel_z = (-cos(player_angle) * move_speed); + suic_ode_body_set_linear_vel(player_body, vel_x, vel_y, vel_z); + } + if (a_pressed) { + vel_x = (sin((player_angle + (3.141590 / 2.000000))) * move_speed); + vel_z = (cos((player_angle + (3.141590 / 2.000000))) * move_speed); + suic_ode_body_set_linear_vel(player_body, vel_x, vel_y, vel_z); + } + if (d_pressed) { + vel_x = (sin((player_angle - (3.141590 / 2.000000))) * move_speed); + vel_z = (cos((player_angle - (3.141590 / 2.000000))) * move_speed); + suic_ode_body_set_linear_vel(player_body, vel_x, vel_y, vel_z); + } + suic_ode_body_get_position(player_body, &player_x, &player_y, &player_z); + float camera_x = (player_x - (sin(player_angle) * camera_distance)); + float camera_y = (player_y + camera_height); + float camera_z = (player_z - (cos(player_angle) * camera_distance)); + suic_begin_drawing(); + suic_clear_background(135, 206, 235, 255); + suic_begin_mode3d(camera_x, camera_y, camera_z, player_x, player_y, player_z, 0.000000, 1.000000, 0.000000, 45.000000, 0); + suic_draw_cube(0.000000, -0.500000, 0.000000, 20.000000, 1.000000, 20.000000, 34, 139, 34, 255); + suic_draw_cube(player_x, player_y, player_z, 1.000000, 1.000000, 1.000000, 0, 255, 0, 255); + suic_end_mode3d(); + suic_end_drawing(); + } + suic_ode_geom_destroy(ground_geom); + suic_ode_geom_destroy(player_geom); + suic_ode_body_destroy(player_body); + suic_ode_joint_group_destroy(contactgroup); + suic_ode_space_destroy(space); + suic_ode_world_destroy(world); + suic_ode_close(); + 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/fishsoup/main.o b/fishsoup/main.o new file mode 100755 index 0000000000000000000000000000000000000000..1e14c563fba66044415641b5844683dc3e8810a7 GIT binary patch literal 43560 zcmeHw4R}=5wf0G1Fj{dY7TWj+qoR#J(13`bA|c7Z0f`1kkWz3m%uK>aGLz0s__3nV zfXz6@rv4TE)TaIw`_(q>MM{;*fRsc;8!cC(rIK3o&Is0ssL@jAd)L}~&zza$;Qj9H z_k7QNo*bT;wb##Hd+oK?UVHCz&V*YW^JeAdjzT%Qh?%=1Dq{sorME&xU78IR%x41gW0c)$vWiQBbo9oa$Mq zXs0h+cK%Mm9hV4PL1R5`uUg7y!I)Lh6*Sf(-?Xh0{A{>Yb|U_Ya*&YA1)zEzvR*c{ zkpM0Ql|M-xeJZ57Y*-8)UB&#ZY1#GKWW8)SPRc7tZO}!KKJ5X*20}YiQ|?WT*}`|j z9;%mZpTdh}Jq4AW6|!EeS_ovrqtY)5Dm&++9{KY>d&zLo7RdIp$4%i4vONVUzUZQM zi}0aXn|)1{mfNJoh^F{CS`OnUf<{-a#1)@pN8v-mLG}NtoqfWjv);PwiTDRg6T4P7 zwAOw$_uF;8 z3fREwV~|cANY*-`XE6HP&^#FZTj;=G^xI7I&oEuEz@)!7o5<7pG*~?U&4hlXiJg@uc79|cKi`CYhY5Y8iT?Xd=sz~G z|K}$D`8N|iZ<^S%$wdEqCi+h>(et#4o@pj@T9yVIuY42v;U@H1CVE~lq5so_KF!2$ zADPhaHqm1<@ei$Ac6_q0>rMIkJ~8p5Ua6`IpoTOaT{Lt$4i>~w0*IhEy3k2mP8^@YOTU}bq}UBK_H zbS**p}!@8HRuz&prkPz4*0omp4r|&JtRv4 z@Ue$mSs3;XDK%ZzvoLC?zRuVS~%ZiJYHd>uuGI7 zm2EJ*>4zlyJFQw&Dh>G2LO9jg`Hkpd&`-f3ESL?yHl&Pa?_@Pcwm~~NnG9mPxt5Y! z=&Nt2^9r-sgQ?aG{U%SOnvrf9+!#lF0~{Xm`89VSgjtCR>0aq{uUP4Efgbmm<4h zm!I_y`}{%v4KvVGS-{~qL1fk#A#uT1(wQ=8%-9~uBK`4|gA>Xa95QIVsK95G&o`1z z3Wbt(?~m@svB9EElK5uEhilU%-gvqXN0(um4xBD(ag^i{F8H}AzB(_dd|Q1UNom?f zdA?P2o1|~bqUTk!xK@~zw-p|{MeymYGg=h+yURd7$3X8k(62Jkdkpk41HIQkcNpku z9iej`ovTt;lPH}4Kx?47@|r}6=vbmsm#s+@iLS+N zM2Y0d7wRf%5+$P3M_p5!M2To>42V+PMBhSIolyzbo9J86PZCA`u4obn>G_%{^7rB< zfe`&zgftR{gG>Ib7Pf1a6AId4u^ezMaN&~&yK%Z`)_Za9i4D?*8?A0$9$nTAI{UGmKU8k=52_DbCcbA^RB!XSatH!Js>B~+lz1O*kY6jUqQS? zZxYveI|j;e_Y#&0B?j;M)Z#)E{@(KJ!S_zi@gOt_u#<%H8wG+|?W z3E^}EO=yfSAe@e#iM}sEIBzcDbmUC*GG0PB9W@i(j9*ST9WfIz#wQU@N6SP9;};S> zitu*E&mo*{T_oBVKb>$oS|*wpKb3GgQYIQ0KZ$TUN+zlq&n29WkckS$zqlSa9UT+J zj2|JKj*N*S#@{ELj*1C84;3GZcmC*fxk z-p%;4gr7rrjPc(PPDjB+2jf2{oQ{BrcE%qioQ{5pHpU+$oQ`~nCdTh3oQ`^l2FC9o zoQ`;jYQ}FPoQ`&h3dV0FoQ`yfV#b4n(@`!_#P|(_(-AIVXM8!~baYGD7+*p-9oZ5Z z;|mC_^UbVN(^GG0PB9nBKmj9*ST9mx_g#wQU@N3lc);};T6N3cXY(JE2F_!rB7(~&As%=i()=_r*b zV*Gu==?ImuGyV?Y(+RgR{ubd^5w0=*8sRet@B0UjKjFoM_cFed@R@{nGyW{$C4|Qq z{|(`EL`rl3r+hQclV-sK0Tc^K{Nt_&g$#*sFXw3xc*!8G_ zgw#6yr%<4`S{@`Ytv@^(sp=aLqEvNave!DciR5085c1z+`AcsgaKV>)q)*@R_Zj+* z{$YB~ZvE9S!=s?!-6cXnUb45wI<_obpX_UzUXHq2<0Vyk^YjNHsp*k-!z1#rO@cA^a4>w2U!?ni{`5l6q?yslddkIj_gTK#(D6_UIGqXc&Ui!Th?M6{~cp!S<- zwLMz+n>usLd#JutcSfeVTMxIR{~kR${5+a-WYWYKMq?i$PLJ$(mJ-ABl>N8kqs700 zo}weqFUA6}-Hxmuza68xox&~NjZ%C)GF^N-zMv_lcRISL8k+B-u1rH31HJo*)n>Ve z8i+b#HP#PbtFab#>Cw?GAl2wr|4x$K1RbKyCL}Y|qE5t!a}ts#@Lp&cy$n?VM^*`F zDQB&tXEAVK>S|WcmoL^u`Y>GyVSy`;5N2F%`;LBlGc)StfpV6dE<+(P}8=3A=!63wjpHSBf>sb zO!g_oe}>{^thh%go-oipTdS~dX%}@KcCvrSPBx3|{JmLszdg{-!PT{Grvx6S3{3Vu zDeUD2$X?X|T(rc|L@|FB7N{c_EAnkj*dF}!E1W_$bC1d9ho#MFm3uB7pfd3JSEy{; zj?}Hi$7I?)AP#uE$!?368(B<~{bru=vG}u}d_^NwT0V^wwu6X;4EX@EhpHR8xtBOzA@}Re%nN{MMuCp4}@Z(BKiZ znY2=afaM!Mwl3zd-AYuMoJe=SA-LELJQ?~#Kz+|J8IIf5wsO6XIwur!SHc3L}`qd8VF6l z3_>($HIz@T9*!E#yKJIu+VnmjrM9UA;qj+H81TGY0nhpp`$ANH4YZM;q8zpCVhU9C zK^4e6R)FlgD36O!4vpIL)J0{<_@_~ols_ThSq}qZEu*E3Z2Jim#_yu9?_)8J(+if( zeL0xk8zvwvAOQL(03PSyqQ$5)zEPApFb?1Zq@rjF7CMx>Nv1={AP76-!yps?6OK;t zx3L4*N){qc`#t(aqj<9rw#3U3FR6`*J+kgFZGGaC$Dz){7~Y8ESUe6S>NqB(Xcok* zg*#~drhFVn2dhxBm19!d2+glLim!4SBgZjV1Wh~5lh7*|&+d}V-J7WurTyg%|$OZm~3 zs=hlgoLj2;TlV4m=#F=6=OvR`^2BaneLLPM0G8BF>_$^N`ch3nWi>p%39hqIuoQ?4 z@^c*E3=xIwlaDQ8)Nv-sj1w}qXUgm%nZ1xHB$*;1vpiF#n`C+@?j}d8ra~6&mT%P~ zdC~G%M9-6iU3x@6Iab^|r~G9d`0`?tlwVI38z0Bly7tIA?7nO)>WEQ^yNEv6D5K>&x~N1o9eb%n)g7?j z#*I7nQHd0Z&a_i$KhbPdqFLuCpwhvp<00C&^68})eT5H~VZ)xMM;4>Ev??vba--XT z7XaT6{2=f%fsc!ygpo&%ENTN)#&vv4Ml=*tBZu)-9>-VJL3}Mk>-k<7lV9JH87uoJ zR=O!x_O?`Y-Ql1p>E>A3n-MEr=~$tTkb03Ts0~Ly(WoKEF_f0|;H!$ej_y%{u^}cq zt%ZNX`GA&VT3h3P{m>Y1|3i%4pJ8-*o=!e&NX%*S_!ODqupqt+)p-Wd!G+vHUyj2# z3hdE2T~YSa&+gGrL~y@ACj{hId*m&F>k+Z9HH`epN+GRLB5}q0|E?O@(Qi-FVL&k^ zH3F?MHsAn?)hJpOlZWL_D8LNrMs_T=-nSbe*u^Mqnj$%RWIoNwUOh6?2G~{H(ts#+ z&^jd!wOFT~_<%KZi8+Xt5zFgDmJXMYuyspu!TMNu3Ro2KU>z>dBk$?a96bv4kr8@i z5g2G8GRqd_gN6B-|yX^mUYcI&Q7CuzIFQ%@+_oLwZ$!w6B@8Np#{K@Yd zJwHl$o}#%B+mA?NT&y~OqzrPfrK-0qva_XXf8>jnsvcyLaqC|TFS^5V5XD|jD*H2% zN>4heL>uE#Y-dtFdIwPfA1#BAPSPVw@}lMT$Xr`wXZ!|fQJY~Fd>Y3}y8}TYXTa@{ zkt-!xx)=`Fgdk}*4q2S;yEr;94DB*VYzYdIZWScF#(=+UYdST@fMNov)J*YJVTVsQ zA#4f(&9FEz~23MAg?kxduS#GH_B2A>u0R@wdf1Fy?;F zE0lN-OT8u0D&@xilIGiV@=__V|PFGBrY)b{7|FZE5$+tfb}|&|C}VjiYJ6 za8-4H4|~7bVdWP??PTTXD*eS+2&nM6yL`GOWpmi6#CDFO(&I!cq*4c!E~e6EDiu*_E0rcwX&aTM zQi)r;l1jUf4)IKkGCrk3c(e+0Or^pYr@|B$@lmxg&BbJ;Md7n}$-Ba(v|m9Rjr;Ib z--9pO=GbV%W23E)T4Kp1Ey`;R%Cjq!XRDQG7b}?x@+=L5POBRgiqAwLV_|rnh80Y) zFhnh<_6^fE#2T&f^I%-3CHWz}Dx5k$L@h@^z`@5F|HFR}{{T?K`650RR5f146_af1 zrxW5eP@7)+FrU`ZiQhrD7|P@L!o6ua2!+3edo$&|_`>AGnS`njxPAIghAy~N>Jl38 zR6y2K_d(8qap|^MUYYeXs7kGkg2QH{?A{GOrR)Cp?7rh~|2kcd95m`Gf)CI&Z|T>LGFw&wa z0778k-TCM{#J`XDdX(?o%GK~T@(p#%xTL)d=ch(`uyKS1Uln*4pv9C9@_BX)qr1y` zps0$z25KAFhwF@1iTH~&_K86Lx(a03tv~k~hkUSLeIO$!goK)Z0~^W=^oP^InO@A0 zy&BsPQyJNpwjYsRtT}Ko1RPrdA=DXvkOqVv<{+;Seuu!j(4CkT&Ijny!Y6?n)30!J zg->C6qm}86dGjI%6BpptRHvf@x2kX>s6*eVH^-4%9o+(n?0AlHjvndKajvjFzSDvu zhDE=iOFxa#5kN=$UyJ%;{ZRTW?v>&O-upSYG4vdjpT$ShKl@l;8MEmZU@1g`ik+bE zhz}F@jrb{3kKU@UiDGS!Hnxx#W^N^2obNDL5y$4{b(=NoUDqO&b~=7R8WWeHjDhWm zI(~uviN@(>l$e2*Q^wN0Z<>9BiO^)U92#>xks=c5KCZ}A5_#HOq*KFlG+1G?*o)1K zEhZyL#9}I!m-(U=kM`00-^;H8QX_Lq#<+bz{f@;M6B77s;&V^h#sg;6=69M0M9`$gi^@U z35y;?B73%uP8=h>4WreSf3_S(m+#K=~7F~C0{wOZ>8ph z4)~N)IDO??)?AfZqB9w_W{gE?hS(S$cim{&&x6vBuA{ww&AK7Z@>rJAtJS;+oXsm% z9a;jbGyeRa|8*^s^_X7;h8}boS2A(Su!}qx!&muMd{uSeYuToOA%hfl1r)I)Kc9Ax zxTA+?REM87J2p`X!GmKK2NECUFN8M-tV@@s!{gS&y_k1cQF#H3JVWat?A$OEw@`dT&=GOuOBIKZsVZKucj z@#%EPiHPM?uF{Ps@eQ8D<;c!hX@zy2@s$)D(fd|FlOD-cOE4xh_K~M46hnC>GztZu zBlqF%0zENnrB2YD29!5Y$52M+mi(SNOZS<+P#U7BlJ#7E=36Y!dZ^P%4># zqqlU+H^00OUv!g!60ol7<6Ltk!iFE@;)bSp9@~ckKchZM!||4s9S}uZ-bkfp^L*+? z?YOl1I#q_Hi5{9d)S-W6dbQIU^Z%~L<6w09L{v2R$-}J2m%aWk?=jtY(P70_V>+Wf zYV*3Snsxn^JV9y4K|y0(e=*^$xY^N)eMW2JF8F>c1=r=+R8Sc=dmy&KBCFw!(V5Zm z%`H2K2jr}lKgiM;JP_N_Ym4l;728~TEEVCM4P?eLr-11EfQspuWYq;!6@|rgK&L{5 z4PTC3G+1;efS%Iii-$3Lsni28qT@l)8;C+Y%B@AX{hN3^*wPv4IgeV7yugJd|BA9J z@`BWT+}7wugJ_NJHqbL6JlsJ=qL&|x91yKNMZpbf#x`p`4Poj54)158mIDXyL~@#= zKZu@L-jYb@gst$RcF4lnU)~;|{ZG{LhEe{tua^HAi6DXK7vM#RZoRcFN#nC2rd#!$ zc%kpa4CRj|A>3Mllf&pAQ?WUAlHPjqA2=7aj-Je_FzF)0^VPFZIz4wfXpgEL3ZcWa zT|k{tvW`XLI`RQ=IqaXodg*XtnM}o~Wjs?dYVCQOIH*O2H}51P{#_dJD`LTbL#OJ^ zj($8juzc_(DCEJW)O{41$k+^FpCmU$&ml&UtR@2QrI`J`z|U6vmneogpNzhX+eSxn zx_4_i>G>*jLSIyi#30+JM@KIZvVC+6iH^LIvC$3!IeYYJJ45HeysPNtlGf?BoC<)K z{qP=uc-b#L8sQLc`V+;3KV6s zCPF)LwdeRd8bSr^$vflQ@bDGgKaubRc~UV#%xDyhZHgh65WKBP6R9{a@u=ije_K4f zrnx_7)j3MRft2G&6r&ZXz=pule<(;2(pBh=#Yz^l*YE%a4{*WmlRZ5A8u?)K2m85) zanZvA0_&qDDIy_W6R8-^)jEswV36np-LevG_K7u-vRWa=pIRX6ZD=)K)9H8*5jr0< zv|f>C{jK9Yv}4_ZceTPr*56j)DHNpLuOZqHb!FXD8ZW! zF(aDe1$@TmF$Nvh*R%DKp96WS1C_y@hjMUt-O*0{IiFNdbF^D;n})0p!e8FvwzhH` zThT^0>UDD{rQ4vAh!r@F%;Kx(Na%<-*dGDxo8Oq z#!`WmGv?TO$POuLzYDNSPX}EW+alU3Bw=dnPi@($LZlzM`B4BReHfsByvZ%gbnz}@ zqrW5|(uF0y6Y~+4zD6_=34IY-1p6a4`mX6L#vLA68X-ys!}<}ZaC`-1NB_{!R>X3v zz*N5Iw5$g~)9eUJ%a6FI(O3jY3{IWf4KpH^Qm$oLDyfqNb-JKlFR5b$b%vnYm}p9*jWM_LtsbzM6`2mn$Pb+lLT#adu)?L zs|EUNiOv`3vl1-m^(!3^hpr(H40&M414AAd^1zS>hCDFjfgukJd0@x` zU*UnAjK4;Qzggr9tq9?7L)ypNOI#tJ+kQ!z9e-&uToVY^dxM%bcEh3hTOT<$mZ`RH zhQQm40gF$1qvD8j~;?e8T zt_j%jXB-1)Mqa%$9(;hV-_4j^dbvGN=dss%{r12rZ?L8=uo}Ov({j!jb_M;-clyC@ z_4Z`45NEB97m`UE;8VMjN&36;C;uUtYykW&U>o2QFDH{7fG+`d1Lotn)(6-EXu}!x zO~4|+gMbx)BXII+04$&r7~n;K9e^tUy8*+1eSo(B+ANy(W56Q7#{eq;e+Ae8n2Xb9 z8{o@;9e}@nHJRK8_E!m4H=%VZi?lxDjwW;8wsl0DA!E z?@K280iOaaz+Xxj`|ru*RKS-37XzM)n{{gde+~E$;10lT#0T6DxCA$R>5l+D4LA<) zWO_gWxE8Pu@K1Q~)CM>ek6Stb7Xx+!t^w==YzDO9CwNZ)76E<)SOIu89-lP;UIEw! zxD2oZ@F~D!Tc+vsX2OJ034LA$15AYP+ zavz1Cg8l$-GT-vd?x zZowO5VL%(6``rt;4sbJIE*@>}0}KEj1w0Bk3O|Di;%(QdfR6$$27C>04PX**Bj9C+ zF>Zh_0rmin#jDf(fWHSUz;CJc{2lcH=YNMSnno zuACbeXgOdN7Hu3pxS6XJZ4)uAono7HO2J&~ z*H-5>X){j0;=)VDokMa|cPT#ecO;W;BFsF+c6)B=$Pu~MqXogg3FLdhzczzEH^qMl z^cTRN3;9(2VU9c!ApP6$`QSxqpVIH*>dfB{{>R|Y0!-D=0$&vNZoD@b3a2cg557%hUXaz;6Qo z>qh=HY5q3wL*P$0^4FyK`@wGmAEA}jKReAo2L4Upo7sOR@?kCb1;+Xd)Ag?e-+3JU zOToYTIQ*NyzYKi*FfMIhuIM0*??d3<0RBrE{M~GT9kgxWkA5kcJZR)Qnuq1SmA0`L zGXD-4Gat|&OWgtfGe#Y`9jt(Cpuat^XsZA|rXIM$r`(7!l? zF9w=?Fb@0(_^UGb-%Hgm1OEW{zs%r2mEwEAug4mg(Z}5R%(tV?dhj0u|1M*F^1*r* zVIORQ%t)+%oP?AQu1@p2!2c(73^vZxMjZSE_^sJ(Gz%Rhb28S>1!yB99?6b5X_+F( z+zJ_Iww|iAOeJKtL8d-i#+{Z~0~rg}?B|>z;D7@Z#TB{UC{>B-~Sc-W0G$=|FIWX3H|37^&9fnmEhNdKhMa|6$ysgUkd&M z;1?PBE7SJf1pZUtpKjz!KXU)Uf9yEzZv+2{@%QAAnzGwEvcL|CWNEkG<3aBR^Lpc&dLB_@&^FH}Y4c>puj31^8zE z-v<5y@Xh?UAN+YH_3dc$82HzK--R5R6@%MyVFuY~$J%=Y`@6L$r(|-&DId^N$g8p6 zGtGbCmw<29hbHjLj>B&Ue-`+s8QZT+`zQwfjN|Zo!Jm2@zJ`6{MDWdGzz+Toz`xtr zer{{J|KNWPeoF>lBo*>sHTW*LFVEp7@Gr+ccS%NlF$t)CJNRMnGjd6; z2omDQz~2G>hK%}6Df@cCKOg&Jv-%qLy&>=it8a%+JNP}|-)zi5$ce+koQAj$WssRf zdv2o*hI#G*zvMXl_24f6-)tT{4!#rosYd;wbPVhQe>M2`8u__DO!?p-_=mu+%;1X! zlzccG32-dV0FPwwA4t_72mZt0k2LyVSROmTjyh%F-_e^){=itD){S*(8|g2{eE=DH zi7_>gh8<1i@)q!S<6QBWQAh40DH}F{KL_WF9U1&>DSj9D?}J}zo)qJTT;eArJh|^?>^S(bWHkMzHmDAi|?~i!A@W4|AT8Y-#o>06+uq@zvX90 z9Jgcm;(JyossF!?&f#<^{wH511BBCaRl0DiQd~Ia(uG@heDzB{j`)04O8cak#`na* zp`RQWFIi2C-y*2WKh;t(-)jd8x5)V7`&%eg;O`dFrRddsLpp7DpI~da?ZTI8{~t-w z9}u~VUrM}>{vtfCq{NjSeG;#f{LdvWyC*9BfB5cLH+Z8{?1DZ^!bK9+NVrPE+a@~?W1HimnK^-e%t0dPjK8)fbtX3_ewfHg9hy)d~!5vDo^H0`74+{T5Ff_FQ>g$ z4*Fp2(*0c0ADti+%o0Gm0Wb&ue{j=ng3$ETFfQCI>DtA^85iH0_9PM;$>&MB%8x&U z6zP9e>R-*ZH0>u+k1b2juO)p{7JUg4We&1+k+etYzn0fsZlQq7li{eR=euoT%9|*Q~mZaxb2m;@~mAt|FH39N;r!`hB zg(R2>dXDxDEjxeCWqLts9a6QbLFe}Z6hXopOz1Z;eWcb;fr`t{-?%SrBLA=n{Z}UR z?I!fSOdqLzP%0Ya=O`#9Oyob6^0TGI7Y<__N9aVGT3Oz5+jK2lpbStwTPIQ>Tg zr()cn=7({3W+L0IHqmo~l>d)QgrKsM{syuQ^F_Z+Dv;nd6FqGv^q-p0J51=iOz7Pv z^cmQI*kPyrwoE(UWciWWCuM@(BH8rrTR!rhRxJoB{|p-@{5JJUL09{#(=y@4*RoBq07MFSoWq;NF_X`s}C%}P&&EHp%S1As?GH;(R8~G;7kJS8f|6D5R z=bGr5VnUx`LNAy4Zauds^oD4qXpO{gdQ8;`eMo z|D}nZ-dit4x;Ct zqN($a6xXhndN#>;R6Q}&J^xZcSS;zInJy6nINO9iUg|krc2uSV zZMvjimz94iO!T;<{I6wyWi|Xcd12?FZwq6j`?T97U6*uz=Mf_Jn&@vgp)bjW{#>jE zc0*@Te9lC^Q?}b9+x@z%_7>=rPqNq9_oV!1a=`DE@}Efh0qOr=O8Q7_Xa|eu(@p5# zV){sJx3ovqooXUK$ArE}>hVc?)V_%R$2p3h&2paddlj(tW=a3PjN9?j{`*YyKO*J7 zH%SPpeEv&G|5D~#wQuQ?^mS5R<>5CZefk`sN9B!Am@bVlfIP&1KKAX^w+SM|_&P(* zivk&Mc1gdG=@K!3>7dg-Dtmu2*F=7q)ZZ%CuU4t6p7orrt(k{}Z@7XcdTx<=R_Q`` ziLA5HME(gW|E|mfa(U36H<8~XB2Lnc&y=NtCC&U7{{pjv;6 zCH(JXztu5a3K_sEDgR@+j^8MGw@doIEImIl(erZ?`m-kVy;8qBYrXi3 zr2kFsAMTR&d*zDDXlD{G&i)w_KD32rUa=yN;y7er21Fz8xqB!t4jMt7Jf&gH&v zy{o~w$m^cOczA7t*XOSZ2uhuAIq9kQ-l#N&1I}QbbCuV9i53pJ+$+5v(Fp%cDWs); zvgC9J8vS9d#^*OmXzs>f(CZI7>jJgTI`1lPofhzToj$)W>~q!mZp3e#{9aek>4u`^ zP|sGQd1tK~7Sy^mU&y%@ifgHWpF3%8SI~p%9`72hAsDC+guNPmiM1M3E#!9joq^>y zc->)Vjn7->2|`oY&5pwa`)Ntejag&*9YOgs%3kEeovnqf{Pf40%f$!{LCRDeQCAAI(z|@T{Hf z4bN|Mg}p&Pe#WJF<_3KJ@a!OdKUNy_f~?I!&u2Dze1S6WDxce{d1iY9^$WdWsw;+! z^eqSGto6ceK6VfJP3W2#4!hhd(vmk&1I}7%!RZ!FC_CnH-9@MhqZYWqG ztkFU~fAQ>jb4p5`lW=qLQlXGqtfxLY*O2RIl(cyPmuDeH0RE*2!!WG$u626IAx^Ky z6?SP={yNB1de?*-gXj?T1RbgfgfPbN0m@u|QJ}7|-b=PDgrQ!4W#GC%u+9U+q=q^5 zu3FS54_#a4NOzH)5rS#KK$yc$bI!Te847!RekW{|hLPJ=lS1VNHg`2bC9v8VS`la@ zPF*166^ikbJ_IUhT_x;FjU_kd@nX&d3?mZq)i>06ouLMo+pAjel)FM9bdUV$5#!6Q zB|nil#<9sz=%N4+?)5ArjXX3SFT&Hk#)aVZ^V}FXK->YR=#*CCt@ZiKf-a!7T4^1o zQ3+-cg#rc(!xvi780K+OLt+d})uM+7q0HD_Vch^<)nL#x*YZFxoM9IkpvKQ zO&%*6yRa)rF%H~vhP5fvCQ8$?!_dp!9nhM{97sEBG>6}#Vk*mgT2xdh zrE?1`ad|xOZ9ooRDu0nH4Ec+-5mPqSQ0MY{k>mpPX~*;26Z}*c6)y%>>D zNGR}8{t)iuV32V}2}}hjs}NHk%}d8Fr+MV0NTrD+CIn{n?4WB^%K2os$S$FuXA0rM>7?-v zdh78!UxTC50fcDf&Z{hh-zWR!(lXn)w74lrIK?lDDeO|V&3oDqI+gRTX>0^P{r50onFYE*-x{{g$ zl>G6K2yJOqZm*Spp@vB#v%8t0YN=0qf%^z6v4=&q?(>4cJoI}pkUPm!M%^45eE ziwL0EqLL9igeQfZi%2K6^#Q+Jjhr(4V62!>SjosMgZhMZiCiZqBT~H#Jxb!V%4*0Q zYehn;;q@iMVBV`{c$Ipb%EqbLsZ9v2tq;4F1BQbFu23aEcI*>s{f!f_dvEXtvA9i0 zk(M|5>OA9p9&G~lv=nhHxWW}$p-u3t^+TzE;h^B)uO85LHUn{j7xdP-sDdmt)P+eS z_OcVmi`oQU>?Z^RynCJCU4gNum3M^)brmMfnprYueArbh>dS)_*H>lIK@CD38|SL` zxnU3%L;9M)ZHsm=i?s>vKz%)qL+NAVf4M~OA>mdbo&k%iVpt|DmUIQw{Vj#lV;f`r zHd$Xmd0SYCt{!y?;d{x~Q+l%MFCybyD@!`%Mbo zFNKx;N>0HB@af$tg{$|c6eK=fWIxF$`-w)^E%?xwsQT45qT;cqgna@{y>F)KtNus8 zr}`yQPQ4GNpn89d?58@}_3r_Vd_wl|WzU2ZpT;XYe&~LUvA*3dq!p~lsvx_CdynFJ z0KiyZJ;zXRro7)J#Z&bZ{*$cw>iL&~BbA_pS>|X@$ok6vTD26E@OgoQ?>dkR int do + # Initialize raylib + init_window(800, 600, "Fishsoup - Basic 3D Platformer") + defer close_window() + set_target_fps(60) + + # Initialize ODE + ode_init() + defer ode_close() + + # Create physics world + 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 + ode_world_set_gravity(world, 0.0, -9.81, 0.0) + + # Create contact joint group + let contactgroup = ode_joint_group_create(0) + defer ode_joint_group_destroy(contactgroup) + + # Create player body + let player_body = ode_body_create(world) + defer ode_body_destroy(player_body) + + # Set player mass (cube 1x1x1) + ode_body_set_box_mass(player_body, 1.0, 1.0, 1.0, 1.0) + + # Set initial position + ode_body_set_position(player_body, 0.0, 1.0, 0.0) + + # Create geometry for player + let player_geom = ode_create_box_geom(space, 1.0, 1.0, 1.0) + defer ode_geom_destroy(player_geom) + ode_geom_set_body(player_geom, player_body) + + # Create ground plane (at y = -0.5) + # Plane equation: ax + by + cz + d = 0 + # For y = -0.5: 0*x + 1*y + 0*z + 0.5 = 0 => y = -0.5 + let ground_geom = ode_create_plane_geom(space, 0.0, 1.0, 0.0, 0.5) + defer ode_geom_destroy(ground_geom) + + # Initialize player velocity to allow gravity to work + ode_body_set_linear_vel(player_body, 0.0, 0.0, 0.0) + + # Player variables + let mut player_x = 0.0 + let mut player_y = 0.0 + let mut player_z = 0.0 + let mut player_angle = 0.0 # Yaw + let mut camera_distance = 5.0 + let mut camera_height = 2.0 + let mut mouse_x = 0.0 + let mut mouse_y = 0.0 + let mut last_mouse_x = 0.0 + let mut last_mouse_y = 0.0 + let mut vel_x = 0.0 + let mut vel_y = 0.0 + let mut vel_z = 0.0 + + # Main game loop + while window_should_close() == false do + # Get mouse position for rotation + mouse_x = get_mouse_x() + mouse_y = get_mouse_y() + + # Calculate mouse delta + let mouse_delta_x = mouse_x - last_mouse_x + let mouse_delta_y = mouse_y - last_mouse_y + last_mouse_x = mouse_x + last_mouse_y = mouse_y + + # Update rotation based on mouse movement + let mouse_sensitivity = 0.005 + player_angle = player_angle - mouse_delta_x * mouse_sensitivity + + # Collision detection BEFORE step + ode_space_collide(world, space, contactgroup) + + # Step physics - this applies gravity + ode_world_step(world, 1.0 / 60.0) + ode_joint_group_empty(contactgroup) + + # NOW get the velocity after gravity has been applied + ode_body_get_linear_vel(player_body, &vel_x, &vel_y, &vel_z) + + # Handle input for movement + let move_speed = 5.0 + + # Check if any movement keys are pressed + let w_pressed = is_key_down(87) + let s_pressed = is_key_down(83) + let a_pressed = is_key_down(65) + let d_pressed = is_key_down(68) + + # Only update HORIZONTAL velocity if a key is pressed + # Keep vertical velocity (from gravity) + if w_pressed do + vel_x = sin(player_angle) * move_speed + vel_z = cos(player_angle) * move_speed + ode_body_set_linear_vel(player_body, vel_x, vel_y, vel_z) + end + + if s_pressed do + vel_x = -sin(player_angle) * move_speed + vel_z = -cos(player_angle) * move_speed + ode_body_set_linear_vel(player_body, vel_x, vel_y, vel_z) + end + + if a_pressed do + vel_x = sin(player_angle + 3.14159 / 2.0) * move_speed + vel_z = cos(player_angle + 3.14159 / 2.0) * move_speed + ode_body_set_linear_vel(player_body, vel_x, vel_y, vel_z) + end + + if d_pressed do + vel_x = sin(player_angle - 3.14159 / 2.0) * move_speed + vel_z = cos(player_angle - 3.14159 / 2.0) * move_speed + ode_body_set_linear_vel(player_body, vel_x, vel_y, vel_z) + end + + # Get player position + ode_body_get_position(player_body, &player_x, &player_y, &player_z) + + # Camera position (behind player) + let camera_x = player_x - sin(player_angle) * camera_distance + let camera_y = player_y + camera_height + let camera_z = player_z - cos(player_angle) * camera_distance + + # Drawing + begin_drawing() + clear_background(135, 206, 235, 255) # Sky blue + + begin_mode3d(camera_x, camera_y, camera_z, player_x, player_y, player_z, 0.0, 1.0, 0.0, 45.0, 0) + + # Draw ground + draw_cube(0.0, -0.5, 0.0, 20.0, 1.0, 20.0, 34, 139, 34, 255) # Green ground + + # Draw player + draw_cube(player_x, player_y, player_z, 1.0, 1.0, 1.0, 0, 255, 0, 255) # Green player + + end_mode3d() + end_drawing() + end + + 0 +end \ No newline at end of file diff --git a/fps_game b/fps_game new file mode 100755 index 0000000000000000000000000000000000000000..59080a9b48efc65e2779ee206bea97089e0b0c69 GIT binary patch literal 49256 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 Yu2;(zqmbP~$$9q25`H2_AqTbo2WO>Yr2qf` literal 0 HcmV?d00001 diff --git a/libsuicmez/libsuicmez.c b/libsuicmez/libsuicmez.c index 46fd414..532b1b0 100644 --- a/libsuicmez/libsuicmez.c +++ b/libsuicmez/libsuicmez.c @@ -1,385 +1,417 @@ -#include "raylib.h" #include "libsuicmez.h" -#include +#include "raylib.h" +#include "rlgl.h" +#include "suicmez_gc.h" #include +#include #include -// Simple garbage collection allocator -// This is a basic implementation that tracks allocations -// For production, consider using a more robust GC library - #define MAX_TRACKED_ALLOCATIONS 10000 typedef struct { - void* ptr; - size_t size; - int in_use; + void *ptr; + size_t size; + int in_use; } AllocationInfo; static AllocationInfo tracked_allocations[MAX_TRACKED_ALLOCATIONS]; static int allocation_count = 0; -static const char* last_error = NULL; +static const char *last_error = NULL; // Simple linear search to find allocation -static int find_allocation(void* ptr) { - for (int i = 0; i < allocation_count; i++) { - if (tracked_allocations[i].ptr == ptr && tracked_allocations[i].in_use) { - return i; - } +static int find_allocation(void *ptr) { + for (int i = 0; i < allocation_count; i++) { + if (tracked_allocations[i].ptr == ptr && tracked_allocations[i].in_use) { + return i; } - return -1; + } + return -1; } // GC-aware allocator -void* gc_suic_alloc(size_t size) { - if (size == 0) { - return NULL; - } - - void* ptr = malloc(size); - if (!ptr) { - last_error = "Memory allocation failed"; - return NULL; - } - - // Track this allocation - if (allocation_count < MAX_TRACKED_ALLOCATIONS) { - tracked_allocations[allocation_count].ptr = ptr; - tracked_allocations[allocation_count].size = size; - tracked_allocations[allocation_count].in_use = 1; - allocation_count++; - } else { - last_error = "Too many tracked allocations"; - free(ptr); - return NULL; - } - - return ptr; +void *gc_suic_alloc(size_t size) { + if (size == 0) { + return NULL; + } + + // Use the real GC allocator (for now without type info) + void *ptr = gc_alloc(NULL, size); + if (!ptr) { + last_error = "GC allocation failed"; + return NULL; + } + + return ptr; } // Free memory (called by gc_suic_free) -void suic_gc_free(void* ptr) { - if (!ptr) return; - - int idx = find_allocation(ptr); - if (idx >= 0) { - tracked_allocations[idx].in_use = 0; - free(ptr); - } +// With GC, we don't actually free - just mark as no longer needed +void suic_gc_free(void *ptr) { + // GC will handle freeing when appropriate + // For now, do nothing + (void)ptr; } // Error handling const char *suic_last_error(void) { - return last_error ? last_error : "No error"; + return last_error ? last_error : "No error"; } -void suic_clear_error(void) { - last_error = NULL; -} +void suic_clear_error(void) { last_error = NULL; } // Logging static suic_log_level current_log_level = SUIC_LOG_ALL; -void suic_set_log_level(suic_log_level level) { - current_log_level = level; -} +void suic_set_log_level(suic_log_level level) { current_log_level = level; } // Window management bool suic_init_window(int width, int height, const char *title) { - InitWindow(width, height, title); - return !WindowShouldClose(); + InitWindow(width, height, title); + return !WindowShouldClose(); } -void suic_close_window(void) { - CloseWindow(); -} +void suic_close_window(void) { CloseWindow(); } -bool suic_window_should_close(void) { - return WindowShouldClose(); -} +bool suic_window_should_close(void) { return WindowShouldClose(); } -void suic_set_target_fps(int fps) { - SetTargetFPS(fps); -} +void suic_set_target_fps(int fps) { SetTargetFPS(fps); } + +void suic_enable_msaa_4x(void) { SetConfigFlags(FLAG_MSAA_4X_HINT); } // Drawing -void suic_begin_drawing(void) { - BeginDrawing(); -} +void suic_begin_drawing(void) { BeginDrawing(); } -void suic_end_drawing(void) { - EndDrawing(); -} +void suic_end_drawing(void) { EndDrawing(); } -void suic_clear_background(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { - ClearBackground((Color){r, g, b, a}); +void suic_clear_background(unsigned char r, unsigned char g, unsigned char b, + unsigned char a) { + ClearBackground((Color){r, g, b, a}); } // 3D mode Camera3D suic_to_rl_camera3d(suic_camera3d cam) { - return (Camera3D){ - .position = suic_to_rl_vec3(cam.position), - .target = suic_to_rl_vec3(cam.target), - .up = suic_to_rl_vec3(cam.up), - .fovy = cam.fovy, - .projection = cam.projection - }; + return (Camera3D){.position = suic_to_rl_vec3(cam.position), + .target = suic_to_rl_vec3(cam.target), + .up = suic_to_rl_vec3(cam.up), + .fovy = cam.fovy, + .projection = cam.projection}; } -void suic_begin_mode3d(float pos_x, float pos_y, float pos_z, float target_x, float target_y, float target_z, float up_x, float up_y, float up_z, float fovy, int projection) { - Camera3D camera = { - .position = (Vector3){pos_x, pos_y, pos_z}, - .target = (Vector3){target_x, target_y, target_z}, - .up = (Vector3){up_x, up_y, up_z}, - .fovy = fovy, - .projection = projection - }; - BeginMode3D(camera); +void suic_begin_mode3d(float pos_x, float pos_y, float pos_z, float target_x, + float target_y, float target_z, float up_x, float up_y, + float up_z, float fovy, int projection) { + Camera3D camera = {.position = (Vector3){pos_x, pos_y, pos_z}, + .target = (Vector3){target_x, target_y, target_z}, + .up = (Vector3){up_x, up_y, up_z}, + .fovy = fovy, + .projection = projection}; + BeginMode3D(camera); } -void suic_end_mode3d(void) { - EndMode3D(); -} +void suic_end_mode3d(void) { EndMode3D(); } // 3D Drawing -void suic_draw_cube(float x, float y, float z, float width, float height, float length, unsigned char r, unsigned char g, unsigned char b, unsigned char a) { - DrawCube((Vector3){x, y, z}, width, height, length, (Color){r, g, b, a}); +void suic_draw_cube(float x, float y, float z, float width, float height, + float length, unsigned char r, unsigned char g, + unsigned char b, unsigned char a) { + DrawCube((Vector3){x, y, z}, width, height, length, (Color){r, g, b, a}); } -void suic_draw_cube_wires(float x, float y, float z, float width, float height, float length, unsigned char r, unsigned char g, unsigned char b, unsigned char a) { - DrawCubeWires((Vector3){x, y, z}, width, height, length, (Color){r, g, b, a}); +void suic_draw_cube_wires(float x, float y, float z, float width, float height, + float length, unsigned char r, unsigned char g, + unsigned char b, unsigned char a) { + DrawCubeWires((Vector3){x, y, z}, width, height, length, (Color){r, g, b, a}); } -// Input -bool suic_is_key_down(int key) { - return IsKeyDown(key); -} +// Input - Keyboard +bool suic_is_key_down(int key) { return IsKeyDown(key); } -bool suic_is_mouse_button_down(int b) { - return IsMouseButtonDown(b); -} +bool suic_is_key_pressed(int key) { return IsKeyPressed(key); } + +bool suic_is_key_released(int key) { return IsKeyReleased(key); } + +// Input - Mouse +bool suic_is_mouse_button_down(int b) { return IsMouseButtonDown(b); } + +bool suic_is_mouse_button_pressed(int b) { return IsMouseButtonPressed(b); } + +bool suic_is_mouse_button_released(int b) { return IsMouseButtonReleased(b); } suic_vec2 suic_get_mouse_position(void) { - Vector2 pos = GetMousePosition(); - return (suic_vec2){pos.x, pos.y}; + Vector2 pos = GetMousePosition(); + return (suic_vec2){pos.x, pos.y}; +} + +suic_vec2 suic_get_mouse_delta(void) { + Vector2 delta = GetMouseDelta(); + return (suic_vec2){delta.x, delta.y}; +} + +float suic_get_mouse_x(void) { return GetMousePosition().x; } + +float suic_get_mouse_y(void) { return GetMousePosition().y; } + +float suic_get_mouse_delta_x(void) { return GetMouseDelta().x; } + +float suic_get_mouse_delta_y(void) { return GetMouseDelta().y; } + +// Input - Helper functions for gamedev +int suic_is_movement_input(void) { + // Returns bitmask: 1=W (forward), 2=A (left), 4=S (backward), 8=D (right) + int result = 0; + if (IsKeyDown(KEY_W)) + result |= 1; + if (IsKeyDown(KEY_A)) + result |= 2; + if (IsKeyDown(KEY_S)) + result |= 4; + if (IsKeyDown(KEY_D)) + result |= 8; + return result; +} + +int suic_is_sprint_held(void) { return IsKeyDown(KEY_LEFT_SHIFT) ? 1 : 0; } + +int suic_is_jump_pressed(void) { return IsKeyPressed(KEY_SPACE) ? 1 : 0; } + +// ============================================================================ +// CURSOR MANAGEMENT +// ============================================================================ + +void suic_disable_cursor(void) { DisableCursor(); } + +void suic_enable_cursor(void) { EnableCursor(); } + +bool suic_is_cursor_hidden(void) { return IsCursorHidden(); } + +// ============================================================================ +// MATRIX OPERATIONS FOR 3D TRANSFORMATIONS +// ============================================================================ + +void suic_rl_push_matrix(void) { rlPushMatrix(); } + +void suic_rl_pop_matrix(void) { rlPopMatrix(); } + +void suic_rl_translate_f(float x, float y, float z) { rlTranslatef(x, y, z); } + +void suic_rl_rotate_f(float angle, float x, float y, float z) { + rlRotatef(angle, x, y, z); } // Image and Texture suic_image_handle suic_image_load(const char *path) { - Image img = LoadImage(path); - return (suic_image_handle){img, (img.data != NULL) ? true : false}; + Image img = LoadImage(path); + return (suic_image_handle){img, (img.data != NULL) ? true : false}; } void suic_image_free(suic_image_handle *img) { - if (img && img->valid) { - UnloadImage(img->value); - img->valid = false; - } + if (img && img->valid) { + UnloadImage(img->value); + img->valid = false; + } } suic_texture_handle suic_texture_load(const char *path) { - Texture2D tex = LoadTexture(path); - return (suic_texture_handle){tex, (tex.id != 0) ? true : false}; + Texture2D tex = LoadTexture(path); + return (suic_texture_handle){tex, (tex.id != 0) ? true : false}; } suic_texture_handle suic_texture_from_image(suic_image_handle img) { - if (!img.valid) { - return (suic_texture_handle){0, false}; - } - Texture2D tex = LoadTextureFromImage(img.value); - return (suic_texture_handle){tex, (tex.id != 0) ? true : false}; + if (!img.valid) { + return (suic_texture_handle){0, false}; + } + Texture2D tex = LoadTextureFromImage(img.value); + return (suic_texture_handle){tex, (tex.id != 0) ? true : false}; } void suic_texture_free(suic_texture_handle *tex) { - if (tex && tex->valid) { - UnloadTexture(tex->value); - tex->valid = false; - } + if (tex && tex->valid) { + UnloadTexture(tex->value); + tex->valid = false; + } } void suic_draw_texture(suic_texture_handle tex, int x, int y, unsigned char r, unsigned char g, unsigned char b, unsigned char a) { - if (tex.valid) { - DrawTexture(tex.value, x, y, (Color){r, g, b, a}); - } + if (tex.valid) { + DrawTexture(tex.value, x, y, (Color){r, g, b, a}); + } } // Audio bool suic_audio_init(void) { - InitAudioDevice(); - return IsAudioDeviceReady(); + InitAudioDevice(); + return IsAudioDeviceReady(); } -void suic_audio_close(void) { - CloseAudioDevice(); -} +void suic_audio_close(void) { CloseAudioDevice(); } suic_sound_handle suic_sound_load(const char *path) { - Sound snd = LoadSound(path); - return (suic_sound_handle){snd, (snd.frameCount > 0) ? true : false}; + Sound snd = LoadSound(path); + return (suic_sound_handle){snd, (snd.frameCount > 0) ? true : false}; } void suic_sound_play(suic_sound_handle snd) { - if (snd.valid) { - PlaySound(snd.value); - } + if (snd.valid) { + PlaySound(snd.value); + } } void suic_sound_set_volume(suic_sound_handle snd, float volume) { - if (snd.valid) { - SetSoundVolume(snd.value, volume); - } + if (snd.valid) { + SetSoundVolume(snd.value, volume); + } } void suic_sound_free(suic_sound_handle *snd) { - if (snd && snd->valid) { - UnloadSound(snd->value); - snd->valid = false; - } + if (snd && snd->valid) { + UnloadSound(snd->value); + snd->valid = false; + } } // Raycasting suic_ray suic_get_mouse_ray(suic_vec2 mouse, suic_camera3d cam) { - Ray r = GetMouseRay( - (Vector2){mouse.x, mouse.y}, - suic_to_rl_camera3d(cam) - ); - return (suic_ray){ - .origin = (suic_vec3){r.position.x, r.position.y, r.position.z}, - .direction = (suic_vec3){r.direction.x, r.direction.y, r.direction.z} - }; + Ray r = GetMouseRay((Vector2){mouse.x, mouse.y}, suic_to_rl_camera3d(cam)); + return (suic_ray){ + .origin = (suic_vec3){r.position.x, r.position.y, r.position.z}, + .direction = (suic_vec3){r.direction.x, r.direction.y, r.direction.z}}; } suic_rayhit suic_raycast_aabb(suic_ray ray, suic_aabb box) { - Ray r = (Ray){ - .position = (Vector3){ray.origin.x, ray.origin.y, ray.origin.z}, - .direction = (Vector3){ray.direction.x, ray.direction.y, ray.direction.z} - }; - - BoundingBox bbox = (BoundingBox){ - .min = (Vector3){box.min.x, box.min.y, box.min.z}, - .max = (Vector3){box.max.x, box.max.y, box.max.z} - }; - - RayCollision collision = GetRayCollisionBox(r, bbox); - - return (suic_rayhit){ - .hit = collision.hit, - .distance = collision.distance, - .point = (suic_vec3){collision.point.x, collision.point.y, collision.point.z}, - .normal = (suic_vec3){collision.normal.x, collision.normal.y, collision.normal.z} - }; + Ray r = (Ray){.position = (Vector3){ray.origin.x, ray.origin.y, ray.origin.z}, + .direction = (Vector3){ray.direction.x, ray.direction.y, + ray.direction.z}}; + + BoundingBox bbox = + (BoundingBox){.min = (Vector3){box.min.x, box.min.y, box.min.z}, + .max = (Vector3){box.max.x, box.max.y, box.max.z}}; + + RayCollision collision = GetRayCollisionBox(r, bbox); + + return (suic_rayhit){ + .hit = collision.hit, + .distance = collision.distance, + .point = + (suic_vec3){collision.point.x, collision.point.y, collision.point.z}, + .normal = (suic_vec3){collision.normal.x, collision.normal.y, + collision.normal.z}}; } // ODE Physics Engine Implementation static int ode_initialized = 0; void suic_ode_init(void) { - if (!ode_initialized) { - dInitODE(); - ode_initialized = 1; - } + if (!ode_initialized) { + dInitODE(); + ode_initialized = 1; + } } void suic_ode_close(void) { - if (ode_initialized) { - dCloseODE(); - ode_initialized = 0; - } + if (ode_initialized) { + dCloseODE(); + ode_initialized = 0; + } } -suic_ode_world_id suic_ode_world_create(void) { - return dWorldCreate(); -} +suic_ode_world_id suic_ode_world_create(void) { return dWorldCreate(); } void suic_ode_world_destroy(suic_ode_world_id world) { - if (world) { - dWorldDestroy(world); - } + if (world) { + dWorldDestroy(world); + } } -void suic_ode_world_set_gravity(suic_ode_world_id world, dReal x, dReal y, dReal z) { - if (world) { - dWorldSetGravity(world, x, y, z); - } +void suic_ode_world_set_gravity(suic_ode_world_id world, dReal x, dReal y, + dReal z) { + if (world) { + dWorldSetGravity(world, x, y, z); + } } void suic_ode_world_step(suic_ode_world_id world, dReal stepsize) { - if (world) { - dWorldStep(world, stepsize); - } + if (world) { + dWorldStep(world, stepsize); + } } // Body management suic_ode_body_id suic_ode_body_create(suic_ode_world_id world) { - return dBodyCreate(world); + return dBodyCreate(world); } void suic_ode_body_destroy(suic_ode_body_id body) { - if (body) { - dBodyDestroy(body); - } + if (body) { + dBodyDestroy(body); + } } -void suic_ode_body_set_position(suic_ode_body_id body, dReal x, dReal y, dReal z) { - if (body) { - dBodySetPosition(body, x, y, z); - } +void suic_ode_body_set_position(suic_ode_body_id body, dReal x, dReal y, + dReal z) { + if (body) { + dBodySetPosition(body, x, y, z); + } } -void suic_ode_body_set_linear_vel(suic_ode_body_id body, dReal x, dReal y, dReal z) { - if (body) { - dBodySetLinearVel(body, x, y, z); - } +void suic_ode_body_set_linear_vel(suic_ode_body_id body, dReal x, dReal y, + dReal z) { + if (body) { + dBodySetLinearVel(body, x, y, z); + } } -void suic_ode_body_get_position(suic_ode_body_id body, float *x, float *y, float *z) { - if (body) { - const dReal *pos = dBodyGetPosition(body); - *x = (float)pos[0]; - *y = (float)pos[1]; - *z = (float)pos[2]; - } +void suic_ode_body_get_position(suic_ode_body_id body, float *x, float *y, + float *z) { + if (body) { + const dReal *pos = dBodyGetPosition(body); + *x = (float)pos[0]; + *y = (float)pos[1]; + *z = (float)pos[2]; + } } // Mass and geometry -void suic_ode_body_set_box_mass(suic_ode_body_id body, dReal density, dReal lx, dReal ly, dReal lz) { - if (body) { - dMass mass; - dMassSetBox(&mass, density, lx, ly, lz); - dBodySetMass(body, &mass); - } +void suic_ode_body_set_box_mass(suic_ode_body_id body, dReal density, dReal lx, + dReal ly, dReal lz) { + if (body) { + dMass mass; + dMassSetBox(&mass, density, lx, ly, lz); + dBodySetMass(body, &mass); + } } -suic_ode_geom_id suic_ode_create_box_geom(suic_ode_space_id space, dReal lx, dReal ly, dReal lz) { - return dCreateBox(space, lx, ly, lz); +suic_ode_geom_id suic_ode_create_box_geom(suic_ode_space_id space, dReal lx, + dReal ly, dReal lz) { + return dCreateBox(space, lx, ly, lz); } -suic_ode_geom_id suic_ode_create_plane_geom(suic_ode_space_id space, dReal a, dReal b, dReal c, dReal d) { - return dCreatePlane(space, a, b, c, d); +suic_ode_geom_id suic_ode_create_plane_geom(suic_ode_space_id space, dReal a, + dReal b, dReal c, dReal d) { + return dCreatePlane(space, a, b, c, d); } void suic_ode_geom_set_body(suic_ode_geom_id geom, suic_ode_body_id body) { - if (geom) { - dGeomSetBody(geom, body); - } + if (geom) { + dGeomSetBody(geom, body); + } } void suic_ode_geom_destroy(suic_ode_geom_id geom) { - if (geom) { - dGeomDestroy(geom); - } + if (geom) { + dGeomDestroy(geom); + } } // Collision space suic_ode_space_id suic_ode_simple_space_create(suic_ode_space_id parent) { - return dSimpleSpaceCreate(parent); + return dSimpleSpaceCreate(parent); } void suic_ode_space_destroy(suic_ode_space_id space) { - if (space) { - dSpaceDestroy(space); - } + if (space) { + dSpaceDestroy(space); + } } // ============================================================================ @@ -388,230 +420,335 @@ void suic_ode_space_destroy(suic_ode_space_id space) { // Global contact configuration static dReal contact_max_force = 10000.0; -static dReal contact_erp = 0.8; // Error reduction parameter +static dReal contact_erp = 0.8; // Error reduction parameter static dReal contact_cfm = 0.00001; // Constraint force mixing // Store world and contactgroup for collision callback typedef struct { - dWorldID world; - dJointGroupID contactgroup; + dWorldID world; + dJointGroupID contactgroup; } CollisionContext; // Collision callback for detecting contacts between geometries static void near_callback(void *data, dGeomID o1, dGeomID o2) { - CollisionContext *ctx = (CollisionContext*)data; - dBodyID b1 = dGeomGetBody(o1); - dBodyID b2 = dGeomGetBody(o2); - - // Don't process if both bodies are static or same body - if ((b1 && b2 && b1 == b2) || (!b1 && !b2)) { - return; - } - - const int N = 4; // Max contacts per collision - dContact contact[N]; - - // Check for collisions - int n = dCollide(o1, o2, N, &contact[0].geom, sizeof(dContact)); - if (n > 0) { - for (int i = 0; i < n; i++) { - // Set contact properties - contact[i].surface.mu = 0.5; // Friction coefficient - contact[i].surface.mu2 = 0.5; - contact[i].surface.bounce = 0.1; // Bounciness - contact[i].surface.bounce_vel = 0.1; - contact[i].surface.mode = dContactBounce | dContactSoftERP | dContactSoftCFM; - contact[i].surface.soft_erp = contact_erp; - contact[i].surface.soft_cfm = contact_cfm; - - // Create contact joint - dJointID c = dJointCreateContact(ctx->world, ctx->contactgroup, &contact[i]); - dJointAttach(c, b1, b2); - } + CollisionContext *ctx = (CollisionContext *)data; + dBodyID b1 = dGeomGetBody(o1); + dBodyID b2 = dGeomGetBody(o2); + + // Don't process if both bodies are static or same body + if ((b1 && b2 && b1 == b2) || (!b1 && !b2)) { + return; + } + + const int N = 4; // Max contacts per collision + dContact contact[N]; + + // Check for collisions + int n = dCollide(o1, o2, N, &contact[0].geom, sizeof(dContact)); + if (n > 0) { + for (int i = 0; i < n; i++) { + // Set contact properties + contact[i].surface.mu = 0.5; // Friction coefficient + contact[i].surface.mu2 = 0.5; + contact[i].surface.bounce = 0.1; // Bounciness + contact[i].surface.bounce_vel = 0.1; + contact[i].surface.mode = + dContactBounce | dContactSoftERP | dContactSoftCFM; + contact[i].surface.soft_erp = contact_erp; + contact[i].surface.soft_cfm = contact_cfm; + + // Create contact joint + dJointID c = + dJointCreateContact(ctx->world, ctx->contactgroup, &contact[i]); + dJointAttach(c, b1, b2); } + } } -void suic_ode_space_collide(suic_ode_world_id world, suic_ode_space_id space, suic_ode_joint_group_id contactgroup) { - if (space && contactgroup && world) { - CollisionContext ctx = {.world = world, .contactgroup = contactgroup}; - dSpaceCollide(space, (void*)&ctx, &near_callback); - } +void suic_ode_space_collide(suic_ode_world_id world, suic_ode_space_id space, + suic_ode_joint_group_id contactgroup) { + if (space && contactgroup && world) { + CollisionContext ctx = {.world = world, .contactgroup = contactgroup}; + dSpaceCollide(space, (void *)&ctx, &near_callback); + } } suic_ode_joint_group_id suic_ode_joint_group_create(int max_size) { - return dJointGroupCreate(max_size); + return dJointGroupCreate(max_size); } void suic_ode_joint_group_destroy(suic_ode_joint_group_id group) { - if (group) { - dJointGroupDestroy(group); - } + if (group) { + dJointGroupDestroy(group); + } } void suic_ode_joint_group_empty(suic_ode_joint_group_id group) { - if (group) { - dJointGroupEmpty(group); - } + if (group) { + dJointGroupEmpty(group); + } } -void suic_ode_set_contact_max_force(dReal force) { - contact_max_force = force; -} +void suic_ode_set_contact_max_force(dReal force) { contact_max_force = force; } -void suic_ode_set_contact_erp(dReal erp) { - contact_erp = erp; -} +void suic_ode_set_contact_erp(dReal erp) { contact_erp = erp; } -void suic_ode_set_contact_cfm(dReal cfm) { - contact_cfm = cfm; -} +void suic_ode_set_contact_cfm(dReal cfm) { contact_cfm = cfm; } // ============================================================================ // ADDITIONAL BODY FUNCTIONS // ============================================================================ -void suic_ode_body_get_linear_vel(suic_ode_body_id body, float *x, float *y, float *z) { - if (body) { - const dReal *vel = dBodyGetLinearVel(body); - *x = (float)vel[0]; - *y = (float)vel[1]; - *z = (float)vel[2]; - } +void suic_ode_body_get_linear_vel(suic_ode_body_id body, float *x, float *y, + float *z) { + if (body) { + const dReal *vel = dBodyGetLinearVel(body); + *x = (float)vel[0]; + *y = (float)vel[1]; + *z = (float)vel[2]; + } } -void suic_ode_body_get_rotation(suic_ode_body_id body, float *q_w, float *q_x, float *q_y, float *q_z) { - if (body) { - const dReal *q = dBodyGetQuaternion(body); - *q_w = (float)q[0]; - *q_x = (float)q[1]; - *q_y = (float)q[2]; - *q_z = (float)q[3]; - } +void suic_ode_body_get_rotation(suic_ode_body_id body, float *q_w, float *q_x, + float *q_y, float *q_z) { + if (body) { + const dReal *q = dBodyGetQuaternion(body); + *q_w = (float)q[0]; + *q_x = (float)q[1]; + *q_y = (float)q[2]; + *q_z = (float)q[3]; + } } -void suic_ode_body_set_rotation(suic_ode_body_id body, dReal q_w, dReal q_x, dReal q_y, dReal q_z) { - if (body) { - dQuaternion q; - q[0] = q_w; - q[1] = q_x; - q[2] = q_y; - q[3] = q_z; - dBodySetQuaternion(body, q); - } +void suic_ode_body_set_rotation(suic_ode_body_id body, dReal q_w, dReal q_x, + dReal q_y, dReal q_z) { + if (body) { + dQuaternion q; + q[0] = q_w; + q[1] = q_x; + q[2] = q_y; + q[3] = q_z; + dBodySetQuaternion(body, q); + } } // ============================================================================ // GAME OBJECT SYSTEM - Unified Physics & Rendering // ============================================================================ -suic_game_object* suic_game_object_create_box( - suic_ode_world_id world, - suic_ode_space_id space, - float x, float y, float z, - float width, float height, float length, - float density, - unsigned char r, unsigned char g, unsigned char b, unsigned char a -) { - suic_game_object* obj = (suic_game_object*)gc_suic_alloc(sizeof(suic_game_object)); - if (!obj) return NULL; - - // Create physics body - obj->body = dBodyCreate(world); - if (!obj->body) { - suic_gc_free(obj); - return NULL; +suic_game_object *suic_game_object_create_box( + suic_ode_world_id world, suic_ode_space_id space, float x, float y, float z, + float width, float height, float length, float density, unsigned char r, + unsigned char g, unsigned char b, unsigned char a) { + suic_game_object *obj = + (suic_game_object *)gc_suic_alloc(sizeof(suic_game_object)); + if (!obj) + return NULL; + + // Create physics body + obj->body = dBodyCreate(world); + if (!obj->body) { + suic_gc_free(obj); + return NULL; + } + + // Set position + dBodySetPosition(obj->body, x, y, z); + + // Create and attach geometry + obj->geom = dCreateBox(space, width, height, length); + if (!obj->geom) { + dBodyDestroy(obj->body); + suic_gc_free(obj); + return NULL; + } + + dGeomSetBody(obj->geom, obj->body); + + // Set mass + dMass mass; + dMassSetBox(&mass, density, width, height, length); + dBodySetMass(obj->body, &mass); + + // Store rendering data + obj->width = width; + obj->height = height; + obj->length = length; + obj->r = r; + obj->g = g; + obj->b = b; + obj->a = a; + obj->shape_type = 0; // 0 = box + + return obj; +} + +void suic_game_object_destroy(suic_game_object *obj) { + if (obj) { + if (obj->geom) { + dGeomDestroy(obj->geom); } - - // Set position + if (obj->body) { + dBodyDestroy(obj->body); + } + suic_gc_free(obj); + } +} + +void suic_game_object_set_position(suic_game_object *obj, float x, float y, + float z) { + if (obj && obj->body) { dBodySetPosition(obj->body, x, y, z); - - // Create and attach geometry - obj->geom = dCreateBox(space, width, height, length); - if (!obj->geom) { - dBodyDestroy(obj->body); - suic_gc_free(obj); - return NULL; - } - - dGeomSetBody(obj->geom, obj->body); - - // Set mass - dMass mass; - dMassSetBox(&mass, density, width, height, length); - dBodySetMass(obj->body, &mass); - - // Store rendering data - obj->width = width; - obj->height = height; - obj->length = length; - obj->r = r; - obj->g = g; - obj->b = b; - obj->a = a; - obj->shape_type = 0; // 0 = box - - return obj; + } } -void suic_game_object_destroy(suic_game_object* obj) { - if (obj) { - if (obj->geom) { - dGeomDestroy(obj->geom); - } - if (obj->body) { - dBodyDestroy(obj->body); - } - suic_gc_free(obj); - } +void suic_game_object_get_position(suic_game_object *obj, float *x, float *y, + float *z) { + if (obj && obj->body) { + const dReal *pos = dBodyGetPosition(obj->body); + *x = (float)pos[0]; + *y = (float)pos[1]; + *z = (float)pos[2]; + } } -void suic_game_object_set_position(suic_game_object* obj, float x, float y, float z) { - if (obj && obj->body) { - dBodySetPosition(obj->body, x, y, z); - } +void suic_game_object_set_velocity(suic_game_object *obj, float x, float y, + float z) { + if (obj && obj->body) { + dBodySetLinearVel(obj->body, x, y, z); + } } -void suic_game_object_get_position(suic_game_object* obj, float *x, float *y, float *z) { - if (obj && obj->body) { - const dReal *pos = dBodyGetPosition(obj->body); - *x = (float)pos[0]; - *y = (float)pos[1]; - *z = (float)pos[2]; - } +void suic_game_object_get_velocity(suic_game_object *obj, float *x, float *y, + float *z) { + if (obj && obj->body) { + const dReal *vel = dBodyGetLinearVel(obj->body); + *x = (float)vel[0]; + *y = (float)vel[1]; + *z = (float)vel[2]; + } } -void suic_game_object_set_velocity(suic_game_object* obj, float x, float y, float z) { - if (obj && obj->body) { - dBodySetLinearVel(obj->body, x, y, z); +void suic_game_object_draw(suic_game_object *obj) { + if (obj && obj->body) { + float x, y, z; + suic_game_object_get_position(obj, &x, &y, &z); + + if (obj->shape_type == 0) { // Box + DrawCube((Vector3){x, y, z}, obj->width, obj->height, obj->length, + (Color){obj->r, obj->g, obj->b, obj->a}); + // Draw wireframe for visual clarity + DrawCubeWires((Vector3){x, y, z}, obj->width, obj->height, obj->length, + (Color){0, 0, 0, 200}); } + } } -void suic_game_object_get_velocity(suic_game_object* obj, float *x, float *y, float *z) { - if (obj && obj->body) { - const dReal *vel = dBodyGetLinearVel(obj->body); - *x = (float)vel[0]; - *y = (float)vel[1]; - *z = (float)vel[2]; - } +// ============================================================================ +// PLAYER CONTROLLER - FPS STYLE MOVEMENT +// ============================================================================ + +suic_player_controller *suic_player_controller_create(float x, float y, + float z) { + suic_player_controller *player = + (suic_player_controller *)gc_suic_alloc(sizeof(suic_player_controller)); + if (!player) + return NULL; + + player->position = (suic_vec3){x, y, z}; + player->velocity = (suic_vec3){0.0, 0.0, 0.0}; + player->forward = (suic_vec3){0.0, 0.0, -1.0}; // Looking down -Z + player->right = (suic_vec3){1.0, 0.0, 0.0}; // Right is +X + player->move_speed = 5.0; // units per second + player->sprint_speed = 10.0; // units per second + player->jump_force = 10.0; // units per second + player->gravity = -9.81; + player->is_grounded = 1; + + return player; } -void suic_game_object_draw(suic_game_object* obj) { - if (obj && obj->body) { - float x, y, z; - suic_game_object_get_position(obj, &x, &y, &z); - - if (obj->shape_type == 0) { // Box - DrawCube( - (Vector3){x, y, z}, - obj->width, obj->height, obj->length, - (Color){obj->r, obj->g, obj->b, obj->a} - ); - // Draw wireframe for visual clarity - DrawCubeWires( - (Vector3){x, y, z}, - obj->width, obj->height, obj->length, - (Color){0, 0, 0, 200} - ); - } - } +void suic_player_controller_destroy(suic_player_controller *player) { + if (player) { + suic_gc_free(player); + } } + +void suic_player_controller_update(suic_player_controller *player, + float delta_time) { + if (!player) + return; + + // Apply gravity + player->velocity.y += player->gravity * delta_time; + + // Update position + player->position.x += player->velocity.x * delta_time; + player->position.y += player->velocity.y * delta_time; + player->position.z += player->velocity.z * delta_time; +} + +void suic_player_controller_set_direction(suic_player_controller *player, + float forward_x, float forward_y, + float forward_z, float right_x, + float right_y, float right_z) { + if (!player) + return; + player->forward = (suic_vec3){forward_x, forward_y, forward_z}; + player->right = (suic_vec3){right_x, right_y, right_z}; +} + +void suic_player_controller_move_forward(suic_player_controller *player, + float amount) { + if (!player) + return; + + float speed = player->move_speed; + if (suic_is_sprint_held()) { + speed = player->sprint_speed; + } + + player->velocity.x += player->forward.x * speed * amount; + player->velocity.z += player->forward.z * speed * amount; +} + +void suic_player_controller_move_right(suic_player_controller *player, + float amount) { + if (!player) + return; + + float speed = player->move_speed; + if (suic_is_sprint_held()) { + speed = player->sprint_speed; + } + + player->velocity.x += player->right.x * speed * amount; + player->velocity.z += player->right.z * speed * amount; +} + +void suic_player_controller_jump(suic_player_controller *player) { + if (!player || !player->is_grounded) + return; + + player->velocity.y = player->jump_force; + player->is_grounded = 0; +} + +void suic_player_controller_get_position(suic_player_controller *player, + float *x, float *y, float *z) { + if (player) { + *x = player->position.x; + *y = player->position.y; + *z = player->position.z; + } +} + +void suic_player_controller_set_position(suic_player_controller *player, + float x, float y, float z) { + if (player) { + player->position.x = x; + player->position.y = y; + player->position.z = z; + } +} + diff --git a/libsuicmez/libsuicmez.h b/libsuicmez/libsuicmez.h index baafec8..dba015f 100644 --- a/libsuicmez/libsuicmez.h +++ b/libsuicmez/libsuicmez.h @@ -5,6 +5,10 @@ #include #include #include +#include + +// Include GC header for TypeInfo +#include "suicmez_gc.h" // Raylib support #include "raylib.h" @@ -52,11 +56,43 @@ static inline suic_vec3 suic_from_rl_vec3(Vector3 v) { return (suic_vec3){v.x, v.y, v.z}; } +// Keyboard key constants (from raylib) +#define KEY_W 87 +#define KEY_A 65 +#define KEY_S 83 +#define KEY_D 68 +#define KEY_SPACE 32 +#define KEY_LEFT_SHIFT 341 +#define KEY_LEFT_CTRL 341 // Platform dependent +#define KEY_LEFT_ALT 342 +#define KEY_UP 265 +#define KEY_DOWN 264 +#define KEY_LEFT 263 +#define KEY_RIGHT 262 +#define KEY_ESCAPE 256 +#define KEY_ENTER 257 +#define KEY_TAB 258 +#define KEY_BACKSPACE 259 +#define KEY_DELETE 261 +#define KEY_HOME 268 +#define KEY_END 269 +#define KEY_EQUAL 61 +#define KEY_MINUS 45 +#define KEY_KP_ADD 334 +#define KEY_KP_SUBTRACT 333 +#define KEY_F1 290 + +// Mouse button constants +#define MOUSE_LEFT 0 +#define MOUSE_RIGHT 1 +#define MOUSE_MIDDLE 2 + // Window management bool suic_init_window(int width, int height, const char *title); void suic_close_window(void); bool suic_window_should_close(void); void suic_set_target_fps(int fps); +void suic_enable_msaa_4x(void); // Drawing (2D) void suic_begin_drawing(void); @@ -80,10 +116,37 @@ void suic_end_mode3d(void); void suic_draw_cube(float x, float y, float z, float width, float height, float length, unsigned char r, unsigned char g, unsigned char b, unsigned char a); void suic_draw_cube_wires(float x, float y, float z, float width, float height, float length, unsigned char r, unsigned char g, unsigned char b, unsigned char a); -// Input +// Input - Keyboard bool suic_is_key_down(int key); +bool suic_is_key_pressed(int key); +bool suic_is_key_released(int key); + +// Input - Mouse bool suic_is_mouse_button_down(int b); +bool suic_is_mouse_button_pressed(int b); +bool suic_is_mouse_button_released(int b); suic_vec2 suic_get_mouse_position(void); +suic_vec2 suic_get_mouse_delta(void); +float suic_get_mouse_x(void); +float suic_get_mouse_y(void); +float suic_get_mouse_delta_x(void); +float suic_get_mouse_delta_y(void); + +// Input - Helper functions for gamedev +int suic_is_movement_input(void); // Returns bitmask: 1=W, 2=A, 4=S, 8=D +int suic_is_sprint_held(void); +int suic_is_jump_pressed(void); + +// Cursor management +void suic_disable_cursor(void); +void suic_enable_cursor(void); +bool suic_is_cursor_hidden(void); + +// Matrix operations for 3D transformations +void suic_rl_push_matrix(void); +void suic_rl_pop_matrix(void); +void suic_rl_translate_f(float x, float y, float z); +void suic_rl_rotate_f(float angle, float x, float y, float z); // Images and Textures typedef struct suic_image_handle { @@ -119,10 +182,23 @@ void suic_sound_play(suic_sound_handle snd); void suic_sound_set_volume(suic_sound_handle snd, float volume); void suic_sound_free(suic_sound_handle *snd); +// Player controller for FPS-style movement +typedef struct suic_player_controller { + suic_vec3 position; + suic_vec3 velocity; + suic_vec3 forward; // Camera forward direction + suic_vec3 right; // Camera right direction + float move_speed; + float sprint_speed; + float jump_force; + float gravity; + int is_grounded; +} suic_player_controller; + // Raycasting typedef struct suic_ray { - suic_vec3 origin; - suic_vec3 direction; + suic_vec3 origin; + suic_vec3 direction; } suic_ray; typedef struct suic_rayhit { @@ -230,4 +306,15 @@ void suic_game_object_set_velocity(suic_game_object* obj, float x, float y, floa void suic_game_object_get_velocity(suic_game_object* obj, float *x, float *y, float *z); void suic_game_object_draw(suic_game_object* obj); +// Player controller functions for FPS-style games +suic_player_controller* suic_player_controller_create(float x, float y, float z); +void suic_player_controller_destroy(suic_player_controller* player); +void suic_player_controller_update(suic_player_controller* player, float delta_time); +void suic_player_controller_set_direction(suic_player_controller* player, float forward_x, float forward_y, float forward_z, float right_x, float right_y, float right_z); +void suic_player_controller_move_forward(suic_player_controller* player, float amount); +void suic_player_controller_move_right(suic_player_controller* player, float amount); +void suic_player_controller_jump(suic_player_controller* player); +void suic_player_controller_get_position(suic_player_controller* player, float *x, float *y, float *z); +void suic_player_controller_set_position(suic_player_controller* player, float x, float y, float z); + #endif // LIBSUICMEZ_H diff --git a/libsuicmez/suicmez_gc.c b/libsuicmez/suicmez_gc.c index f51aa70..42bfce9 100644 --- a/libsuicmez/suicmez_gc.c +++ b/libsuicmez/suicmez_gc.c @@ -112,6 +112,16 @@ static Obj *forward(Obj *obj) { return new_obj; } +static inline void scan_object_fields(Obj *obj) { + const TypeInfo *t = obj->header.type; + + for (uint16_t i = 0; i < t->field_count; i++) { + if (t->pointer_bitmap[i]) { + obj->fields[i] = forward((Obj*)obj->fields[i]); + } + } +} + static void gc_minor_collect(void) { gc.to_ptr = gc.to_space; @@ -189,16 +199,6 @@ void *gc_alloc(const TypeInfo *type, size_t payload_size) { return obj; } -static inline void scan_object_fields(Obj *obj) { - const TypeInfo *t = obj->header.type; - - for (uint16_t i = 0; i < t->field_count; i++) { - if (t->pointer_bitmap[i]) { - obj->fields[i] = forward((Obj*)obj->fields[i]); - } - } -} - void gc_init(void) { gc.young_size = YOUNG_SIZE; gc.old_size = OLD_SIZE; diff --git a/libsuicmez/suicmez_gc.h b/libsuicmez/suicmez_gc.h index 274c9da..43a233d 100644 --- a/libsuicmez/suicmez_gc.h +++ b/libsuicmez/suicmez_gc.h @@ -15,6 +15,7 @@ /* Forward declare Obj so ObjHeader can reference it */ typedef struct Obj Obj; +/* Forward declare TypeInfo */ typedef struct TypeInfo TypeInfo; /* Header must come first */ diff --git a/src/c_ir.rs b/src/c_ir.rs index aca4d2a..ec173e8 100644 --- a/src/c_ir.rs +++ b/src/c_ir.rs @@ -1,4 +1,4 @@ -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum CType { Void, Int, @@ -56,20 +56,20 @@ impl CType { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct CVarDecl { pub name: String, pub ty: CType, pub initializer: Option, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct CStructDecl { pub name: String, pub fields: Vec, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct CFuncDecl { pub name: String, pub return_type: CType, @@ -77,7 +77,7 @@ pub struct CFuncDecl { pub body: Option>, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum CExpr { IntLit(i64), FloatLit(f64), @@ -99,7 +99,7 @@ pub enum CExpr { Ternary(Box, Box, Box), // cond ? then : else } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum CBinaryOp { Add, Sub, @@ -136,7 +136,7 @@ impl CBinaryOp { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum CUnaryOp { Neg, Not, @@ -157,7 +157,7 @@ impl CUnaryOp { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum CStmt { VarDecl(CVarDecl), Expr(CExpr), @@ -171,7 +171,7 @@ pub enum CStmt { Block(Vec), } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum CToplevel { StructDecl(CStructDecl), FuncDecl(CFuncDecl), diff --git a/src/c_lowerer/declaration_transpiler.rs b/src/c_lowerer/declaration_transpiler.rs index dedfcfa..5cb7dae 100644 --- a/src/c_lowerer/declaration_transpiler.rs +++ b/src/c_lowerer/declaration_transpiler.rs @@ -179,6 +179,7 @@ pub fn convert_to_c_type(name: &String) -> Result { "float" => Ok(CType::Float), "bool" => Ok(CType::Bool), "string" => Ok(CType::Ptr(Box::new(CType::Char))), + "()" => Ok(CType::Void), // Unit type _ => Ok(CType::Ptr(Box::new(CType::Struct(name.clone())))), // Assume heap-allocated struct } } diff --git a/src/c_lowerer/statements_transpiler.rs b/src/c_lowerer/statements_transpiler.rs index 2038f25..2c6f76c 100644 --- a/src/c_lowerer/statements_transpiler.rs +++ b/src/c_lowerer/statements_transpiler.rs @@ -339,6 +339,15 @@ impl StatementsTranspiler { TypedExprKind::Break => Ok(CStmt::Break), TypedExprKind::Continue => Ok(CStmt::Continue), TypedExprKind::Defer(_) => Err("Defer should be handled in Do blocks".to_string()), + TypedExprKind::If(cond, then_expr, else_expr) => { + let c_cond = self.transpile_expr(cond)?; + let then_stmts = self.expr_to_loop_stmts(then_expr)?; + let else_stmts = match else_expr { + Some(else_expr) => self.expr_to_loop_stmts(else_expr)?, + None => vec![], + }; + Ok(CStmt::If(c_cond, then_stmts, if else_stmts.is_empty() { None } else { Some(else_stmts) })) + } _ => { // For other expressions, treat as expression statements let c_expr = self.transpile_expr(expr)?; @@ -385,6 +394,11 @@ impl StatementsTranspiler { } Ok(c_stmts) } + TypedExprKind::If(_, _, _) => { + // For If expressions at the statement level, treat as statement + let stmt = self.transpile_stmt(expr)?; + Ok(vec![stmt]) + } _ => Ok(vec![CStmt::Return(Some(self.transpile_expr(expr)?))]), } } diff --git a/src/codegen/transpiler.rs b/src/codegen/transpiler.rs index dae1960..87aa005 100644 --- a/src/codegen/transpiler.rs +++ b/src/codegen/transpiler.rs @@ -41,10 +41,12 @@ pub struct Transpiler { stmt_transpiler: StatementsTranspiler, array_types: std::collections::HashSet, // Track array types we need to generate has_main: bool, // Track if we found a main function + typeinfo_map: std::collections::HashMap>, // Map struct name to pointer bitmap + debug: bool, // Whether to generate debug printf statements } impl Transpiler { - pub fn new() -> Self { + pub fn new(debug: bool) -> Self { Transpiler { structs: Vec::new(), functions: Vec::new(), @@ -53,6 +55,8 @@ impl Transpiler { stmt_transpiler: StatementsTranspiler::new(), array_types: std::collections::HashSet::new(), has_main: false, + typeinfo_map: std::collections::HashMap::new(), + debug, } } @@ -68,6 +72,19 @@ impl Transpiler { } } + /// Check if a CType is a pointer type (needs to be tracked in GC bitmap) + fn is_pointer_type(ty: &CType) -> bool { + matches!(ty, CType::Ptr(_) | CType::Array(_) | CType::Struct(_)) + } + + /// Generate pointer bitmap for a struct's fields + fn generate_pointer_bitmap(fields: &[CVarDecl]) -> Vec { + fields + .iter() + .map(|field| if Self::is_pointer_type(&field.ty) { 1u8 } else { 0u8 }) + .collect() + } + pub fn transpile_program(&mut self, nodes: &[TypedASTNode]) -> Result { for node in nodes { self.lower_declarations_to_c_ir(node)?; @@ -93,16 +110,17 @@ impl Transpiler { output.push_str("\n"); // GC functions - output.push_str("void* gc_suic_alloc(size_t size);\n"); - output.push_str("void suic_gc_free(void* ptr);\n"); + output.push_str("void* gc_alloc(const TypeInfo* type, size_t size);\n"); + output.push_str("void gc_init(void);\n"); + output.push_str("void gc_shutdown(void);\n"); output.push_str("\n"); // Helper functions for heap allocation output.push_str("// Helper for allocating arrays\n"); output.push_str( - "static void* suic_alloc_array(size_t elem_size, size_t len, void* init_data) {\n", + "static void* suic_alloc_array(const TypeInfo* type, size_t elem_size, size_t len, void* init_data) {\n", ); - output.push_str(" void* ptr = gc_suic_alloc(elem_size * len);\n"); + output.push_str(" void* ptr = gc_alloc(type, elem_size * len);\n"); output.push_str(" if (init_data) memcpy(ptr, init_data, elem_size * len);\n"); output.push_str(" return ptr;\n"); output.push_str("}\n"); @@ -110,8 +128,8 @@ impl Transpiler { // Helper for allocating structs output.push_str("// Helper for allocating structs\n"); - output.push_str("static void* suic_alloc_struct(size_t size, void* init_data) {\n"); - output.push_str(" void* ptr = gc_suic_alloc(size);\n"); + output.push_str("static void* suic_alloc_struct(const TypeInfo* type, size_t size, void* init_data) {\n"); + output.push_str(" void* ptr = gc_alloc(type, size);\n"); output.push_str(" if (init_data) memcpy(ptr, init_data, size);\n"); output.push_str(" return ptr;\n"); output.push_str("}\n"); @@ -129,6 +147,14 @@ impl Transpiler { output.push_str(&self.generate_struct_decl(struct_decl)); output.push_str(";\n"); } + output.push_str("\n"); + + // Generate TypeInfo definitions for GC + for struct_decl in &self.structs { + output.push_str(&self.generate_typeinfo_decl(struct_decl)); + output.push_str("\n"); + } + output.push_str("\n"); // Generate function declarations (prototypes) for func in &self.functions { @@ -167,6 +193,9 @@ impl Transpiler { for field in &struct_decl.fields { self.collect_array_types_from_ctype(&field.ty); } + // Generate TypeInfo bitmap for this struct + let bitmap = Self::generate_pointer_bitmap(&struct_decl.fields); + self.typeinfo_map.insert(struct_decl.name.clone(), bitmap); self.structs.push(struct_decl); } TypedASTNodeKind::Enum(e) => { @@ -175,6 +204,9 @@ impl Transpiler { for field in &struct_decl.fields { self.collect_array_types_from_ctype(&field.ty); } + // Generate TypeInfo bitmap for this enum struct + let bitmap = Self::generate_pointer_bitmap(&struct_decl.fields); + self.typeinfo_map.insert(struct_decl.name.clone(), bitmap); self.structs.push(struct_decl); } } @@ -265,6 +297,46 @@ impl Transpiler { output } + fn generate_typeinfo_decl(&self, struct_decl: &CStructDecl) -> String { + if let Some(bitmap) = self.typeinfo_map.get(&struct_decl.name) { + // Generate pointer bitmap as a C array + let bitmap_str = bitmap + .iter() + .map(|b| b.to_string()) + .collect::>() + .join(", "); + + let field_count = struct_decl.fields.len(); + let pointer_count = bitmap.iter().filter(|&&b| b == 1).count(); + + format!( + "static const uint8_t sui_bitmap_{}[] = {{ {} }};\n\ + static const TypeInfo sui_typeinfo_{} = {{\n \ + .field_count = {},\n \ + .pointer_count = {},\n \ + .pointer_bitmap = sui_bitmap_{}\n\ + }};", + struct_decl.name, + bitmap_str, + struct_decl.name, + field_count, + pointer_count, + struct_decl.name + ) + } else { + // Empty bitmap for struct with no fields + format!( + "static const uint8_t sui_bitmap_{}[] = {{}};\n\ + static const TypeInfo sui_typeinfo_{} = {{\n \ + .field_count = 0,\n \ + .pointer_count = 0,\n \ + .pointer_bitmap = sui_bitmap_{}\n\ + }};", + struct_decl.name, struct_decl.name, struct_decl.name + ) + } + } + fn generate_func_proto(&self, func: &CFuncDecl) -> String { let params_str = if func.params.is_empty() { "void".to_string() @@ -300,11 +372,13 @@ impl Transpiler { fn generate_wrapper_main(&self) -> String { let mut output = String::new(); output.push_str("int main(int argc, char* argv[]) {\n"); - output.push_str(" // init gc and stuff\n"); + output.push_str(" // Initialize GC\n"); + output.push_str(" gc_init();\n"); output.push_str(" // init globals\n"); output.push_str(" // init event loop\n"); output.push_str(" int result = suic_main();\n"); - output.push_str(" // free the stuff\n"); + output.push_str(" // Shutdown GC\n"); + output.push_str(" gc_shutdown();\n"); output.push_str(" return result;\n"); output.push_str("}\n"); output @@ -321,13 +395,13 @@ impl Transpiler { fn generate_heap_alloc(&self, ty: &CType) -> String { match ty { CType::Struct(name) => { - format!("(struct {}*)suic_gc_alloc(sizeof(struct {}))", name, name) + format!("(struct {}*)gc_alloc(&sui_typeinfo_{}, sizeof(struct {}))", name, name, name) } CType::Array(elem_type) => { + let array_name = Self::get_array_struct_name(elem_type); format!( - "(struct {}*)suic_gc_alloc(sizeof(struct {}))", - Self::get_array_struct_name(elem_type), - Self::get_array_struct_name(elem_type) + "(struct {}*)gc_alloc(&sui_typeinfo_{}, sizeof(struct {}))", + array_name, array_name, array_name ) } _ => "NULL".to_string(), @@ -335,7 +409,10 @@ impl Transpiler { } fn add_debug_print(&self, code: &str) -> String { - // Extract the actual statement for the debug message + if !self.debug { + return code.to_string(); + } + let trimmed = code.trim_end_matches('\n').trim_start(); let trimmed_no_semi = trimmed.trim_end_matches(';'); @@ -452,8 +529,10 @@ impl Transpiler { CExpr::FloatLit(f) => format!("{:.6}", f), CExpr::BoolLit(b) => format!("{}", b), CExpr::StringLit(s) => { + // For strings, we treat them as char arrays, so use a generic TypeInfo + // that marks all fields as non-pointers format!( - "suic_alloc_array(sizeof(char), {}, \"{}\")", + "suic_alloc_array(NULL, sizeof(char), {}, \"{}\")", s.len() + 1, // +1 for null terminator s ) @@ -493,19 +572,62 @@ impl Transpiler { "ode_body_get_linear_vel" => "suic_ode_body_get_linear_vel", "ode_body_get_rotation" => "suic_ode_body_get_rotation", "ode_body_set_rotation" => "suic_ode_body_set_rotation", - // Raylib functions - "init_window" => "suic_init_window", - "close_window" => "suic_close_window", - "window_should_close" => "suic_window_should_close", - "set_target_fps" => "suic_set_target_fps", + // Raylib functions + "init_window" => "suic_init_window", + "close_window" => "suic_close_window", + "window_should_close" => "suic_window_should_close", + "set_target_fps" => "suic_set_target_fps", + "enable_msaa_4x" => "suic_enable_msaa_4x", "begin_drawing" => "suic_begin_drawing", "end_drawing" => "suic_end_drawing", "clear_background" => "suic_clear_background", - "begin_mode3d" => "suic_begin_mode3d", - "end_mode3d" => "suic_end_mode3d", - "draw_cube" => "suic_draw_cube", - "draw_cube_wires" => "suic_draw_cube_wires", + "begin_mode3d" => "suic_begin_mode3d", + "end_mode3d" => "suic_end_mode3d", + "draw_cube" => "suic_draw_cube", + "draw_cube_wires" => "suic_draw_cube_wires", + "enable_msaa_4x" => "suic_enable_msaa_4x", + "enable_msaa_8x" => "suic_enable_msaa_8x", + "enable_msaa_16x" => "suic_enable_msaa_16x", + // Input - Keyboard "is_key_down" => "suic_is_key_down", + "is_key_pressed" => "suic_is_key_pressed", + "is_key_released" => "suic_is_key_released", + // Input - Mouse + "is_mouse_button_down" => "suic_is_mouse_button_down", + "is_mouse_button_pressed" => "suic_is_mouse_button_pressed", + "is_mouse_button_released" => "suic_is_mouse_button_released", + "get_mouse_position" => "suic_get_mouse_position", + "get_mouse_delta" => "suic_get_mouse_delta", + "get_mouse_x" => "suic_get_mouse_x", + "get_mouse_y" => "suic_get_mouse_y", + "get_mouse_delta_x" => "suic_get_mouse_delta_x", + "get_mouse_delta_y" => "suic_get_mouse_delta_y", + // Input - Gamedev helpers + "is_movement_input" => "suic_is_movement_input", + "is_sprint_held" => "suic_is_sprint_held", + "is_jump_pressed" => "suic_is_jump_pressed", + // Cursor management + "disable_cursor" => "suic_disable_cursor", + "enable_cursor" => "suic_enable_cursor", + "is_cursor_hidden" => "suic_is_cursor_hidden", + // Matrix operations + "rl_push_matrix" => "suic_rl_push_matrix", + "rl_pop_matrix" => "suic_rl_pop_matrix", + "rl_translate_f" => "suic_rl_translate_f", + "rl_rotate_f" => "suic_rl_rotate_f", + // Player controller functions + "player_controller_create" => "suic_player_controller_create", + "player_controller_destroy" => "suic_player_controller_destroy", + "player_controller_update" => "suic_player_controller_update", + "player_controller_set_direction" => "suic_player_controller_set_direction", + "player_controller_move_forward" => "suic_player_controller_move_forward", + "player_controller_move_right" => "suic_player_controller_move_right", + "player_controller_jump" => "suic_player_controller_jump", + "player_controller_get_position" => "suic_player_controller_get_position", + "player_controller_set_position" => "suic_player_controller_set_position", + // Math functions + "sin" => "sin", + "cos" => "cos", _ => func, }; @@ -523,7 +645,10 @@ impl Transpiler { format!("{}{}", op.to_string(), self.generate_expr(expr)) } CExpr::Cast(expr, ty) => { - format!("({}) {}", ty.to_string(), self.generate_expr(expr)) + match (*expr.clone(), ty.clone()) { + (CExpr::IntLit(0), CType::Ptr(_)) => "NULL".to_string(), + _ => format!("({}) {}", ty.to_string(), self.generate_expr(expr)), + } } CExpr::AddrOf(expr) => format!("&{}", self.generate_expr(expr)), CExpr::Deref(expr) => format!("*{}", self.generate_expr(expr)), @@ -539,7 +664,8 @@ impl Transpiler { .map(|(name, expr)| format!(".{} = {}", name, self.generate_expr(expr))) .collect(); format!( - "suic_alloc_struct(sizeof(struct {}), &(struct {}){{ {} }})", + "suic_alloc_struct(&sui_typeinfo_{}, sizeof(struct {}), &(struct {}){{ {} }})", + struct_name, struct_name, struct_name, field_inits.join(", ") @@ -571,8 +697,8 @@ impl Transpiler { }; format!( - "suic_alloc_struct(sizeof(struct {}), &(struct {}){{ .discriminant = {}, .data = {{ .{} = {} }} }})", - enum_name, enum_name, variant_index, union_field_name, variant_init + "suic_alloc_struct(&sui_typeinfo_{}, sizeof(struct {}), &(struct {}){{ .discriminant = {}, .data = {{ .{} = {} }} }})", + enum_name, enum_name, enum_name, variant_index, union_field_name, variant_init ) } @@ -585,8 +711,9 @@ impl Transpiler { .map(|expr| self.generate_expr(expr)) .collect(); // Generate heap-allocated array using helper function + // Use NULL for TypeInfo since arrays of primitives don't contain pointers format!( - "suic_alloc_array(sizeof(int), {}, (int[]){{{}}})", + "suic_alloc_array(NULL, sizeof(int), {}, (int[]){{{}}})", vec.len(), vec.join(", ") ) diff --git a/src/lexer/mod.rs b/src/lexer/mod.rs index a64b756..7cf5825 100644 --- a/src/lexer/mod.rs +++ b/src/lexer/mod.rs @@ -37,10 +37,10 @@ pub enum Token { })] String(String), - #[regex(r#"r#"([^"]*)""#, |lex| { + #[regex(r#"r"([^"]*)""#, |lex| { let s = lex.slice(); // Remove the outer r" and " (s[2..s.len() - 1]) - s[3..s.len() - 1].to_string() + s[2..s.len() - 1].to_string() })] RawString(String), diff --git a/src/lexer/tests.rs b/src/lexer/tests.rs index 6e03c88..21b0e62 100644 --- a/src/lexer/tests.rs +++ b/src/lexer/tests.rs @@ -10,9 +10,7 @@ fn test_literals() { assert_eq!(lexer.next(), Some(Ok(Token::Int(42)))); assert_eq!(lexer.next(), Some(Ok(Token::Float(2.14)))); assert_eq!(lexer.next(), Some(Ok(Token::String("hello".to_string())))); - // RawString regex seems to have issues, let's test separately - assert_eq!(lexer.next(), Some(Ok(Token::Variable("r".to_string())))); - assert_eq!(lexer.next(), Some(Ok(Token::String("raw".to_string())))); + assert_eq!(lexer.next(), Some(Ok(Token::RawString("raw".to_string())))); assert_eq!(lexer.next(), None); } diff --git a/src/main.rs b/src/main.rs index 7d454da..cd17113 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,10 @@ struct Args { #[arg(short, long)] test: bool, + /// Generate debug printf statements in the output C code + #[arg(long)] + debug: bool, + /// The Sui source file to compile file: Option, } @@ -27,7 +31,7 @@ fn main() { } else if let Some(filename) = args.file { println!("Type checking file: {}", filename); - if let Err(e) = run_file(&filename) { + if let Err(e) = run_file(&filename, args.debug) { eprintln!("Error: {}", e); } } else { @@ -53,7 +57,7 @@ fn run_test_suite() { for file in test_files { println!("Testing: {}", file); - match run_file(file) { + match run_file(file, false) { Ok(_) => println!("✓ Passed\n"), Err(e) => println!("✗ Failed: {}\n", e), } @@ -175,7 +179,7 @@ fn format_type_error(source: &str, error: &suicmez::typechecker::TypeError) -> S format!("Type error: {} (at byte {})", error.kind, error.span.start) } -fn run_file(filename: &str) -> Result<(), String> { +fn run_file(filename: &str, debug: bool) -> Result<(), String> { // ========== IMPORT RESOLUTION PHASE ========== println!("\n=== Import Resolution Phase ==="); let mut resolver = ImportResolver::new(); @@ -315,7 +319,7 @@ fn run_file(filename: &str) -> Result<(), String> { println!("Type variable check passed! No type variables remain in AST."); // Generate C code - let mut transpiler = Transpiler::new(); + let mut transpiler = Transpiler::new(debug); let c_code = transpiler .transpile_program(&mono_nodes) .map_err(|e| format!("Code generation error: {}", e))?; diff --git a/src/typechecker.rs b/src/typechecker.rs index 2dccee6..c7ac8a7 100644 --- a/src/typechecker.rs +++ b/src/typechecker.rs @@ -660,6 +660,77 @@ impl TypeChecker { return_type: Type::Unit, }, ); + self.env.functions.insert( + "enable_msaa_4x".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Unit, + }, + ); + + // Cursor management + self.env.functions.insert( + "disable_cursor".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "enable_cursor".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Unit, + }, + ); + + // Input helpers + self.env.functions.insert( + "is_movement_input".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Int, + }, + ); + self.env.functions.insert( + "is_sprint_held".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Int, + }, + ); + self.env.functions.insert( + "is_jump_pressed".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Int, + }, + ); + + // Key constants + let keys = vec![ + "KEY_W", "KEY_A", "KEY_S", "KEY_D", "KEY_SPACE", "KEY_LEFT_SHIFT", + "KEY_EQUAL", "KEY_MINUS", "KEY_KP_ADD", "KEY_KP_SUBTRACT", + "KEY_ESCAPE", "KEY_ENTER", "KEY_TAB", "KEY_BACKSPACE", "KEY_DELETE", + "KEY_HOME", "KEY_END", "KEY_F1" + ]; + for (i, key) in keys.iter().enumerate() { + let id = 1000 + i; + self.env.name_to_id.insert(key.to_string(), BindingId(id)); + self.env.vars.insert(BindingId(id), VarInfo { + ty: Type::Int, + kind: BindingKind::Default, + name: key.to_string(), + usage: 0, + span: Span { start: 0, end: 0, file: "builtin".to_string() }, + }); + } // Drawing self.env.functions.insert( @@ -766,6 +837,22 @@ impl TypeChecker { return_type: Type::Bool, }, ); + self.env.functions.insert( + "is_key_pressed".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Int], // key + return_type: Type::Bool, + }, + ); + self.env.functions.insert( + "is_key_released".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Int], // key + return_type: Type::Bool, + }, + ); // Physics integration helper self.env.functions.insert( @@ -781,6 +868,120 @@ impl TypeChecker { return_type: Type::Unit, }, ); + + // Built-in Vec2 type + self.env.add_type( + "Vec2".to_string(), + TypeInfo { + kind: TypeInfoKind::Struct(vec![ + ("x".to_string(), TypeAnnot::Var("float".to_string())), + ("y".to_string(), TypeAnnot::Var("float".to_string())), + ]), + parameters: vec![], + }, + ); + + // Mouse input functions + self.env.functions.insert( + "get_mouse_position".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Struct("Vec2".to_string(), vec![]), // suic_vec2 + }, + ); + self.env.functions.insert( + "get_mouse_delta".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Struct("Vec2".to_string(), vec![]), // suic_vec2 + }, + ); + self.env.functions.insert( + "get_mouse_x".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Float, + }, + ); + self.env.functions.insert( + "get_mouse_y".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Float, + }, + ); + self.env.functions.insert( + "get_mouse_delta_x".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Float, + }, + ); + self.env.functions.insert( + "get_mouse_delta_y".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Float, + }, + ); + + // Math functions + self.env.functions.insert( + "cos".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Float], // angle in radians + return_type: Type::Float, + }, + ); + self.env.functions.insert( + "sin".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Float], // angle in radians + return_type: Type::Float, + }, + ); + + // Raylib matrix operations + self.env.functions.insert( + "rl_push_matrix".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "rl_pop_matrix".to_string(), + FunctionType { + type_params: vec![], + params: vec![], + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "rl_translate_f".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Float, Type::Float, Type::Float], // x, y, z + return_type: Type::Unit, + }, + ); + self.env.functions.insert( + "rl_rotate_f".to_string(), + FunctionType { + type_params: vec![], + params: vec![Type::Float, Type::Float, Type::Float, Type::Float], // angle, x, y, z + return_type: Type::Unit, + }, + ); } fn collect_definitions(&mut self, node: &ASTNode) -> Result<(), TypeError> { diff --git a/test_player.c b/test_player.c new file mode 100644 index 0000000..28c6fa0 --- /dev/null +++ b/test_player.c @@ -0,0 +1,46 @@ +#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) { + void* p = suic_player_controller_create(0.000000, 1.000000, 2.000000); + 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/test_player.sui b/test_player.sui new file mode 100644 index 0000000..2fb5b01 --- /dev/null +++ b/test_player.sui @@ -0,0 +1 @@ +fn main() -> int do let p = player_controller_create(0.0, 1.0, 2.0); 0 end diff --git a/test_window b/test_window new file mode 100755 index 0000000000000000000000000000000000000000..96801af400dbf07f38585f067e7ce42ce4396a5e GIT binary patch literal 44536 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 +#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) { + suic_init_window(800, 600, suic_alloc_array(NULL, sizeof(char), 5, "Test")); + suic_set_target_fps(60); + while ((suic_window_should_close() == false)) { + suic_begin_drawing(); + suic_clear_background(255, 0, 0, 255); + 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/test_window.sui b/test_window.sui new file mode 100644 index 0000000..6a87cfa --- /dev/null +++ b/test_window.sui @@ -0,0 +1 @@ +fn main() -> int do init_window(800, 600, "Test"); set_target_fps(60); while window_should_close() == false do begin_drawing(); clear_background(255, 0, 0, 255); end_drawing(); end; close_window(); 0 end diff --git a/tests/basic_types.c b/tests/basic_types.c new file mode 100644 index 0000000..ce4f999 --- /dev/null +++ b/tests/basic_types.c @@ -0,0 +1,49 @@ +#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) { + int x = 5; + float y = 10.500000; + bool z = true; + char* s = suic_alloc_array(NULL, sizeof(char), 6, "hello"); + return x; +} + +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/tests/basic_types.o b/tests/basic_types.o new file mode 100755 index 0000000000000000000000000000000000000000..fae5902da03d31436e2b3d6175909bac6d2d2bc3 GIT binary patch literal 39184 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 +#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) { + (true ? 1 : 0); + int i = 0; + while ((i < 5)) { + i = (i + 1); + } + return i; +} + +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/tests/fps_game.c b/tests/fps_game.c new file mode 100644 index 0000000..cd2e145 --- /dev/null +++ b/tests/fps_game.c @@ -0,0 +1,216 @@ +#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) { + suic_enable_msaa_4x(); + suic_init_window(1280, 720, suic_alloc_array(NULL, sizeof(char), 75, "Sui FPS Game - WASD to move, Mouse to look, SPACE to jump, SHIFT to sprint")); + suic_set_target_fps(60); + suic_disable_cursor(); + 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); + void* player_body = suic_ode_body_create(world); + suic_ode_body_set_position(player_body, 0.000000, 2.000000, 0.000000); + void* player_geom = suic_ode_create_box_geom(space, 0.800000, 1.600000, 0.800000); + suic_ode_geom_set_body(player_geom, player_body); + suic_ode_body_set_box_mass(player_body, 1.000000, 0.800000, 1.600000, 0.800000); + void* cube1_body = suic_ode_body_create(world); + suic_ode_body_set_position(cube1_body, 0.000000, 1.000000, -5.000000); + suic_ode_body_set_box_mass(cube1_body, 1.000000, 1.000000, 1.000000, 1.000000); + void* cube1_geom = suic_ode_create_box_geom(space, 1.000000, 1.000000, 1.000000); + suic_ode_geom_set_body(cube1_geom, cube1_body); + void* cube2_body = suic_ode_body_create(world); + suic_ode_body_set_position(cube2_body, 5.000000, 1.000000, -3.000000); + suic_ode_body_set_box_mass(cube2_body, 1.000000, 1.000000, 1.000000, 1.000000); + void* cube2_geom = suic_ode_create_box_geom(space, 1.000000, 1.000000, 1.000000); + suic_ode_geom_set_body(cube2_geom, cube2_body); + void* cube3_body = suic_ode_body_create(world); + suic_ode_body_set_position(cube3_body, -5.000000, 1.000000, -3.000000); + suic_ode_body_set_box_mass(cube3_body, 1.000000, 1.000000, 1.000000, 1.000000); + void* cube3_geom = suic_ode_create_box_geom(space, 1.000000, 1.000000, 1.000000); + suic_ode_geom_set_body(cube3_geom, cube3_body); + float forward_x = 0.000000; + float forward_y = 0.000000; + float forward_z = -1.000000; + float right_x = 1.000000; + float right_y = 0.000000; + float right_z = 0.000000; + float camera_x = 0.000000; + float camera_y = 2.000000; + float camera_z = 0.000000; + float target_x = 0.000000; + float target_y = 2.000000; + float target_z = -5.000000; + float yaw = 0.000000; + float pitch = 0.000000; + float mouse_sensitivity = 0.003000; + float cube1_x = 0.000000; + float cube1_y = 0.000000; + float cube1_z = 0.000000; + float cube2_x = 0.000000; + float cube2_y = 0.000000; + float cube2_z = 0.000000; + float cube3_x = 0.000000; + float cube3_y = 0.000000; + float cube3_z = 0.000000; + float player_x = 0.000000; + float player_y = 2.000000; + float player_z = 0.000000; + while ((suic_window_should_close() == false)) { + float delta_time = 0.016660; + float move_speed = 5.000000; + float target_vx = 0.000000; + float target_vz = 0.000000; + if ((suic_is_key_down(KEY_W) != 0)) { + target_vx = (target_vx + (forward_x * move_speed)); + target_vz = (target_vz + (forward_z * move_speed)); + } + if ((suic_is_key_down(KEY_S) != 0)) { + target_vx = (target_vx - (forward_x * move_speed)); + target_vz = (target_vz - (forward_z * move_speed)); + } + if ((suic_is_key_down(KEY_D) != 0)) { + target_vx = (target_vx + (right_x * move_speed)); + target_vz = (target_vz + (right_z * move_speed)); + } + if ((suic_is_key_down(KEY_A) != 0)) { + target_vx = (target_vx - (right_x * move_speed)); + target_vz = (target_vz - (right_z * move_speed)); + } + float current_vx = 0.000000; + float current_vy = 0.000000; + float current_vz = 0.000000; + suic_ode_body_get_linear_vel(player_body, ¤t_vx, ¤t_vy, ¤t_vz); + if ((suic_is_jump_pressed() != 0)) { + float dummy_x = 0.000000; + float current_y = 0.000000; + float dummy_z = 0.000000; + suic_ode_body_get_position(player_body, &dummy_x, ¤t_y, &dummy_z); + if ((current_y <= 1.300000)) { + current_vy = 8.000000; + } + } + suic_ode_body_set_linear_vel(player_body, target_vx, current_vy, target_vz); + suic_ode_body_get_position(player_body, &player_x, &player_y, &player_z); + if (((suic_is_key_pressed(KEY_EQUAL) != 0) || (suic_is_key_pressed(KEY_KP_ADD) != 0))) { + mouse_sensitivity = (mouse_sensitivity + 0.001000); + } + if (((suic_is_key_pressed(KEY_MINUS) != 0) || (suic_is_key_pressed(KEY_KP_SUBTRACT) != 0))) { + mouse_sensitivity = (mouse_sensitivity - 0.001000); + if ((mouse_sensitivity < 0.001000)) { + mouse_sensitivity = 0.001000; + } + } + if ((suic_is_key_pressed(KEY_F1) != 0)) { + suic_enable_cursor(); + } + float mouse_delta_x = suic_get_mouse_delta_x(); + float mouse_delta_y = suic_get_mouse_delta_y(); + yaw = (yaw + (mouse_delta_x * mouse_sensitivity)); + pitch = (pitch - (mouse_delta_y * mouse_sensitivity)); + if ((pitch > 1.500000)) { + pitch = 1.500000; + } + if ((pitch < -1.500000)) { + pitch = -1.500000; + } + suic_ode_space_collide(world, space, contactgroup); + suic_ode_world_step(world, delta_time); + suic_ode_joint_group_empty(contactgroup); + float cos_yaw = cos(yaw); + float sin_yaw = sin(yaw); + float cos_pitch = cos(pitch); + float sin_pitch = sin(pitch); + forward_x = sin_yaw; + forward_y = sin_pitch; + forward_z = -cos_yaw; + right_x = cos_yaw; + right_y = 0.000000; + right_z = sin_yaw; + camera_x = (player_x + (forward_x * 0.500000)); + camera_y = (player_y + 0.900000); + camera_z = (player_z + (forward_z * 0.500000)); + target_x = (player_x + (forward_x * 5.000000)); + target_y = (player_y + (forward_y * 5.000000)); + target_z = (player_z + (forward_z * 5.000000)); + suic_ode_body_get_position(cube1_body, &cube1_x, &cube1_y, &cube1_z); + suic_ode_body_get_position(cube2_body, &cube2_x, &cube2_y, &cube2_z); + suic_ode_body_get_position(cube3_body, &cube3_x, &cube3_y, &cube3_z); + suic_begin_drawing(); + suic_clear_background(135, 206, 235, 255); + suic_begin_mode3d(camera_x, camera_y, camera_z, target_x, target_y, target_z, 0.000000, 1.000000, 0.000000, 45.000000, 0); + suic_draw_cube(0.000000, -1.000000, 0.000000, 100.000000, 0.100000, 100.000000, 34, 139, 34, 255); + suic_draw_cube(cube1_x, cube1_y, cube1_z, 1.000000, 1.000000, 1.000000, 255, 0, 0, 255); + suic_draw_cube_wires(cube1_x, cube1_y, cube1_z, 1.000000, 1.000000, 1.000000, 0, 0, 0, 255); + suic_draw_cube(cube2_x, cube2_y, cube2_z, 1.000000, 1.000000, 1.000000, 0, 255, 0, 255); + suic_draw_cube_wires(cube2_x, cube2_y, cube2_z, 1.000000, 1.000000, 1.000000, 0, 0, 0, 255); + suic_draw_cube(cube3_x, cube3_y, cube3_z, 1.000000, 1.000000, 1.000000, 0, 0, 255, 255); + suic_draw_cube_wires(cube3_x, cube3_y, cube3_z, 1.000000, 1.000000, 1.000000, 0, 0, 0, 255); + suic_rl_push_matrix(); + suic_rl_translate_f(player_x, player_y, player_z); + suic_rl_rotate_f(((-yaw * 180.000000) / 3.141590), 0.000000, 1.000000, 0.000000); + suic_draw_cube(0.000000, 0.000000, 0.000000, 0.800000, 1.600000, 0.800000, 255, 255, 0, 255); + suic_draw_cube_wires(0.000000, 0.000000, 0.000000, 0.800000, 1.600000, 0.800000, 0, 0, 0, 255); + suic_rl_pop_matrix(); + suic_end_mode3d(); + suic_end_drawing(); + } + suic_ode_geom_destroy(cube3_geom); + suic_ode_body_destroy(cube3_body); + suic_ode_geom_destroy(cube2_geom); + suic_ode_body_destroy(cube2_body); + suic_ode_geom_destroy(cube1_geom); + suic_ode_body_destroy(cube1_body); + suic_ode_geom_destroy(player_geom); + suic_ode_body_destroy(player_body); + 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(); + 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/tests/fps_game.o b/tests/fps_game.o new file mode 100755 index 0000000000000000000000000000000000000000..3b3e29a740e3e5419be5940a406784cdadd0c9d6 GIT binary patch literal 49432 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

o#WMeHw= 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 QD$b@|3Z9mukb_$P3kb&wVE_OC literal 0 HcmV?d00001 diff --git a/tests/fps_game.sui b/tests/fps_game.sui new file mode 100644 index 0000000..4ca9474 --- /dev/null +++ b/tests/fps_game.sui @@ -0,0 +1,271 @@ +# FPS-Style 3D Game with Sui Language +# Demonstrates WASD movement, mouse look, jumping, sprinting, and physics-based gameplay + +fn main() -> int do + # Enable antialiasing + enable_msaa_4x() + + # Initialize graphics + init_window(1280, 720, "Sui FPS Game - WASD to move, Mouse to look, SPACE to jump, SHIFT to sprint") + defer close_window() + set_target_fps(60) + + # Hide cursor and capture mouse for FPS controls + disable_cursor() + + # Initialize physics + ode_init() + defer ode_close() + + # Create physics world + 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 + ode_world_set_gravity(world, 0.0, -9.81, 0.0) + + # Create contact joint group + let contactgroup = ode_joint_group_create(0) + defer ode_joint_group_destroy(contactgroup) + + # Create ground plane + let ground_geom = ode_create_plane_geom(space, 0.0, 1.0, 0.0, 0.0) + defer ode_geom_destroy(ground_geom) + + # Create player physics body (capsule shape) + let player_body = ode_body_create(world) + defer ode_body_destroy(player_body) + ode_body_set_position(player_body, 0.0, 2.0, 0.0) + + # Create box geometry for player (0.8 x 1.6 x 0.8) + let player_geom = ode_create_box_geom(space, 0.8, 1.6, 0.8) + defer ode_geom_destroy(player_geom) + ode_geom_set_body(player_geom, player_body) + + # Set player mass (box with density 1.0) + ode_body_set_box_mass(player_body, 1.0, 0.8, 1.6, 0.8) + + # Create cube physics bodies + let cube1_body = ode_body_create(world) + defer ode_body_destroy(cube1_body) + ode_body_set_position(cube1_body, 0.0, 1.0, -5.0) + ode_body_set_box_mass(cube1_body, 1.0, 1.0, 1.0, 1.0) + let cube1_geom = ode_create_box_geom(space, 1.0, 1.0, 1.0) + defer ode_geom_destroy(cube1_geom) + ode_geom_set_body(cube1_geom, cube1_body) + + let cube2_body = ode_body_create(world) + defer ode_body_destroy(cube2_body) + ode_body_set_position(cube2_body, 5.0, 1.0, -3.0) + ode_body_set_box_mass(cube2_body, 1.0, 1.0, 1.0, 1.0) + let cube2_geom = ode_create_box_geom(space, 1.0, 1.0, 1.0) + defer ode_geom_destroy(cube2_geom) + ode_geom_set_body(cube2_geom, cube2_body) + + let cube3_body = ode_body_create(world) + defer ode_body_destroy(cube3_body) + ode_body_set_position(cube3_body, -5.0, 1.0, -3.0) + ode_body_set_box_mass(cube3_body, 1.0, 1.0, 1.0, 1.0) + let cube3_geom = ode_create_box_geom(space, 1.0, 1.0, 1.0) + defer ode_geom_destroy(cube3_geom) + ode_geom_set_body(cube3_geom, cube3_body) + + # Set player movement direction (looking down -Z axis) + let mut forward_x = 0.0 + let mut forward_y = 0.0 + let mut forward_z = -1.0 + let mut right_x = 1.0 + let mut right_y = 0.0 + let mut right_z = 0.0 + + # ==== CAMERA AND PLAYER STATE ==== + let mut camera_x = 0.0 + let mut camera_y = 2.0 + let mut camera_z = 0.0 + let mut target_x = 0.0 + let mut target_y = 2.0 + let mut target_z = -5.0 + + # Mouse look state + let mut yaw = 0.0 + let mut pitch = 0.0 + let mut mouse_sensitivity = 0.003 + + # Cube position variables + let mut cube1_x = 0.0 + let mut cube1_y = 0.0 + let mut cube1_z = 0.0 + let mut cube2_x = 0.0 + let mut cube2_y = 0.0 + let mut cube2_z = 0.0 + let mut cube3_x = 0.0 + let mut cube3_y = 0.0 + let mut cube3_z = 0.0 + + # Player position (initial values) + let mut player_x = 0.0 + let mut player_y = 2.0 + let mut player_z = 0.0 + + # Main game loop + while window_should_close() == false do + # Input handling + let delta_time = 0.01666 # ~60 FPS + + # WASD movement - set velocities on physics body + let move_speed = 5.0 # Velocity applied to body + let mut target_vx = 0.0 + let mut target_vz = 0.0 + + if is_key_down(KEY_W) != 0 do + target_vx = target_vx + forward_x * move_speed + target_vz = target_vz + forward_z * move_speed + end + + if is_key_down(KEY_S) != 0 do + target_vx = target_vx - forward_x * move_speed + target_vz = target_vz - forward_z * move_speed + end + + if is_key_down(KEY_D) != 0 do + target_vx = target_vx + right_x * move_speed + target_vz = target_vz + right_z * move_speed + end + + if is_key_down(KEY_A) != 0 do + target_vx = target_vx - right_x * move_speed + target_vz = target_vz - right_z * move_speed + end + + # Get current velocity for Y (preserve gravity) + let mut current_vx = 0.0 + let mut current_vy = 0.0 + let mut current_vz = 0.0 + ode_body_get_linear_vel(player_body, ¤t_vx, ¤t_vy, ¤t_vz) + + # Jump - set upward velocity + if is_jump_pressed() != 0 do + # Get current position to check if on ground + let mut dummy_x = 0.0 + let mut current_y = 0.0 + let mut dummy_z = 0.0 + ode_body_get_position(player_body, &dummy_x, ¤t_y, &dummy_z) + if current_y <= 1.3 do # On ground (box bottom is at y - 0.8 from center) + current_vy = 8.0 # Jump velocity + end + end + + # Set new velocity (keep Y velocity for gravity/jumping) + ode_body_set_linear_vel(player_body, target_vx, current_vy, target_vz) + + # Get player position from physics body + ode_body_get_position(player_body, &player_x, &player_y, &player_z) + + # Adjust mouse sensitivity + if is_key_pressed(KEY_EQUAL) != 0 or is_key_pressed(KEY_KP_ADD) != 0 do # + key + mouse_sensitivity = mouse_sensitivity + 0.001 + end + if is_key_pressed(KEY_MINUS) != 0 or is_key_pressed(KEY_KP_SUBTRACT) != 0 do # - key + mouse_sensitivity = mouse_sensitivity - 0.001 + if mouse_sensitivity < 0.001 do + mouse_sensitivity = 0.001 # Minimum sensitivity + end + end + + # Show cursor with F1 (useful for debugging) + if is_key_pressed(KEY_F1) != 0 do + enable_cursor() + end + + # Mouse look + let mouse_delta_x = get_mouse_delta_x() + let mouse_delta_y = get_mouse_delta_y() + + yaw = yaw + (mouse_delta_x * mouse_sensitivity) + pitch = pitch - (mouse_delta_y * mouse_sensitivity) # Negate Y for natural FPS controls + + # Clamp pitch to prevent flipping + if pitch > 1.5 do + pitch = 1.5 + end + if pitch < -1.5 do + pitch = -1.5 + end + + # Update physics (just for cubes) + ode_space_collide(world, space, contactgroup) + ode_world_step(world, delta_time) + ode_joint_group_empty(contactgroup) + + # Calculate camera direction from yaw and pitch + let cos_yaw = cos(yaw) + let sin_yaw = sin(yaw) + let cos_pitch = cos(pitch) + let sin_pitch = sin(pitch) + + # Update forward and right vectors + forward_x = sin_yaw + forward_y = sin_pitch + forward_z = -cos_yaw + + right_x = cos_yaw + right_y = 0.0 + right_z = sin_yaw + + # Direction vectors are updated above + + # Camera follows player (at eye position, slightly in front) + camera_x = player_x + forward_x * 0.5 # Offset forward + camera_y = player_y + 0.9 # Eye height + camera_z = player_z + forward_z * 0.5 # Offset forward + + # Camera looks where player is looking + target_x = player_x + forward_x * 5.0 + target_y = player_y + forward_y * 5.0 + target_z = player_z + forward_z * 5.0 + + # Player rotation is handled visually during rendering + + # Get cube positions from physics bodies + ode_body_get_position(cube1_body, &cube1_x, &cube1_y, &cube1_z) + ode_body_get_position(cube2_body, &cube2_x, &cube2_y, &cube2_z) + ode_body_get_position(cube3_body, &cube3_x, &cube3_y, &cube3_z) + + # ==== RENDERING ==== + begin_drawing() + clear_background(135, 206, 235, 255) # Sky blue + + # 3D mode with calculated camera + begin_mode3d(camera_x, camera_y, camera_z, target_x, target_y, target_z, 0.0, 1.0, 0.0, 45.0, 0) + + # Draw ground plane + draw_cube(0.0, -1.0, 0.0, 100.0, 0.1, 100.0, 34, 139, 34, 255) # Green ground + + # Draw cubes + draw_cube(cube1_x, cube1_y, cube1_z, 1.0, 1.0, 1.0, 255, 0, 0, 255) # Red + draw_cube_wires(cube1_x, cube1_y, cube1_z, 1.0, 1.0, 1.0, 0, 0, 0, 255) + + draw_cube(cube2_x, cube2_y, cube2_z, 1.0, 1.0, 1.0, 0, 255, 0, 255) # Green + draw_cube_wires(cube2_x, cube2_y, cube2_z, 1.0, 1.0, 1.0, 0, 0, 0, 255) + + draw_cube(cube3_x, cube3_y, cube3_z, 1.0, 1.0, 1.0, 0, 0, 255, 255) # Blue + draw_cube_wires(cube3_x, cube3_y, cube3_z, 1.0, 1.0, 1.0, 0, 0, 0, 255) + + # Draw player model with rotation (yellow cube to represent the player) + rl_push_matrix() + rl_translate_f(player_x, player_y, player_z) + rl_rotate_f(-yaw * 180.0 / 3.14159, 0.0, 1.0, 0.0) # Convert radians to degrees for Y-axis rotation, negate for correct direction + draw_cube(0.0, 0.0, 0.0, 0.8, 1.6, 0.8, 255, 255, 0, 255) # Yellow player + draw_cube_wires(0.0, 0.0, 0.0, 0.8, 1.6, 0.8, 0, 0, 0, 255) + rl_pop_matrix() + + end_mode3d() + + end_drawing() + end + + 0 +end diff --git a/tests/functions.c b/tests/functions.c new file mode 100644 index 0000000..08378bb --- /dev/null +++ b/tests/functions.c @@ -0,0 +1,52 @@ +#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 add(int x, int y); +int suic_main(void); + + +int add(int x, int y) { + return (x + y); +} + +int suic_main(void) { + int sum = add(5, 3); + struct T id = identity(42); + return sum; +} + +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/tests/game_3d_improved.c b/tests/game_3d_improved.c new file mode 100644 index 0000000..6ab3df2 --- /dev/null +++ b/tests/game_3d_improved.c @@ -0,0 +1,89 @@ +#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) { + suic_init_window(800, 600, suic_alloc_array(NULL, sizeof(char), 27, "3D Physics Game - Improved")); + suic_set_target_fps(60); + suic_ode_init(); + void* world = suic_ode_world_create(); + void* null_space = (struct unit**) 0; + 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* body = suic_ode_body_create(world); + suic_ode_body_set_box_mass(body, 1.000000, 1.000000, 1.000000, 1.000000); + suic_ode_body_set_position(body, 0.000000, 5.000000, 0.000000); + void* geom = suic_ode_create_box_geom(space, 1.000000, 1.000000, 1.000000); + suic_ode_geom_set_body(geom, body); + void* ground_geom = suic_ode_create_plane_geom(space, 0.000000, 1.000000, 0.000000, 0.000000); + float camera_pos_x = 0.000000; + float camera_pos_y = 2.000000; + float camera_pos_z = 10.000000; + float cube_x = 0.000000; + float cube_y = 0.000000; + float cube_z = 0.000000; + int frame_count = 0; + while ((suic_window_should_close() == false)) { + suic_ode_space_collide(world, space, contactgroup); + suic_ode_world_step(world, (1.000000 / 60.000000)); + suic_ode_joint_group_empty(contactgroup); + suic_ode_body_get_position(body, &cube_x, &cube_y, &cube_z); + suic_begin_drawing(); + suic_clear_background(135, 206, 235, 255); + suic_begin_mode3d(camera_pos_x, camera_pos_y, camera_pos_z, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 45.000000, 0); + suic_draw_cube(0.000000, -1.000000, 0.000000, 20.000000, 0.100000, 20.000000, 34, 139, 34, 255); + suic_draw_cube(cube_x, cube_y, cube_z, 1.000000, 1.000000, 1.000000, 255, 0, 0, 255); + suic_draw_cube_wires(cube_x, cube_y, cube_z, 1.000000, 1.000000, 1.000000, 0, 0, 0, 255); + suic_end_mode3d(); + suic_end_drawing(); + frame_count = (frame_count + 1); + } + suic_ode_geom_destroy(ground_geom); + suic_ode_geom_destroy(geom); + suic_ode_body_destroy(body); + suic_ode_joint_group_destroy(contactgroup); + suic_ode_space_destroy(space); + suic_ode_world_destroy(world); + suic_ode_close(); + 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/tests/game_3d_improved.o b/tests/game_3d_improved.o new file mode 100755 index 0000000000000000000000000000000000000000..e857ff8cdfa016ffb5b26de990bce2d7551f09e5 GIT binary patch literal 45248 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 +#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) { + suic_ode_init(); + void* world = suic_ode_world_create(); + suic_ode_world_set_gravity(world, 0.000000, -9.810000, 0.000000); + suic_ode_world_step(world, 0.016000); + 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/tests/ode_test.o b/tests/ode_test.o new file mode 100755 index 0000000000000000000000000000000000000000..05894694b2df46817f65d31f6cde754587d9f56f GIT binary patch literal 45240 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 M;$wLQ@=)V{18%)DkN^Mx literal 0 HcmV?d00001 diff --git a/tests/ode_voxel_example.c b/tests/ode_voxel_example.c new file mode 100644 index 0000000..796d3ed --- /dev/null +++ b/tests/ode_voxel_example.c @@ -0,0 +1,64 @@ +#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) { + suic_ode_init(); + void* world = suic_ode_world_create(); + void* space = suic_ode_simple_space_create(NULL); + suic_ode_world_set_gravity(world, 0.000000, -9.810000, 0.000000); + void* body = suic_ode_body_create(world); + suic_ode_body_set_box_mass(body, 1.000000, 1.000000, 1.000000, 1.000000); + suic_ode_body_set_position(body, 0.000000, 5.000000, 0.000000); + void* geom = suic_ode_create_box_geom(space, 1.000000, 1.000000, 1.000000); + suic_ode_geom_set_body(geom, body); + int i = 0; + while ((i < 10)) { + suic_ode_world_step(world, 0.016000); + i = (i + 1); + } + suic_ode_geom_destroy(geom); + suic_ode_body_destroy(body); + 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/tests/ode_voxel_example.o b/tests/ode_voxel_example.o new file mode 100755 index 0000000000000000000000000000000000000000..850967d885f646f008744bbe1a86d98f78e32e1b GIT binary patch literal 45248 zcmeHw4SZD9weLwF7!;fdLdB2jXwe3X7!VQsr~_oeL5T)PfKur&$xM>b$xJ#Qe0Zgz z5t=blQ?FXuTFbT6Qmd9{QK{PNfJ&lLZ>knki#1isoe{LDQX4IG-hb`A_L)7C9NPPC z-~0XU`*HYX)?Ocb?X}lld+m=i2{(D>R}~i(8R{8ke9<7xb&jOCnc@C17XaMG4C6$6 zo?(2}7y*2^ph>=40&wNy9F`ADnNDP?x1ITg@N||_P+3Tj>e)Rtr%H~3hEw8HuY`&& z`oQB7pB9`sP2vjb^+bCsSiS&upCsuD>h;Jso7YPI=8gGK8e|w_ z9%{D&KNM?oudXwS*BL3IDSnYrB=C`-(NoO0;*;!H{7`qO{`DKqd7|W(CmcWf_Ny-{ znKXU!mZdX(azQ9qKYiK-A^-WIU^ub*{M9q2pFe%te zq1W5!|GAC)M>h6%*!bsV8~L3!^xxU&X|SPJ+0Z|4W53Ua{*jIUAF;9X6dU>HZ0y-$ z(=M&wF8mZer`e3lS{r+QU}Mh=n|47SvfW8G^h2Nzl}}!=p*w8s`MyoRerqHDFOV-Y zPBAv$iH7i~{gvVMHnl{;-dNlhjeEU@cV2C^*B^)mnu4)-AX-~JClm<>YJK&gfaDFy znGNx9b;KXIu+l(Nx@`oNMP8Zn}w znn-K4FCGo9Hs%K6LP2F96!#gPu%B&|RxFAn!hS>8PAY=oCRAP+iTmP#MrpOxq*7E9 zi3Q`qNZ42s4ErOi7Bxo_A;0Lcu_zF)^+lTk@v53dvUX);RoIwsb=MOnFUl@kHs^Oy zd8slO(_~3SZD4gg5e-yDBQ4T-Xl_m<+!$=C3i+C1LLbWr|493&%c^UnMfOIhkL`%S^3HjDYA-FLSYtH#`QA0Ek2-ilIM4}=8Lf;zEG1cN6j7)U4ui^TpsPL)u zui{2SwNYO<77~7iCsBJ&Boqq9;K(VL|Py@JAxqaizXMv1FeRi2%uZT z;GYu>KrLxuu|Rxo)VDGiM?F$f8HmNB5v9b!7Pa~s0v1MsaD;4)K7q^+hS8_Rfso;+ zc)O<3WB9L(1jF%J@wl&{+3;8UVlhz(O$&9RPyT>3QracUkSa77ehx!Yj6_bgtb}1j z3vsKn3livIG)z$^Etm@@w_3&v?-Vpgwm~~NnG6zki&{!o6p&^M4_d8h{U%RX z&9GaBHpbJ^3Ws|si!@yCZD_vU+vp31j7Efv(c%k*A`M{T^wPk2ro|Tw8?iX@OcacU z)jn@yFzgEjZwMF-QoJS5($KobXj~Ny#sh}0J`#-^P!RR4!6zMgF1o0K2*^2v&7g7% zm8MgvL6+vupErAsck1M6hAK_T6)(&cr%t|zaw5)X|L{MY->iSCEa5Pm1#>)ED#@ed z%NNQX9jCfT@%S8Wyo#Kz&aGpE!O?X3e3NN+ee)h11BV;`$@q4G4>LYsJaK9eN6}*A zZ@}qM_Y`VfaGopaTlpSB(Nlasw60(sQF!VOS&z=3C(EMv?AGWLGi&3(Lblrof@5|y5Nr2=$sk^-KEh#ujwh*=;a!{LZeUA=rc6>c^ciV(Z8V4 zO^r@_ZS~Y>^z#)FaH&S0tkG9!^b0h4vqrDb=&c%kibh|p(Wh$kbsGIbjoz-&`3hQa zJ2kpkl(^0&jXqt|vst5GtkJh>^cfm`n?|3h(RXO{OEh{)qhG4gyEXb{8ofuOU#`)6 zHToAddY?wWLZhcOx?7|7YxG$feL$nn*60SWQxyMmGqtDmqrbe&U=rtO>Mx!s)=nFLZ3XQ%{qc>~xMH;9e8(*^6ET zIeX3?d^*l_qeOT!@iKi`Jm>5poQ_nP9)UkeI31-jDS+a zgwv5J(<$)p5Kc#>%sPSJNjNRrnO1?{MmQafGAjgr3*mGm%G3z_2EyqmlyM6@N;n;X zG8F>9j&M5qWLyHTC!CHv8K=OP5l%;)j3MxaggXfD{}hCCt|Z(^c%Q&$6JADmkH9Y> zd<@|!flnozjxd>R0zZ#%I=W;w3;b-t>By4l6!@ux(@`a}PT*q*rz3QxRp7@HPDhr^ z3V|0BPDhnYjle$%1E(WO#x3v<2&bb-rb6KF5>7{wj7#8e6HZ5wj8oum5Kc#sj3Mw> z2&bb*rvGo${}%~&5#A^8U4+w7Bhw@BCkdw`MkXcjM+v8+MP{48A0(WP{+Z1Jzn^eA zVq`i6{vE>UXpvbb@H+{oBSofF;I|P@M~Tb|f!{(n9U(F`0>6Q9Iyz+B0*?|-M}|y= zz^@~mjtUuqB0aN6Q$It6|z;k32StP}Vc!f8vNX%+bKgws|&vqIp- zgwqy2QzP(CT7c8mJ>wSm2ZYm>JyRj@cL}Ghdd4O2w+W{$dd4a6HwdS#dBzaXQ zJk$SIG5&=}d*duOpnc z&>5G&>j|$W+$r#7gkMd#0i5#Vl=tQ(fAtkJ`L@}%zrUu|GbJ_U1#{!&pCHL)$F*H& z7>64tJI=fnRgge8UOo>B%#9_p3CtXbk3(v0gb=0Hk=Z`Snd?aIS%#25MaW+?hQP#6 z&1Ap1^ZhH#odd(nqTS}NK8=rsf{R!|X|}J?aVET{>XUuzE`Kuwm5B@M%(lzl4Wei! z{}3N-c3gfR=-F|-Af+2HcDqZqgHW{m*_^%5<2D*|IO)qYLADM$urO4Z$+c-Sndmc< zb-iY?y2tGB^qG#IdVuUg8N9t_vMW7v61D0XFx%Gl81Xanr9`a(Gx;(}z5%a-J@CS_ zLpIS-*Qcp{8xxn+_8Re%O~I}1rTVO{W01P^Dagj@T6~~p-!tUxbT1Mvu=EEGXGs|* z3)$D`_~R>$j`D7^W84Uk8cj!d7a2I0YEmyzenM*LN4;?wOgg~Pzn8G&H-M=7iU6K| zsColGzao{EuANv2sLjVLA*;IN3{sepC6GBdw#{>-sH3Ffq~XR)&ygGd zZ3p5%%gweOa)~L>wl-}fjuV|fc#(9_ZW&u&oXBI*wsycsjDr=gBYm66lJuD2(pv|I zqk;kGS zoJ?R!P&Cx_cT^9M(90OY(+9HI^y{BwvyR78>r;-qQ*Hf4D7N(#$-zl~7Xqv({Zq(U z-6ox+r7Jz-V~9xcXIwBP-9!W_n7-;Sxw0dt3#r37D>;z-OLA}W#meN)_Ua?akK3yU zl7DKiKHOf{e;da4@w$Qb*YJ6G=iAP6vRNZLvIkiI&bP+{%Niql(Dsp!thS+Y1%_fP zeCed<8BbB2N`D)xv=(AJD2P&!Ih|xCNSQ>w%yT5O2QuX(Qz2y*uAl4qMDvP zRHEu0Snm{#dtRdwDUzMpOr?E9b5e<>p=Ugm_IG&hMS_$mzYl$d50`hNzh-hNdP^yM zc`y3r1U?@4KH&R-pALLN`gueF4hb=|jlC`x)ntnA5)mF`@uP)A6;OdiyRXMkwbkmm?W%X{%rC%TUA zQO0p1Cc7Nv?;vqI%6ljZcBQY)i?{zFM*k?!=-kA;=7Vfj1{_UCYd)7kdcQQwkfAQaG~}DH`@-E{*!0ae8JD@%}!b~m(11%)0oatZwQRG2N{R6w* zJM#oiJ#{FV3#I)(~I8Fnv>U?6J>9Dt=@=M z3tDtM?kUGE0G%3x`n}i&ryONQqhqhzdGK0uBewd~Rng7gLjbO;Lywg=UBa8mzochl z%#re4|L4}Oz>t##mbLJq^1Yk72H%f`nbVHyd$^uFf71K9=f^6~Q@$w29yOUr%bm!7 z(5kY(y{@k^xvRZyU-Faox?Zd<6K;JazW6rJeiZw}LbES#q3O*nG#!a_2ll*{kKRU9 zz(>pBqvOrwveJ%fSMo|{a##ABY*A+}d!_$&2-`6;H}xKd3{O3>bSWIL6+yCDAF{Lv z`)wG8%^W1hy+=XPqk=^2JHTJQBez_qfMNov<(lHF#s!~lMc9-Bru9kiI#~){&QLO@ z6oE1W?!T1#T5cv0iK?%qyf1*#<=|KiA>wLW>APuY^Y;THb5lM!#Cm6U)G0UqL#nHx z+N4ChD_sRQ4y7LM!wv>J_4q>SBjTqV9jFo=01k+jFkqOl*wo1JGCN><2lg}=HH;rJ zgc~tF+m-%3yiARdrrqvxqci88S+&%gRy5a+dE;3(Xt?UOfe(BCzQd{~LG3j3Ol+jg z^6WaSh`VwN<@~eyurSU`ip}4xYPGCHmju<^Sl5|r_vjH(js5TP*HpWW z^BiI9WnWJpdDm*Zr4tqe?!w3NP57w07a!G|@!{D5m$YLjDUb-R7|sRSDGEx>C@zq1 z1;tItDlh7MG>BlD8w34co^`EUjL`9QuA6Q)vd3L~EB(={clBT!vG|r&I`!)?tpR zRG1Q}(BdLK>Ne%Ln5?uY{3SgvBV9^+ShSIN4IeGN_@J$?lQzLl+77F&5xJyYd977> zwpn?0h4SoDB~wG5rC~5>b)$kCXaD?#;m_u&JRldm!c-F2J-+jF`^YeJXQfa^7R1tRwE)b?*+T!FkY>vu3~ zsMW@@du?9b|DN67{7>DE|DLYr)4DDsmV!$;k@ITN%`|!7N06rd5_KEC#f{Rk6v~LS zGDEncEmf+~5sMbxsnHRwWojKYZ$6Yl0GP>NG-JaK|F5UFFMu1DN_cmTgx@m(3udp` zCTbb+rO@=C6`boyf!T34=`%O3Zv{XI48BTx^Z@biCcfFRo~+>2a3sYVbxU8; zhNrcW9?JKy;O_-q4O+CKg?wHZ!|49pahy;~7&fJ+ECNCFp-;JHBxzSwRfwjFO(N12N zwS#m~-xCcJ8u64E|n22kjUFUoDG*3 zY#k1{F-d#rkcA-b9+ZUW&BP2DmQw)mLg73pg*=_G5VyFYFgK3N;H{Urv6@IwBaB`0 z_7EB7e)J$Wm#xc{6JULgOi2Sx;V@~<+Bg30yxvO9NgeR1Na6HRR`U8nYYEP0?6zY( zmSf0`;ZfI(JNm?+44~_1@1L`7w248%vV?Obze1WXlLU6@A+!WmSNi$4{&_8v^_XAd zwH|cqE1A4T?j{eW@KL=3A9dUCv3%>`kU zHVrV@U76fnnS7!B?h0V->n9PdzkPkV;I*%x09equXXsWXJzgYnxt#JUoj6`x%w_0T zL$T6I>$=kSQ*dY{OP6V%C=DH`Qt%SZ{GE^&dZ^P%4>6I8IMFCogl}&c(T#?SXs#A%O5_x@d{+q(2S76fJY^pGu zO%>f2raJ!k9%LS-u_LqJHIK6M*#V_iQ+Ty3_dv42QDRhtK{!IJC*6n{w=#`r94~YL zv*b8-+~b+%cw7cf4NeY12n33u_L|S;2oy~1HD}}q6jkjtXELG7?LtIR$cPx}sG|+p zSaErWi?$g2KU7|<6w_4>LmXz)u9e)`mHw*e8sXvP(+^fHgaQm5jhuq$k>=iFblh2Am))t2(uD0*nJ(gv!H-jnkR^07z<;=PZkf!rVws_7oCFkFa~VakIiXJeV0HcJ*lNx?$M zl@>w{wh+4WNTWX`Nqkw3G`bYwMkY+q#mjYMk`k?B(F#Q{nJ`TeE@r|EML3TMml2`M z?M5Vtep<;6$!yRj@B<_;bw{BRmPk{MTRUZaBr&JBJfnj9vJV|!qLj9j0uvOG;l&G1 z@|zGDRVYGM2rcAjA%gHL(4tskdoE1rZLZ=P@%5=-b*u1t~DkGd+t)Ktz9C@N{V)r}!d0rJgZeB`al6IrF;D1Ab? zP>M?OwZ6MF7lQ+4N6D5y4#T(WJOfcAgp%(w5<6}O&Ax*rVzb5<%G8sNl6!UeZ~cAw z5Q$(5V@||(!g|b&ompBT)~8H|xeM=jN9HMSa^PD$8*6ZPG45I_wxy0YH;#IqJcE4f}@+y>vZN^6`miqNC&k0{OM> zP_@YLwq0bzui1z=v0%W#F=m@*pa}IJrTXN-b?WAwzv)CLHOyaHC7;47iJ+MRypQmI zk@#7P{}QdDVn;J>k?Lhp&u*h|T9AB)kxW6h-|QH7vXt$oi;#}dMFJalJb|JY&6&Gm z=fJ#Sc=L@fNA`#>;O%^pz99YYG`Q(2_u>`WIj_>HRPyqB)GOK|(j9Ph8tuT%;>;cs z65}2s3HoXqno5@3Co%O^Ecx}uUIcfqwPwAKHc+9Ly8AS~5`^xLBs@c&RE(HlBqZZ$ z#o$dWzIaJXxw|xTKXV*UxQ92k4HT_BTPb+UavX_bw30O!&6uA|c+Gtf4gDZ+5v$VUX+uIZU?MFEbeJ ztI9D=sRgp$3BRTryF3RFp$mlmj+#=(6P^QT$MLv<*J>4xC+hGX9MTQ1Aliz}j>;ZL zEI&Z5yO%mhui+bBGTU|*o5{)-MeVj!QDYKHV6fu}qj9F^K=l63&b$pqE4uybgVgPk zy#%^Eo5<{gm!Q(7f{6bf3DEcbcw0@|KD2&@Y#nYbM!0XHaDVm$5$>C!KZnB2q%iY1 zKH$J_3mu-#s$-5@za<&#a*W+1S+YbB@EUgK+ara$#l=ydSwg>x4->XR=2DWm)U!2q z0+7js2s+Il&$ffKjo5|~#?m8aL|b~ixMdVGL(aMuVLkJUAWwCmGP(=-8U5Kz{WOs985lXo>XmoqXLnCDyl3(Q60R=&+aYytSAeB;E z3dMP%STdCWUFIfBE*8a-8Ip09#Ks5=?YkgF?RNuqYeCm7Y>{ofml4+Qh`!ocu!4$< zB1$*7!GV%~3{Z-MDS$<~cu-*Do+TjDMM-)W<|8cq7SUuR^e1T>K9F?MXJeNecg$QG zAxoNJ17dO|YalzWR%O@H`mekKN^(09hE~&pxlZKML1UgDymsqdFelM}NCH4-1o#~N~PUrX{HIfPQUlt}j zPpqzz7fbWr+d*}R7?7*|58<&EMm-W;$>?;6-o)tVfnw#depkr)?I8H#*mKMS$2@S% z1IIjY%mc?faLfb8JaEhd$2{;q#sl)N$Qj0&>kls2ao^`s`G)t?@BQK#>pt@1KfO|2 z-+9H{IWF;s`F!-(FJ1K4{qTo4ua3Cz7yKeoDU8p)E57q>dVY@j>+oB0>i{>qad4XT z?4M8HId{$_u1Lu5Y6^s1k(GgHV<@ufc+@I7ZP=yVIA5(s`L1WO*&`_5^;|Z)A8_OI z+3W-yX8Hju0k7DN7utXici|T*0AB^%0(eSyHv1f4C*Xd--vbUWF^ofi697+q0rdf0 zfPTOW0dECt1>6F7Bj9s@UkBU|_;dZv`}Po3|A(@H+YpxE?SK_(QGc#-oEU^(C(z*&HY0G9!d!f(s= z08Rp|$NRDQfbRl^0N=s4hi(VF9B&040(=l~58wrVKz+b_0Y~ABX=mZ92a^E5k8f4f z0QRKecfbz-I|09!!MFi_4quY(0ek|mAMh%Ck=2R2)2{%T zKLT9q+A!{&V1Cn&tR&bNnOVZv)@X{?l<= z`d#qH>-87q>R$%_zk-i2%;}fzk>d~ktw(A9M(|sY!oL^%Yr&`AwzK+IEFB=mAN)JO ze<_c@TNvm9Z6ElT(7L4aJ#E8^-^lfW{sWIsAYq`H;t%WGW#u3VpDXAwSVy68a)!M7~jT;hLNu+QFX+zFn+s1^>LG)b9rWjHA>~ zgZ~-uuhsieyu=#EQslCQ;M>i$a_~Jz;p5$cF#~+NIBEue!cq9`;8UE~&Bd+Y{}tn4 zr@tHg|2zsm4gRa(<4+dk;_$0E|CeG9lmUN^&i`7DUk*Nv@eMk^IAQtE1iumdrFndr zEX4SOe;@cO^Z3#L;JvZw3Dr>>cxBtayRoyHKYa{2kzbL$6P9dTXu^ zhaht{_LpKIQ!#i|jz0?fxG~@lxnvE>mP~Qn^1-d( zuK?d}joSkL67cQ%@ErJGItqV3_+JM96utf0oR5Yhcx#Wsp8$UKQTUbMSAlPr+x+0) z3;vyY`^6h`{RjU~!d%%C}DEvd315eTr=#j6-WKx&%{~(2fB{p`z#xrIMY83{?0u9(-yx1{N=bC7;2wHRj|zz|HlJ0 zPya6t2aYa5Z39xk+&m^(A#`{yoH*b`M(-_Bfhj_$!9wqhvfzke(9>xFjr`ZVM zJ-8pH2iJq*DdmQ7RVJPR=Hm!0o{=nwBc*u6eJx7k7*~L+8RVqos28Hdzp@F4e_Y<|C*Kk0a1v4%6Lk=oWNgKW?YR!KjUMV|1smr zZdU*Q9H{?4zOdoxE=j3kxR_xh!<7s-FuaH10}LN$xSQc#h6fma#Bjt}hIl^1@LYz| z8CEe|%&?K+N`@O4-ox+#hL1Dc&2TTn0}MZ6I6@roaaYgqT!zybRxw=6u#w?Ph8q~( z!|(xyk2BoOa4*9H3_oHx;&a@8hUYSz&ajH%VupeTL^UoX)U{;bMl33|BJT!0;Z14={Y3;ckX|86IHx5yKJZaQh4;hI>kJdBs@! zvu^plk<1l;YJR8vv4Q`MU$sap5mHXG4-M;Q>IK+8is~NAP+bG zlr7{^J}Jhp&Yp6vDMrw?ktAV<6(JkxfHBoc{-UFA&aKCU+aE6OmKos zcV9MK;PMl93P`{tZ!%rwqZ=Sa_WY3buM)NJJqOlPQ=sQwrq>qGr{Z3s$QW<5vpq`x z38G#6fyx5<_gH>Y0sSGiCwr+hMBK}w_#}RY@=q7&)UOq6&r%l%cwWR0_3PpJ0yV^) z6N;}g{mlaU8%!TvE#=Rb!1x2xmt8Fh;_e5%=GL9lEB*m zV`TBremKpBK3UL58^x?gt@l?jykkkFxy4E2ZEDmVce;8J>4@nEsAUyC2!mvo`e6CDNYR9RF%x zK7r{su%DHGE@Jxg91ksQk4MlM(ZCWLdIRWX#pCn$C#cuT`cLNk@EGe_Z=u|86}*SaNLP5TQ3osH0do9M+S z8tQzgSXHd&-*_IW7{1m<&l;BhDaVhBx9>6ig-WSejn`95UtEwkUS)a%_lwmTe_{HD zsZx*1Gb4|a{VlJO^!40<&olk@>5?G6$AIEYrtjl;Q*l+z^bx$TsAWB05p+g0(8}^_ z3i3k-(^t-t!s6X4ia)Z^^C-(ty-3Q7?_{9(yp8RO#PWyPez;dWSJ}wVDn`4-kaDpggGL+q zm<|0VZug;yQo%{A=T6WmPZsWr?qm5V$Dx|<4-0y}ErdO3L+@riFK~ZVyKgeRm*eLV zR{3WeJ;le9{|7$~K}SBECwVH5O=kLcCQ7=hdxec2`cAx((OX&0dg|FuwSSHN~Bh+pH<>3W3diLZh zcP^H{+eV&#=YaO}h5O#eY~<;86KMW!;Qhu%*551ioMP;_78@AtdDBMEyR7G(g7Ny4 z=@DKBm$9ysF+fAb6@7Px>^XrGj2g#_nf^P@!>rDzvC;Dt8~XJ&^i{0C>xq!Z^)*u&OvZ24pdQ2X7 zgp+vQXZpUW68{F%=}1iWSF@e!98?CnOUY=^#qytFJI6C`ijDkLEFb-X6x`49%LQFi z%*7@fdW`j~Unm8C!16cR$ZxQrf7^!s0PFuu;XX6s4|rEbRtG}fz-nJhYbY?e!H6Y- z4PNoRY1|V)1CAA#Q|%^(562xIxLsBi?ApyE4#lp%IVz8mPK~dV71X2jkHAK0VCGn3wtB=*998l-o{`c zkKyM@z0^RU>ajEU~nBJ;|v#LE_vvQ%~t^Cr}v#RIKF}!o=4}eV zT|wa%@|V;#D<1bXH0LC*qXxW9)PlD`HX*FSV6`S<&E6JYJQ`eW**0J3TMTtDbfIs} z9QY*|gQ>G4tEEzEwT1fWT}|$z5i;gSeEvo7z8^lAlZeJ5Q8VcG2g0%jM&$ay8n2&x zN_?iMnG_)`hheI0;Ke_apN>9!w!h13FBT6FFpm*Li-dNlp413Wr zzm#kZ`PKv|GQ#mFMMu8;c^4x$ddawzvh!9939J19%)p2i39%r}T5qh?*AP%G_^W-f7<@=$=9h70 z4Ii1K$3&h&9|fKqQvV{-D2Cr3z_e&s?Zc!Ai@E5YJAdBnIo_#w@pF;1T6DlGJ7vrc zGzG(zQ6JDIJ69%J5eETd4m=f|jrmLgitrJg9qjlP{64Zb8fs7GAD;+UB7OGG^I9F{{i2Z859N)kSi>9xVv5{UXPr0f<7MH=$jl+gn> z#C=ifL}P0V?nPYb*~G@bB;TqgpODE*GS)QF(v_#BHNM86kO)c(sYVlWl~+ZS7s;s} z0|9%GF?_+WW$uO3?1oVcbYmpC3fWuAG@;8XY11I*o0%J}eEQ%J8eBInvyWGdq3E>U z7HLLSjWh(&O~J)V*x-xBy*^)ky`=bqF<(6=&9KIr z8-w4%au{U~t$LDgEfZFzwiH-774~AZV=<{9NXb}pG1daPc+`tk(%Xs&K&eu!qE_M* zam!PJ))qCFL~DVt?sP$tNs|U$wpvda$V>B#QjnbGivn0@eJicuq^`-l9E%4ytzPp+2I zcp4IG*W>lpR?qQzuCDZYDWIYOnfquYJ)+}seKjg&>@g-3!MC(RSw0oST$E#KiqTL@ zLJf_z++WPq_ZNfbj+)UzVFRUXul&OjGecv==V0@&fG!EJx5zOijAMe&>}?&KN!1X}cI{ zRl7w|Q5Y=DqZ}nhiFRsY4_wK+B5aM78^x}mnntBk8bkGY+d`X6vCF8B#kiAJ6H-Kl zplV=n0^+%h!Dt$KnkyBQP~;vl*9L0QJ`c++BD>X)o1aSMjoc<(kwi^76X-O;yO(IF z23zWCxuX^$AzCoxT(KGxnKCbE1dCQkL&fnDu`$q6UlqVX zq_rq=NhlHy)KbQj@sQU8J&b9B^ zx5z+9cPbemu5etGxzXFG1%}pCLt~59$jU$qofCuM)|;{!+i>Dp-U2RQ)Mz|9LR=`M)(Lr4@APl~FG2|Er+kN?Xh!5>?;( z-@KNvT)apuhbueY0)tFc-BiC9u=O9Te-L#k_EdfK{mE@y-^q?u@u}KXada4U$$zST z>JA`yQZ%vfluKZJs`?6k431u3{a!(u>vyVwWeuvHg2kw;*H`ZoSKlHllv^#!f~u#; zrKn6aWxsmgxtZ&ae^GH{4VS9Oa5T4HQ9xJq3+FG{N{ +#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; +} + + +struct Point { + int x; + int y; +}; +struct Person { + char* name; + int age; +}; + +static const uint8_t sui_bitmap_Point[] = { 0, 0 }; +static const TypeInfo sui_typeinfo_Point = { + .field_count = 2, + .pointer_count = 0, + .pointer_bitmap = sui_bitmap_Point +}; +static const uint8_t sui_bitmap_Person[] = { 1, 0 }; +static const TypeInfo sui_typeinfo_Person = { + .field_count = 2, + .pointer_count = 1, + .pointer_bitmap = sui_bitmap_Person +}; + +int suic_main(void); + + +int suic_main(void) { + struct Point* p = suic_alloc_struct(&sui_typeinfo_Point, sizeof(struct Point), &(struct Point){ .x = 5, .y = 10 }); + struct Person* person = suic_alloc_struct(&sui_typeinfo_Person, sizeof(struct Person), &(struct Person){ .name = suic_alloc_array(NULL, sizeof(char), 6, "Alice"), .age = 30 }); + int _ = ((*p).x + (*person).age); + 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/tests/structs.o b/tests/structs.o new file mode 100755 index 0000000000000000000000000000000000000000..13e75a4d04c0605447165bb5dbd853e2a8485c53 GIT binary patch literal 45488 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 Qmw$Szl(<+KYE%Ay0sU8fb^rhX literal 0 HcmV?d00001