Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
[submodule "libs/SDL_image"]
path = libs/SDL_image
url = https://github.com/libsdl-org/SDL_image.git
[submodule "libs/SDL_net"]
path = libs/SDL_net
url = https://github.com/libsdl-org/SDL_net.git
11 changes: 7 additions & 4 deletions build.bat
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@ set auto_compile_flags=
if "%asan%"=="1" set auto_compile_flags=%auto_compile_flags% -fsanitize=address && echo [asan enabled]

:: --- Compile/Link Line Definitions ------------------------------------------
set cl_common= /I..\src\ /I..\libs\SDL\include\ /I..\libs\SDL_image\include\ /nologo /FC /Z7 /MD /W4 /wd4244 /wd4201
set clang_common= -I..\src\ -I..\libs\SDL\include\ -I..\libs\SDL_image\include\ -fdiagnostics-absolute-paths -Wall -Wno-unused-variable -Wno-missing-braces -Wno-unused-function -Wno-microsoft-static-assert -Wno-c2x-extensions
set cl_common= /I..\src\ /I..\libs\SDL\include\ /I..\libs\SDL_image\include\ -I..\libs\SDL_net\include\ /nologo /FC /Z7 /MD /W4 /wd4244 /wd4201
set clang_common= -I..\src\ -I..\libs\SDL\include\ -I..\libs\SDL_image\include\ -I..\libs\SDL_net\include\ -fdiagnostics-absolute-paths -Wall -Wno-unused-variable -Wno-missing-braces -Wno-unused-function -Wno-microsoft-static-assert -Wno-c2x-extensions
set cl_debug= call cl /Od /Ob1 /DBUILD_DEBUG=1 %cl_common% %auto_compile_flags%
set cl_release= call cl /O2 /DBUILD_DEBUG=0 %cl_common% %auto_compile_flags%
set cl_libs= User32.lib Advapi32.lib Shell32.lib Gdi32.lib Version.lib OleAut32.lib Imm32.lib Ole32.lib Cfgmgr32.lib Setupapi.lib Winmm.lib ..\libs\SDL\build\win\Debug\SDL3-static.lib ..\libs\SDL_image\build\win\Debug\SDL3_image-static.lib
set cl_libs= User32.lib Advapi32.lib Shell32.lib Gdi32.lib Version.lib OleAut32.lib Imm32.lib Ole32.lib Cfgmgr32.lib Setupapi.lib Winmm.lib Ws2_32.lib Iphlpapi.lib ..\libs\SDL\build\win\Debug\SDL3-static.lib ..\libs\SDL_image\build\win\Debug\SDL3_image-static.lib ..\libs\SDL_net\build\win\Debug\SDL3_net-static.lib
set cl_link= /link /SUBSYSTEM:WINDOWS /MANIFEST:EMBED /INCREMENTAL:NO /pdbaltpath:%%%%_PDB%%%% %cl_libs%
set cl_out= /out:

set clang_debug= call clang -g -O0 -DBUILD_DEBUG=1 %clang_common% %auto_compile_flags%
set clang_release= call clang -g -O2 -DBUILD_DEBUG=0 %clang_common% %auto_compile_flags%
set clang_libs= -lUser32.lib -lAdvapi32.lib -lShell32.lib -lGdi32.lib -lVersion.lib -lOleAut32.lib -lImm32.lib -lOle32.lib -lCfgmgr32.lib -lSetupapi.lib -lWinmm.lib ..\libs\SDL\build\win\Debug\SDL3-static.lib ..\libs\SDL_image\build\win\Debug\SDL3_image-static.lib
set clang_libs= -lUser32.lib -lAdvapi32.lib -lShell32.lib -lGdi32.lib -lVersion.lib -lOleAut32.lib -lImm32.lib -lOle32.lib -lCfgmgr32.lib -lSetupapi.lib -lWinmm.lib -lWs2_32.lib -lIphlpapi.lib ..\libs\SDL\build\win\Debug\SDL3-static.lib ..\libs\SDL_image\build\win\Debug\SDL3_image-static.lib ..\libs\SDL_net\build\win\Debug\SDL3_net-static.lib
set clang_link= -fuse-ld=lld -Xlinker /SUBSYSTEM:WINDOWS -Xlinker /MANIFEST:EMBED -Xlinker /pdbaltpath:%%%%_PDB%%%% %clang_libs%
set clang_out= -o

Expand Down Expand Up @@ -78,6 +78,9 @@ if "%sdl%"=="1" (
pushd libs\SDL_image
(cmake -S . -B build\win -DSDLIMAGE_VENDORED=OFF -DBUILD_SHARED_LIBS=OFF "-DSDL3_DIR=..\SDL\build\win" && cmake --build build\win) || exit /b 1
popd
pushd libs\SDL_net
(cmake -S . -B build\win -DBUILD_SHARED_LIBS=OFF "-DSDL3_DIR=..\SDL\build\win" && cmake --build build\win) || exit /b 1
popd
) else (
echo "SDL directory not found! Make sure to initialize git submodules."
)
Expand Down
15 changes: 11 additions & 4 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ if [ -v gcc ]; then compiler="${CC:-gcc}"; echo "[gcc compile]"; fi
auto_compile_flags=''

# --- Compile/Link Line Definitions -------------------------------------------
clang_common='-I../src/ -I../libs/SDL/include/ -I../libs/SDL_image/include/ -g -fdiagnostics-absolute-paths -Wall -Wno-unused-variable -std=c23'
clang_common='-I../src/ -I../libs/SDL/include/ -I../libs/SDL_image/include/ -I../libs/SDL_net/include/ -g -fdiagnostics-absolute-paths -Wall -Wno-unused-variable -std=c23'
clang_debug="$compiler -O0 -DBUILD_DEBUG=1 ${clang_common} ${auto_compile_flags}"
clang_release="$compiler -O2 -DBUILD_DEBUG=0 ${clang_common} ${auto_compile_flags}"
clang_link="../libs/SDL/build/libSDL3.a ../libs/SDL_image/build/libSDL3_image.a -lm"
clang_link="../libs/SDL/build/libSDL3.a ../libs/SDL_image/build/libSDL3_image.a ../libs/SDL_net/build/libSDL3_net.a -lm"
clang_out="-o"
gcc_common='-I../src/ -I../libs/SDL/include/ -I../libs/SDL_image/include/ -g -Wall -Wno-unused-variable -std=c23'
gcc_common='-I../src/ -I../libs/SDL/include/ -I../libs/SDL_image/include/ -I../libs/SDL_net/include/ -g -Wall -Wno-unused-variable -std=c23'
gcc_debug="$compiler -O0 -DBUILD_DEBUG=1 ${gcc_common} ${auto_compile_flags}"
gcc_release="$compiler -O2 -DBUILD_DEBUG=0 ${gcc_common} ${auto_compile_flags}"
gcc_link="../libs/SDL/build/libSDL3.a ../libs/SDL_image/build/libSDL3_image.a -lm"
gcc_link="../libs/SDL/build/libSDL3.a ../libs/SDL_image/build/libSDL3_image.a ../libs/SDL_net/build/libSDL3_net.a -lm"
gcc_out="-o"

# --- Choose Compile/Link Lines -----------------------------------------------
Expand Down Expand Up @@ -62,6 +62,13 @@ if [ -v sdl ]; then
else
echo "SDL_image directory not found! Make sure to initialize git submodules."
fi
if [ -d "libs/SDL_net" ]; then
cd libs/SDL_net
cmake -S . -B build -DBUILD_SHARED_LIBS=OFF "-DSDL3_DIR=..\SDL\build" && cmake --build build
cd ../../
else
echo "SDL_net directory not found! Make sure to initialize git submodules."
fi
fi

cd build
Expand Down
1 change: 1 addition & 0 deletions libs/SDL_net
Submodule SDL_net added at c40703
258 changes: 27 additions & 231 deletions src/de_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,230 +3,6 @@
// and it should be isolated from platform specific
// stuff when it's reasonable.
//
static void Game_AdvanceSimulation(AppState *app)
{
// update prev_p
ForU32(obj_id, app->object_count)
{
Object *obj = app->object_pool + obj_id;
obj->prev_p = obj->p;
}

// animate special wall
{
Object *obj = Object_Get(app, app->special_wall);
obj->collision_rotation = WrapF(0.f, 1.f, obj->collision_rotation + TIME_STEP);
obj->sprite_rotation = obj->collision_rotation;
Object_UpdateCollisionVerticesAndNormals(obj);
}

// player input
ForArray(player_id_index, app->player_ids)
{
Object *player = Object_PlayerFromIndex(app, player_id_index);

V2 dir = {0};
if (player_id_index == 0)
{
if (app->keyboard[SDL_SCANCODE_W] || app->keyboard[SDL_SCANCODE_UP]) dir.y += 1;
if (app->keyboard[SDL_SCANCODE_S] || app->keyboard[SDL_SCANCODE_DOWN]) dir.y -= 1;
if (app->keyboard[SDL_SCANCODE_A] || app->keyboard[SDL_SCANCODE_LEFT]) dir.x -= 1;
if (app->keyboard[SDL_SCANCODE_D] || app->keyboard[SDL_SCANCODE_RIGHT]) dir.x += 1;
}
else if (player_id_index == 1)
{
// for vim fans
if (app->keyboard[SDL_SCANCODE_K]) dir.y += 1;
if (app->keyboard[SDL_SCANCODE_J]) dir.y -= 1;
if (app->keyboard[SDL_SCANCODE_H]) dir.x -= 1;
if (app->keyboard[SDL_SCANCODE_L]) dir.x += 1;
}
dir = V2_Normalize(dir);

bool ice_skating_dlc = (player_id_index == 1);
if (ice_skating_dlc)
{
// @todo(mg): this is bad, we need a fixed timestep
float player_speed = 0.005f * TIME_STEP;
V2 player_ddp = V2_Scale(dir, player_speed);
player->dp = V2_Add(player->dp, player_ddp);

float drag = -0.999f * TIME_STEP;
V2 player_drag = V2_Scale(player->dp, drag);
player->dp = V2_Add(player->dp, player_drag);
}
else
{
float player_speed = 5.f * TIME_STEP;
player->dp = V2_Scale(dir, player_speed);
}
}

// movement & collision
ForU32(obj_id, app->object_count)
{
Object *obj = app->object_pool + obj_id;
obj->has_collision = false;
}
ForU32(obj_id, app->object_count)
{
Object *obj = app->object_pool + obj_id;
if (!(obj->flags & ObjectFlag_Move)) continue;

obj->p = V2_Add(obj->p, obj->dp);
Object_UpdateCollisionVerticesAndNormals(obj);

ForU32(collision_iteration, 8) // support up to 8 overlapping wall collisions
{
float closest_obstacle_separation_dist = FLT_MAX;
V2 closest_obstacle_wall_normal = {0};

ForU32(obstacle_id, app->object_count)
{
Object *obstacle = app->object_pool + obstacle_id;
if (!(obstacle->flags & ObjectFlag_Collide)) continue;
if (obj == obstacle) continue;

float biggest_dist = -FLT_MAX;
V2 wall_normal = {0};

// @info(mg) SAT algorithm needs 2 iterations
// from the perspective of the obj
// and from the perspective of the obstacle.
ForU32(sat_iteration, 2)
{
Object *normal_obj;
Object *projected_obstacle;
CollisionProjectionResult a;
CollisionProjectionResult b;
if (sat_iteration == 0)
{
normal_obj = obj;
projected_obstacle = obstacle;
}
else
{
normal_obj = obstacle;
projected_obstacle = obj;
}

a = Object_CollisionProjection(normal_obj->collision_normals, normal_obj->collision_vertices); // @speed(mg) we could cache these per object
b = Object_CollisionProjection(normal_obj->collision_normals, projected_obstacle->collision_vertices);

ForArray(i, a.arr)
{
static_assert(ArrayCount(a.arr) == ArrayCount(obj->collision_normals.arr));
V2 normal = normal_obj->collision_normals.arr[i];

V2 obj_col = Object_GetAvgCollisionPos(normal_obj);
V2 obstacle_col = Object_GetAvgCollisionPos(projected_obstacle);
V2 obstacle_dir = V2_Sub(obstacle_col, obj_col);
if (V2_Inner(normal, obstacle_dir) < 0)
{
continue;
}

float d = RngF_MaxDistance(a.arr[i], b.arr[i]);
if (d > 0.f)
{
// @info(mg) We can exit early from checking this
// obstacle since we found an axis that has
// a separation between obj and obstacle.
goto skip_this_obstacle;
}

if (d > biggest_dist)
{
biggest_dist = d;
if (normal_obj == obj)
{
wall_normal = V2_Reverse(normal);
}
else
{
wall_normal = normal;
}
}
}
}

if (closest_obstacle_separation_dist > biggest_dist)
{
closest_obstacle_separation_dist = biggest_dist;
closest_obstacle_wall_normal = wall_normal;
}

obj->has_collision |= (biggest_dist < 0.f);
obstacle->has_collision |= (biggest_dist < 0.f);

skip_this_obstacle:;
}

if (closest_obstacle_separation_dist < 0.f)
{
V2 move_out_dir = closest_obstacle_wall_normal;
float move_out_magnitude = -closest_obstacle_separation_dist;

V2 move_out = V2_Scale(move_out_dir, move_out_magnitude);
obj->p = V2_Add(obj->p, move_out);

// remove all velocity on collision axis
// we might want to do something different here!
if (move_out.x) obj->dp.x = 0;
if (move_out.y) obj->dp.y = 0;

Object_UpdateCollisionVerticesAndNormals(obj);
}
else
{
// Collision not found, stop iterating
break;
}
} // collision_iteration
} // obj_id


// animate textures
ForU32(obj_id, app->object_count)
{
Object *obj = app->object_pool + obj_id;
if (Sprite_Get(app, obj->sprite_id)->frame_count <= 1) continue;

Uint32 frame_index_map[8] =
{
0, 1, 2, 1,
0, 3, 4, 3
};

bool in_idle_frame = (0 == frame_index_map[obj->sprite_animation_index]);

float distance = V2_Length(V2_Sub(obj->p, obj->prev_p));
float anim_speed = (16.f * TIME_STEP);
anim_speed += (3200.f * distance * TIME_STEP);

if (!distance && in_idle_frame)
{
anim_speed = 0.f;
}
obj->sprite_animation_t += anim_speed;

float period = 1.f;
while (obj->sprite_animation_t > period)
{
obj->sprite_animation_t -= period;
obj->sprite_animation_index += 1;
}

obj->sprite_animation_index %= ArrayCount(frame_index_map);
obj->sprite_frame_index = frame_index_map[obj->sprite_animation_index];
}

// move camera
{
Object *player = Object_Get(app, app->player_ids[0]);
app->camera_p = player->p;
}
}

static void Game_VerticesCameraTransform(AppState *app, V2 verts[4], float camera_scale, V2 window_transform)
{
Expand All @@ -243,7 +19,7 @@ static void Game_VerticesCameraTransform(AppState *app, V2 verts[4], float camer
verts[i].y += window_transform.y;

// fix y axis direction to +Y up (SDL uses +Y down, -Y up)
verts[i].y = app->height - verts[i].y;
verts[i].y = app->window_height - verts[i].y;
}
}

Expand Down Expand Up @@ -271,10 +47,10 @@ static void Game_IssueDrawCommands(AppState *app)
{
float camera_scale = 1.f;
{
float wh = Max(app->width, app->height); // pick bigger window dimension
float wh = Max(app->window_width, app->window_height); // pick bigger window dimension
camera_scale = wh / app->camera_range;
}
V2 window_transform = (V2){app->width*0.5f, app->height*0.5f};
V2 window_transform = (V2){app->window_width*0.5f, app->window_height*0.5f};

ForU32(object_index, app->object_count)
{
Expand Down Expand Up @@ -379,6 +155,19 @@ static void Game_IssueDrawCommands(AppState *app)
}
}

// draw debug networking stuff
{
ColorF green = ColorF_RGB(0, 1, 0);
ColorF red = ColorF_RGB(1, 0, 0);

SDL_FRect rect = { 0, 0, 30, 30 };
if (!app->net.is_server) rect.x = 40;

ColorF color = app->net.err ? red : green;
SDL_SetRenderDrawColorFloat(app->renderer, color.r, color.g, color.b, color.a);
SDL_RenderFillRect(app->renderer, &rect);
}

// draw mouse
{
static float r = 0;
Expand All @@ -399,25 +188,30 @@ static void Game_IssueDrawCommands(AppState *app)
static void Game_Iterate(AppState *app)
{
{
app->frame_id += 1;

Uint64 new_frame_time = SDL_GetTicks();
Uint64 delta_time = new_frame_time - app->frame_time;
app->frame_time = new_frame_time;
app->dt = delta_time * (0.001f);
app->physics_time_accumulator += Min(app->dt, 1.f); // clamp dt to 1s
app->tick_dt_accumulator += Min(app->dt, 1.f); // clamp dt to 1s

if (app->debug.fixed_dt)
{
app->dt = app->debug.fixed_dt;
}
}

Net_Iterate(app);

bool run_simulation = (!app->debug.pause_on_every_frame || !app->debug.paused_frame);
if (run_simulation)
{
while (app->physics_time_accumulator > TIME_STEP)
while (app->tick_dt_accumulator > TIME_STEP)
{
app->physics_time_accumulator -= TIME_STEP;
Game_AdvanceSimulation(app);
app->tick_id += 1;
app->tick_dt_accumulator -= TIME_STEP;
Tick_Iterate(app);
}
}
Game_IssueDrawCommands(app);
Expand All @@ -432,6 +226,8 @@ static void Game_Init(AppState *app)
app->debug.draw_collision_box = true;
}

Net_Init(app);

app->frame_time = SDL_GetTicks();
app->object_count += 1; // reserve object under index 0 as special 'nil' value
app->sprite_count += 1; // reserve sprite under index 0 as special 'nil' value
Expand Down
Loading