diff --git a/src/game.zig b/src/game.zig index b5b33220..b46e0816 100644 --- a/src/game.zig +++ b/src/game.zig @@ -335,6 +335,7 @@ pub const collision = struct { const VolumeProperties = struct { terminalVelocity: f64, density: f64, + maxDensity: f64, mobility: f64, }; @@ -359,6 +360,7 @@ pub const collision = struct { var invTerminalVelocitySum: f64 = 0; var densitySum: f64 = 0; + var maxDensity: f64 = defaults.maxDensity; var mobilitySum: f64 = 0; var volumeSum: f64 = 0; @@ -388,6 +390,7 @@ pub const collision = struct { mobilitySum += emptyVolume*defaults.mobility; invTerminalVelocitySum += filledVolume/block.terminalVelocity(); densitySum += filledVolume*block.density(); + maxDensity = @max(maxDensity, block.density()); mobilitySum += filledVolume*block.mobility(); } else { invTerminalVelocitySum += gridVolume/defaults.terminalVelocity; @@ -401,6 +404,7 @@ pub const collision = struct { return .{ .terminalVelocity = volumeSum/invTerminalVelocitySum, .density = densitySum/volumeSum, + .maxDensity = maxDensity, .mobility = mobilitySum/volumeSum, }; } @@ -920,7 +924,7 @@ pub fn update(deltaTime: f64) void { // MARK: update() const playerDensity = 1.2; var move: Vec3d = .{0, 0, 0}; if(main.renderer.mesh_storage.getBlockFromRenderThread(@intFromFloat(@floor(Player.super.pos[0])), @intFromFloat(@floor(Player.super.pos[1])), @intFromFloat(@floor(Player.super.pos[2]))) != null) { - const volumeProperties = collision.calculateVolumeProperties(.client, Player.super.pos, Player.outerBoundingBox, .{.density = 0.001, .terminalVelocity = airTerminalVelocity, .mobility = 1.0}); + const volumeProperties = collision.calculateVolumeProperties(.client, Player.super.pos, Player.outerBoundingBox, .{.density = 0.001, .terminalVelocity = airTerminalVelocity, .maxDensity = 0.001, .mobility = 1.0}); const effectiveGravity = gravity*(playerDensity - volumeProperties.density)/playerDensity; const volumeFrictionCoeffecient: f32 = @floatCast(gravity/volumeProperties.terminalVelocity); var acc = Vec3d{0, 0, 0}; @@ -931,6 +935,8 @@ pub fn update(deltaTime: f64) void { // MARK: update() const groundFriction = if(!Player.onGround and !Player.isFlying.load(.monotonic)) 0 else collision.calculateFriction(.client, Player.super.pos, Player.outerBoundingBox, 20); Player.currentFriction = if(Player.isFlying.load(.monotonic)) 20 else groundFriction + volumeFrictionCoeffecient; const mobility = if(Player.isFlying.load(.monotonic)) 1.0 else volumeProperties.mobility; + const density = if(Player.isFlying.load(.monotonic)) 0.0 else volumeProperties.density; + const maxDensity = if(Player.isFlying.load(.monotonic)) 0.0 else volumeProperties.maxDensity; const baseFrictionCoefficient: f32 = Player.currentFriction; var directionalFrictionCoefficients: Vec3f = @splat(0); const speedMultiplier: f32 = if(Player.hyperSpeed.load(.monotonic)) 4.0 else 1.0; @@ -940,8 +946,9 @@ pub fn update(deltaTime: f64) void { // MARK: update() // At equillibrium we want to have dv/dt = a - λv = 0 → a = λ*v const fricMul = speedMultiplier*baseFrictionCoefficient*if(Player.isFlying.load(.monotonic)) 1.0 else mobility; - const forward = vec.rotateZ(Vec3d{0, 1, 0}, -camera.rotation[2]); - const right = Vec3d{-forward[1], forward[0], 0}; + const horizontalForward = vec.rotateZ(Vec3d{0, 1, 0}, -camera.rotation[2]); + const forward = vec.normalize(std.math.lerp(horizontalForward, camera.direction, @as(Vec3d, @splat(density/@max(1.0, maxDensity))))); + const right = Vec3d{-horizontalForward[1], horizontalForward[0], 0}; var movementDir: Vec3d = .{0, 0, 0}; var movementSpeed: f64 = 0; @@ -1023,8 +1030,13 @@ pub fn update(deltaTime: f64) void { // MARK: update() movementDir[2] -= walkingSpeed; } } + if(movementSpeed != 0 and vec.lengthSquare(movementDir) != 0) { - movementDir = vec.normalize(movementDir); + if(vec.lengthSquare(movementDir) > movementSpeed*movementSpeed) { + movementDir = vec.normalize(movementDir); + } else { + movementDir /= @splat(movementSpeed); + } acc += movementDir*@as(Vec3d, @splat(movementSpeed*fricMul)); }