Fix incorrect triangle normal when colliding against level geom, reverse gear, engine sound

This commit is contained in:
sergeypdev 2025-07-01 11:57:53 +04:00
parent 7f2f1795fe
commit a8e3bb6104
6 changed files with 74 additions and 6 deletions

2
.gitattributes vendored
View File

@ -4,3 +4,5 @@
*.jpeg filter=lfs diff=lfs merge=lfs -text *.jpeg filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text *.blend filter=lfs diff=lfs merge=lfs -text
*.blend1 filter=lfs diff=lfs merge=lfs -text *.blend1 filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.mp3 filter=lfs diff=lfs merge=lfs -text

BIN
assets/engine_loop.wav (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -49,6 +49,8 @@ Asset_Manager :: struct {
textures: Asset_Cache(rl.Texture2D), textures: Asset_Cache(rl.Texture2D),
models: Asset_Cache(rl.Model), models: Asset_Cache(rl.Model),
shaders: Asset_Cache(Loaded_Shader), shaders: Asset_Cache(Loaded_Shader),
sounds: Asset_Cache(rl.Sound),
music: Asset_Cache(rl.Music),
curves_1d: Asset_Cache([]f32), curves_1d: Asset_Cache([]f32),
curves_2d: Asset_Cache(Curve_2D), curves_2d: Asset_Cache(Curve_2D),
bvhs: map[cstring]Loaded_BVH, bvhs: map[cstring]Loaded_BVH,
@ -107,6 +109,26 @@ SHADER_LOADER :: Asset_Cache_Loader(Loaded_Shader) {
}, },
} }
SOUND_LOADER :: Asset_Cache_Loader(rl.Sound) {
load = proc(path: cstring, payload: Asset_Cache_Loader_Payload) -> (rl.Sound, bool) {
sound := rl.LoadSound(path)
return sound, rl.IsSoundValid(sound)
},
unload = proc(sound: rl.Sound) {
rl.UnloadSound(sound)
},
}
MUSIC_LOADER :: Asset_Cache_Loader(rl.Music) {
load = proc(path: cstring, payload: Asset_Cache_Loader_Payload) -> (rl.Music, bool) {
music := rl.LoadMusicStream(path)
return music, rl.IsMusicValid(music)
},
unload = proc(music: rl.Music) {
rl.UnloadMusicStream(music)
},
}
MODEL_LOADER :: Asset_Cache_Loader(rl.Model) { MODEL_LOADER :: Asset_Cache_Loader(rl.Model) {
load = proc(path: cstring, payload: Asset_Cache_Loader_Payload) -> (rl.Model, bool) { load = proc(path: cstring, payload: Asset_Cache_Loader_Payload) -> (rl.Model, bool) {
model := rl.LoadModel(path) model := rl.LoadModel(path)
@ -176,6 +198,12 @@ assetman_init :: proc(assetman: ^Asset_Manager) {
assetman.shaders = { assetman.shaders = {
loader = SHADER_LOADER, loader = SHADER_LOADER,
} }
assetman.sounds = {
loader = SOUND_LOADER,
}
assetman.music = {
loader = MUSIC_LOADER,
}
assetman.textures = { assetman.textures = {
loader = TEXTURE_LOADER, loader = TEXTURE_LOADER,
} }
@ -321,6 +349,16 @@ get_shader :: proc(
return loaded_shader return loaded_shader
} }
get_sound :: proc(assetman: ^Asset_Manager, path: cstring) -> rl.Sound {
sound, _, _ := assetcache_fetch_or_load(&assetman.sounds, path)
return sound
}
get_music :: proc(assetman: ^Asset_Manager, path: cstring) -> rl.Music {
sound, _, _ := assetcache_fetch_or_load(&assetman.music, path)
return sound
}
null_bvhs: []bvh.BVH null_bvhs: []bvh.BVH
get_bvh :: proc(assetman: ^Asset_Manager, path: cstring) -> Loaded_BVH { get_bvh :: proc(assetman: ^Asset_Manager, path: cstring) -> Loaded_BVH {
@ -784,6 +822,8 @@ shutdown :: proc(assetman: ^Asset_Manager) {
assetcache_destroy(&assetman.textures) assetcache_destroy(&assetman.textures)
assetcache_destroy(&assetman.models) assetcache_destroy(&assetman.models)
assetcache_destroy(&assetman.shaders) assetcache_destroy(&assetman.shaders)
assetcache_destroy(&assetman.sounds)
assetcache_destroy(&assetman.music)
assetcache_destroy(&assetman.curves_1d) assetcache_destroy(&assetman.curves_1d)
assetcache_destroy(&assetman.curves_2d) assetcache_destroy(&assetman.curves_2d)

View File

@ -361,6 +361,7 @@ World_Update_Config :: struct {
} }
update_world :: proc(world: ^World, dt: f32, config: World_Update_Config) { update_world :: proc(world: ^World, dt: f32, config: World_Update_Config) {
if !world.pause { if !world.pause {
car_model := assets.get_model(&g_mem.assetman, "assets/ice_cream_truck.glb") car_model := assets.get_model(&g_mem.assetman, "assets/ice_cream_truck.glb")
car_bounds := rl.GetModelBoundingBox(car_model) car_bounds := rl.GetModelBoundingBox(car_model)
@ -626,7 +627,7 @@ update_world :: proc(world: ^World, dt: f32, config: World_Update_Config) {
axle = physics.Drive_Axle_Config { axle = physics.Drive_Axle_Config {
wheels = {wheel_rl, wheel_rr}, wheels = {wheel_rl, wheel_rr},
wheel_count = 2, wheel_count = 2,
diff_type = .Open, diff_type = .Fixed,
final_drive_ratio = 4.1, final_drive_ratio = 4.1,
}, },
}, },
@ -747,6 +748,24 @@ update_world :: proc(world: ^World, dt: f32, config: World_Update_Config) {
step_mode = config.single_step_physics ? physics.Step_Mode.Single : physics.Step_Mode.Accumulated_Time, step_mode = config.single_step_physics ? physics.Step_Mode.Single : physics.Step_Mode.Accumulated_Time,
) )
} }
{
engine_loop := assets.get_music(&g_mem.assetman, "assets/engine_loop.wav")
if !rl.IsMusicStreamPlaying(engine_loop) {
rl.PlayMusicStream(engine_loop)
}
rl.UpdateMusicStream(engine_loop)
sim_state := physics.get_sim_state(&world.physics_scene)
engine := physics.get_engine(sim_state, world.engine_handle)
rpm_percent :=
max(physics.angular_velocity_to_rpm(engine.w) - engine.lowest_rpm, 0.0) /
(engine.rev_limit_rpm - engine.lowest_rpm)
pitch := linalg.lerp(f32(1.0), f32(3.0), rpm_percent)
rl.SetMusicPitch(engine_loop, pitch)
}
} }
update_runtime_world :: proc(runtime_world: ^Runtime_World, dt: f32) { update_runtime_world :: proc(runtime_world: ^Runtime_World, dt: f32) {
@ -1393,6 +1412,7 @@ game_init_window :: proc(args: []string) {
rl.SetConfigFlags({.WINDOW_RESIZABLE, .VSYNC_HINT}) rl.SetConfigFlags({.WINDOW_RESIZABLE, .VSYNC_HINT})
rl.InitWindow(1280, 720, "Gutter Runner") rl.InitWindow(1280, 720, "Gutter Runner")
rl.InitAudioDevice()
rl.SetExitKey(.KEY_NULL) rl.SetExitKey(.KEY_NULL)
rl.SetWindowPosition(200, 200) rl.SetWindowPosition(200, 200)
rl.SetTargetFPS(120) rl.SetTargetFPS(120)
@ -1441,6 +1461,7 @@ game_shutdown :: proc() {
@(export) @(export)
game_shutdown_window :: proc() { game_shutdown_window :: proc() {
rl.CloseAudioDevice()
rl.CloseWindow() rl.CloseWindow()
deinit_physfs() deinit_physfs()

View File

@ -77,6 +77,8 @@ double_sided_triangle_to_convex :: proc(
convex.vertices[0].pos = tri[0] convex.vertices[0].pos = tri[0]
convex.vertices[1].pos = tri[1] convex.vertices[1].pos = tri[1]
convex.vertices[2].pos = tri[2] convex.vertices[2].pos = tri[2]
convex.faces[0].normal = lg.normalize0(lg.cross(tri[1] - tri[0], tri[2] - tri[0]))
convex.faces[1].normal = -convex.faces[0].normal
return return
} }

View File

@ -896,10 +896,10 @@ pgs_solve_contacts :: proc(
random_order[i] = i32(i) random_order[i] = i32(i)
} }
// for i in 0 ..< len(random_order) - 1 { for i in 0 ..< len(random_order) - 1 {
// j := rand.int_max(len(random_order)) j := rand.int_max(len(random_order))
// slice.swap(random_order, i, j) slice.swap(random_order, i, j)
// } }
} }
for i in 0 ..< len(sim_state.contact_container.contacts) { for i in 0 ..< len(sim_state.contact_container.contacts) {
@ -1027,7 +1027,7 @@ lookup_gear_ratio :: #force_inline proc(gear_ratios: []f32, gear: i32) -> (ratio
index -= 1 index -= 1
} }
index = clamp(index, 0, len(gear_ratios) - 1) index = clamp(index, 0, len(gear_ratios) - 1)
return gear_ratios[index] return gear_ratios[index] * (index == 0 ? -1 : 1)
} }
} }