Bouncy mushrooms (#1707)

Fixes #1704

---------

Co-authored-by: IntegratedQuantum <jahe788@gmail.com>
This commit is contained in:
codemob 2025-07-31 10:33:02 -04:00 committed by GitHub
parent 2dc2a6e790
commit fc5f76411e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 43 additions and 8 deletions

View File

@ -1,6 +1,7 @@
.{
.tags = .{.choppable, .cuttable, .mushroom},
.blockHealth = 3,
.bounciness = 0.75,
.drops = .{
.{.items = .{.auto}},
},

View File

@ -1,6 +1,7 @@
.{
.tags = .{.choppable, .cuttable, .mushroom},
.blockHealth = 3,
.bounciness = 0.5,
.drops = .{
.{.items = .{.auto}},
},

View File

@ -1,6 +1,7 @@
.{
.tags = .{.choppable, .cuttable, .mushroom},
.blockHealth = 3,
.bounciness = 1.0,
.drops = .{
.{.items = .{.auto}},
},

View File

@ -79,6 +79,7 @@ var _lodReplacement: [maxBlockCount]u16 = undefined;
var _opaqueVariant: [maxBlockCount]u16 = undefined;
var _friction: [maxBlockCount]f32 = undefined;
var _bounciness: [maxBlockCount]f32 = undefined;
var _density: [maxBlockCount]f32 = undefined;
var _terminalVelocity: [maxBlockCount]f32 = undefined;
var _mobility: [maxBlockCount]f32 = undefined;
@ -132,6 +133,7 @@ pub fn register(_: []const u8, id: []const u8, zon: ZonElement) u16 {
_viewThrough[size] = zon.get(bool, "viewThrough", false) or _transparent[size] or _alwaysViewThrough[size];
_hasBackFace[size] = zon.get(bool, "hasBackFace", false);
_friction[size] = zon.get(f32, "friction", 20);
_bounciness[size] = zon.get(f32, "bounciness", 0.0);
_density[size] = zon.get(f32, "density", 0.001);
_terminalVelocity[size] = zon.get(f32, "terminalVelocity", 90);
_mobility[size] = zon.get(f32, "mobility", 1.0);
@ -399,6 +401,10 @@ pub const Block = packed struct { // MARK: Block
return _friction[self.typ];
}
pub inline fn bounciness(self: Block) f32 {
return _bounciness[self.typ];
}
pub inline fn density(self: Block) f32 {
return _density[self.typ];
}

View File

@ -279,7 +279,12 @@ pub const collision = struct {
return resultBox;
}
pub fn calculateFriction(comptime side: main.utils.Side, pos: Vec3d, hitBox: Box, defaultFriction: f32) f32 {
const SurfaceProperties = struct {
friction: f32,
bounciness: f32,
};
pub fn calculateSurfaceProperties(comptime side: main.utils.Side, pos: Vec3d, hitBox: Box, defaultFriction: f32) SurfaceProperties {
const boundingBox: Box = .{
.min = pos + hitBox.min,
.max = pos + hitBox.max,
@ -292,6 +297,7 @@ pub const collision = struct {
const z: i32 = @intFromFloat(@floor(boundingBox.min[2] - 0.01));
var friction: f64 = 0;
var bounciness: f64 = 0;
var totalArea: f64 = 0;
var x = minX;
@ -320,16 +326,24 @@ pub const collision = struct {
if(block.collide()) {
totalArea += area;
friction += area*@as(f64, @floatCast(block.friction()));
bounciness += area*@as(f64, @floatCast(block.bounciness()));
}
}
}
}
if(totalArea == 0) {
return defaultFriction;
friction = defaultFriction;
bounciness = 0.0;
} else {
friction = friction/totalArea;
bounciness = bounciness/totalArea;
}
return @floatCast(friction/totalArea);
return .{
.friction = @floatCast(friction),
.bounciness = @floatCast(bounciness),
};
}
const VolumeProperties = struct {
@ -932,7 +946,7 @@ pub fn update(deltaTime: f64) void { // MARK: update()
acc[2] = -effectiveGravity;
}
const groundFriction = if(!Player.onGround and !Player.isFlying.load(.monotonic)) 0 else collision.calculateFriction(.client, Player.super.pos, Player.outerBoundingBox, 20);
const groundFriction = if(!Player.onGround and !Player.isFlying.load(.monotonic)) 0 else collision.calculateSurfaceProperties(.client, Player.super.pos, Player.outerBoundingBox, 20).friction;
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;
@ -1092,7 +1106,7 @@ pub fn update(deltaTime: f64) void { // MARK: update()
var frictionCoefficient = baseFrictionCoefficient + directionalFrictionCoefficients[i];
if(i == 2 and jumping) { // No friction while jumping
// Here we want to ensure a specified jump height under air friction.
Player.super.vel[i] = @sqrt(Player.jumpHeight*gravity*2);
Player.super.vel[i] += @sqrt(Player.jumpHeight*gravity*2);
frictionCoefficient = airFrictionCoefficient;
}
const v_0 = Player.super.vel[i];
@ -1275,14 +1289,26 @@ pub fn update(deltaTime: f64) void { // MARK: update()
} else {
Player.super.pos[2] = box.min[2] - hitBox.max[2];
}
var bounciness = if(Player.isFlying.load(.monotonic)) 0 else collision.calculateSurfaceProperties(.client, Player.super.pos, Player.outerBoundingBox, 0.0).bounciness;
if(KeyBoard.key("crouch").pressed) {
bounciness *= 0.5;
}
var velocityChange: f64 = undefined;
const damage: f32 = @floatCast(@round(@max((Player.super.vel[2]*Player.super.vel[2])/(2*gravity) - 7, 0))/2);
if(bounciness != 0.0 and Player.super.vel[2] < -3.0) {
velocityChange = Player.super.vel[2]*@as(f64, @floatCast(1 - bounciness));
Player.super.vel[2] = -Player.super.vel[2]*bounciness;
Player.jumpCoyote = Player.jumpCoyoteTimeConstant + deltaTime;
Player.eyeVel[2] *= 2;
} else {
velocityChange = Player.super.vel[2];
Player.super.vel[2] = 0;
}
const damage: f32 = @floatCast(@round(@max((velocityChange*velocityChange)/(2*gravity) - 7, 0))/2);
if(damage > 0.01) {
Inventory.Sync.addHealth(-damage, .fall, .client, Player.id);
}
Player.super.vel[2] = 0;
// Always unstuck upwards for now
while(collision.collides(.client, .z, 0, Player.super.pos, hitBox)) |_| {
Player.super.pos[2] += 1;