added anti aliasing. new fps game
This commit is contained in:
parent
798434a55d
commit
7b73c86113
40 changed files with 2386 additions and 564 deletions
88
README.md
88
README.md
|
|
@ -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!</content>
|
||||
<parameter name="filePath">ODE_INTEGRATION.md
|
||||
24
compile.sh
24
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 <sui_source.sui> [output_name]"
|
||||
echo "Usage: ./compile.sh [--debug] <sui_source.sui> [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"
|
||||
|
|
|
|||
|
|
@ -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 <sui_source.sui> [program_args...]"
|
||||
echo "Usage: ./compile_and_run.sh [--debug] <sui_source.sui> [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
|
||||
|
|
|
|||
BIN
fishsoup/main
Executable file
BIN
fishsoup/main
Executable file
Binary file not shown.
141
fishsoup/main.c
Normal file
141
fishsoup/main.c
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
#include "../libsuicmez/libsuicmez.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
BIN
fishsoup/main.o
Executable file
BIN
fishsoup/main.o
Executable file
Binary file not shown.
158
fishsoup/main.sui
Normal file
158
fishsoup/main.sui
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
# Basic 3D Platformer - Fishsoup
|
||||
# Mouse for rotation, WASD for movement
|
||||
|
||||
struct Vec2
|
||||
x: float,
|
||||
y: float,
|
||||
end
|
||||
|
||||
fn main() -> 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
|
||||
BIN
fps_game
Executable file
BIN
fps_game
Executable file
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
|
@ -5,6 +5,10 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
18
src/c_ir.rs
18
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<CExpr>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct CStructDecl {
|
||||
pub name: String,
|
||||
pub fields: Vec<CVarDecl>,
|
||||
}
|
||||
|
||||
#[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<Vec<CStmt>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum CExpr {
|
||||
IntLit(i64),
|
||||
FloatLit(f64),
|
||||
|
|
@ -99,7 +99,7 @@ pub enum CExpr {
|
|||
Ternary(Box<CExpr>, Box<CExpr>, Box<CExpr>), // 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<CStmt>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum CToplevel {
|
||||
StructDecl(CStructDecl),
|
||||
FuncDecl(CFuncDecl),
|
||||
|
|
|
|||
|
|
@ -179,6 +179,7 @@ pub fn convert_to_c_type(name: &String) -> Result<CType, String> {
|
|||
"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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)?))]),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,10 +41,12 @@ pub struct Transpiler {
|
|||
stmt_transpiler: StatementsTranspiler,
|
||||
array_types: std::collections::HashSet<String>, // Track array types we need to generate
|
||||
has_main: bool, // Track if we found a main function
|
||||
typeinfo_map: std::collections::HashMap<String, Vec<u8>>, // 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<u8> {
|
||||
fields
|
||||
.iter()
|
||||
.map(|field| if Self::is_pointer_type(&field.ty) { 1u8 } else { 0u8 })
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn transpile_program(&mut self, nodes: &[TypedASTNode]) -> Result<String, String> {
|
||||
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::<Vec<_>>()
|
||||
.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(", ")
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
12
src/main.rs
12
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<String>,
|
||||
}
|
||||
|
|
@ -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))?;
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
46
test_player.c
Normal file
46
test_player.c
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#include "../libsuicmez/libsuicmez.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
1
test_player.sui
Normal file
1
test_player.sui
Normal file
|
|
@ -0,0 +1 @@
|
|||
fn main() -> int do let p = player_controller_create(0.0, 1.0, 2.0); 0 end
|
||||
BIN
test_window
Executable file
BIN
test_window
Executable file
Binary file not shown.
53
test_window.c
Normal file
53
test_window.c
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#include "../libsuicmez/libsuicmez.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
1
test_window.sui
Normal file
1
test_window.sui
Normal file
|
|
@ -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
|
||||
49
tests/basic_types.c
Normal file
49
tests/basic_types.c
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#include "../libsuicmez/libsuicmez.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
BIN
tests/basic_types.o
Executable file
BIN
tests/basic_types.o
Executable file
Binary file not shown.
50
tests/control_flow.c
Normal file
50
tests/control_flow.c
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#include "../libsuicmez/libsuicmez.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
216
tests/fps_game.c
Normal file
216
tests/fps_game.c
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
#include "../libsuicmez/libsuicmez.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
BIN
tests/fps_game.o
Executable file
BIN
tests/fps_game.o
Executable file
Binary file not shown.
271
tests/fps_game.sui
Normal file
271
tests/fps_game.sui
Normal file
|
|
@ -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
|
||||
52
tests/functions.c
Normal file
52
tests/functions.c
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#include "../libsuicmez/libsuicmez.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
89
tests/game_3d_improved.c
Normal file
89
tests/game_3d_improved.c
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#include "../libsuicmez/libsuicmez.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
BIN
tests/game_3d_improved.o
Executable file
BIN
tests/game_3d_improved.o
Executable file
Binary file not shown.
51
tests/ode_test.c
Normal file
51
tests/ode_test.c
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#include "../libsuicmez/libsuicmez.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
BIN
tests/ode_test.o
Executable file
BIN
tests/ode_test.o
Executable file
Binary file not shown.
64
tests/ode_voxel_example.c
Normal file
64
tests/ode_voxel_example.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#include "../libsuicmez/libsuicmez.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
BIN
tests/ode_voxel_example.o
Executable file
BIN
tests/ode_voxel_example.o
Executable file
Binary file not shown.
68
tests/structs.c
Normal file
68
tests/structs.c
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#include "../libsuicmez/libsuicmez.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
BIN
tests/structs.o
Executable file
BIN
tests/structs.o
Executable file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue