From a6efefaecca48293678dc29461a4749755973a3f Mon Sep 17 00:00:00 2001 From: Maikel de Vries Date: Wed, 30 Dec 2015 12:54:04 +0100 Subject: [PATCH] fix float physics for objects moving out of a liquid surface (#1523) This also fixes objects which previously jumped out of the water continuously, by adding an extra check to also capture faster moving objects. It could be made speed dependent, but that seems to be overkill for the situation. --- src/object/C4Object.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/object/C4Object.cpp b/src/object/C4Object.cpp index bacd66235..8006a5dd0 100644 --- a/src/object/C4Object.cpp +++ b/src/object/C4Object.cpp @@ -3348,7 +3348,7 @@ bool DoBridge(C4Object *clk) clk->Action.Time = 0; if (fWall && clk->Action.ComDir==COMD_Up) { - // special for roof above Clonk: The nonmoving roof is started at bridgelength before the Clonkl + // special for roof above Clonk: The nonmoving roof is started at bridgelength before the Clonk // so, when interrupted, an action time halfway through the action must be set clk->Action.Time = iBridgeTime; iBridgeTime += iBridgeTime; @@ -3375,8 +3375,18 @@ static void DoGravity(C4Object *cobj) if (cobj->xdir>+FloatFriction) cobj->xdir-=FloatFriction; if (cobj->rdir<-FloatFriction) cobj->rdir+=FloatFriction; if (cobj->rdir>+FloatFriction) cobj->rdir-=FloatFriction; - if (!GBackLiquid(cobj->GetX(),cobj->GetY()-1+ cobj->Def->Float*cobj->GetCon()/FullCon -1 )) - if (cobj->ydir<0) cobj->ydir=0; + // Reduce upwards speed when about to leave liquid to prevent eternal moving up and down. + // Check both for no liquid one and two pixels above the surface, because the object could + // skip one pixel as its speed can be more than 100. + int32_t y_float = cobj->GetY() - 1 + cobj->Def->Float * cobj->GetCon() / FullCon; + if (!GBackLiquid(cobj->GetX(), y_float - 1) || !GBackLiquid(cobj->GetX(), y_float - 2)) + if (cobj->ydir < 0) + { + // Reduce the upwards speed and set to zero for small values to prevent fluctuations. + cobj->ydir /= 2; + if (Abs(cobj->ydir) < C4REAL100(10)) + cobj->ydir = 0; + } } // Free fall gravity else if (~cobj->Category & C4D_StaticBack)