forked from Mirrorlandia_minetest/minetest
Alternative code for slipping (#6256)
* Alternative code for slipping - does not depend on frame rate - controllable via environment variables for now * Adjust slipping speed for item entities too. * Final version of framerate-independent slippery code * Remove dead code and fix formatting * getStandingNodePos should only look 0.05 nodes downwards This ensures that, even if the player is standing on a partially filled node, this node is used as the standing node and not the node below it. Specific use: enables slippery slabs * Exchange global getStandingPosNode change for local inline change Reverts previous commit * Revert the item movement changes * Slippery nodes now slip over cliffs and edges Players no longer suddenly stop before falling off. Also refactored slippery code into getSlipFactor method. * Slipping over an edge gated by player's is_slipping state A new flag for just this case, to reduce costly node lookups in the normal case of leaning over a non-slippery edge. Public access for consistency and potential future uses. * Minor code tweaks / cosmetics * Add temp variable to improve readability and fix indentation issues
This commit is contained in:
parent
0e0643df35
commit
fc13c00ef3
@ -656,13 +656,10 @@ void LocalPlayer::applyControl(float dtime, Environment *env)
|
|||||||
else
|
else
|
||||||
incH = incV = movement_acceleration_default * BS * dtime;
|
incH = incV = movement_acceleration_default * BS * dtime;
|
||||||
|
|
||||||
const INodeDefManager *nodemgr = env->getGameDef()->ndef();
|
float slip_factor = getSlipFactor(env, speedH);
|
||||||
Map *map = &env->getMap();
|
|
||||||
const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(getStandingNodePos()));
|
|
||||||
bool slippery = (itemgroup_get(f.groups, "slippery") != 0);
|
|
||||||
// Accelerate to target speed with maximum increment
|
// Accelerate to target speed with maximum increment
|
||||||
accelerateHorizontal(speedH * physics_override_speed,
|
accelerateHorizontal(speedH * physics_override_speed,
|
||||||
incH * physics_override_speed, slippery);
|
incH * physics_override_speed * slip_factor);
|
||||||
accelerateVertical(speedV * physics_override_speed,
|
accelerateVertical(speedV * physics_override_speed,
|
||||||
incV * physics_override_speed);
|
incV * physics_override_speed);
|
||||||
}
|
}
|
||||||
@ -702,19 +699,12 @@ v3f LocalPlayer::getEyeOffset() const
|
|||||||
|
|
||||||
// Horizontal acceleration (X and Z), Y direction is ignored
|
// Horizontal acceleration (X and Z), Y direction is ignored
|
||||||
void LocalPlayer::accelerateHorizontal(const v3f &target_speed,
|
void LocalPlayer::accelerateHorizontal(const v3f &target_speed,
|
||||||
const f32 max_increase, bool slippery)
|
const f32 max_increase)
|
||||||
{
|
{
|
||||||
if (max_increase == 0)
|
if (max_increase == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
v3f d_wanted = target_speed - m_speed;
|
v3f d_wanted = target_speed - m_speed;
|
||||||
if (slippery) {
|
|
||||||
if (target_speed == v3f())
|
|
||||||
d_wanted = -m_speed * 0.05f;
|
|
||||||
else
|
|
||||||
d_wanted *= 0.1f;
|
|
||||||
}
|
|
||||||
|
|
||||||
d_wanted.Y = 0.0f;
|
d_wanted.Y = 0.0f;
|
||||||
f32 dl = d_wanted.getLength();
|
f32 dl = d_wanted.getLength();
|
||||||
if (dl > max_increase)
|
if (dl > max_increase)
|
||||||
@ -1038,3 +1028,52 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
|
|||||||
m_can_jump = false;
|
m_can_jump = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float LocalPlayer::getSlipFactor(Environment *env, const v3f &speedH)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!touching_ground)
|
||||||
|
return 1.0f;
|
||||||
|
|
||||||
|
float slip_factor = 1.0f;
|
||||||
|
// Slip on slippery nodes
|
||||||
|
const INodeDefManager *nodemgr = env->getGameDef()->ndef();
|
||||||
|
Map *map = &env->getMap();
|
||||||
|
const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(
|
||||||
|
floatToInt(getPosition() - v3f(0, 0.05f * BS, 0), BS)));
|
||||||
|
int slippery = 0;
|
||||||
|
if (f.walkable) {
|
||||||
|
slippery = itemgroup_get(f.groups, "slippery");
|
||||||
|
} else if (is_slipping) {
|
||||||
|
// slipping over an edge? Check surroundings for slippery nodes
|
||||||
|
slippery = 2 << 16; // guard value, bigger than all realistic ones
|
||||||
|
for (int z = 0; z <= 1; z++) {
|
||||||
|
for (int x = 0; x <= 1; x++) {
|
||||||
|
// this should cover all nodes surrounding player position
|
||||||
|
v3f offset((x - 0.5f) * BS, 0.05f * BS, (z - 0.5f) * BS);
|
||||||
|
const ContentFeatures &f2 = nodemgr->get(map->getNodeNoEx(
|
||||||
|
floatToInt(getPosition() - offset, BS)));
|
||||||
|
if (f2.walkable) {
|
||||||
|
// find least slippery node we might be standing on
|
||||||
|
int s = itemgroup_get(f2.groups, "slippery");
|
||||||
|
if (s < slippery)
|
||||||
|
slippery = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// without any hits, ignore slippery
|
||||||
|
if (slippery >= (2 << 16))
|
||||||
|
slippery = 0;
|
||||||
|
}
|
||||||
|
if (slippery >= 1) {
|
||||||
|
if (speedH == v3f(0.0f)) {
|
||||||
|
slippery = slippery * 2;
|
||||||
|
}
|
||||||
|
slip_factor = core::clamp(1.0f / (slippery + 1), 0.001f, 1.0f);
|
||||||
|
is_slipping = true;
|
||||||
|
} else {
|
||||||
|
// remember this to avoid checking the edge case above too often
|
||||||
|
is_slipping = false;
|
||||||
|
}
|
||||||
|
return slip_factor;
|
||||||
|
}
|
||||||
|
@ -60,6 +60,7 @@ public:
|
|||||||
u8 liquid_viscosity = 0;
|
u8 liquid_viscosity = 0;
|
||||||
bool is_climbing = false;
|
bool is_climbing = false;
|
||||||
bool swimming_vertical = false;
|
bool swimming_vertical = false;
|
||||||
|
bool is_slipping = false;
|
||||||
|
|
||||||
float physics_override_speed = 1.0f;
|
float physics_override_speed = 1.0f;
|
||||||
float physics_override_jump = 1.0f;
|
float physics_override_jump = 1.0f;
|
||||||
@ -143,11 +144,10 @@ public:
|
|||||||
void setCollisionbox(const aabb3f &box) { m_collisionbox = box; }
|
void setCollisionbox(const aabb3f &box) { m_collisionbox = box; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// clang-format off
|
void accelerateHorizontal(const v3f &target_speed, const f32 max_increase);
|
||||||
void accelerateHorizontal(const v3f &target_speed, f32 max_increase, bool slippery);
|
|
||||||
// clang-format on
|
|
||||||
void accelerateVertical(const v3f &target_speed, const f32 max_increase);
|
void accelerateVertical(const v3f &target_speed, const f32 max_increase);
|
||||||
bool updateSneakNode(Map *map, const v3f &position, const v3f &sneak_max);
|
bool updateSneakNode(Map *map, const v3f &position, const v3f &sneak_max);
|
||||||
|
float getSlipFactor(Environment *env, const v3f &speedH);
|
||||||
|
|
||||||
v3f m_position;
|
v3f m_position;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user