void Footholdtree::limit_movement(PhysicsObject& phobj) const { if (phobj.hmobile()) { double crnt_x = phobj.crnt_x(); double next_x = phobj.next_x(); bool left = phobj.hspeed < 0.0f; double wall = get_wall(phobj.fhid, left, phobj.next_y()); bool collision = left ? crnt_x >= wall && next_x <= wall : crnt_x <= wall && next_x >= wall; if (!collision && phobj.is_flag_set(PhysicsObject::TURNATEDGES)) { wall = get_edge(phobj.fhid, left); collision = left ? crnt_x >= wall && next_x <= wall : crnt_x <= wall && next_x >= wall; } if (collision) { phobj.limitx(wall); phobj.clear_flag(PhysicsObject::TURNATEDGES); } } if (phobj.vmobile()) { double crnt_y = phobj.crnt_y(); double next_y = phobj.next_y(); auto ground = Range<double>( get_fh(phobj.fhid).ground_below(phobj.crnt_x()), get_fh(phobj.fhid).ground_below(phobj.next_x()) ); bool collision = crnt_y <= ground.first() && next_y >= ground.second(); if (collision) { phobj.limity(ground.second()); limit_movement(phobj); } else { if (next_y < borders.first()) { phobj.limity(borders.first()); } else if (next_y > borders.second()) { phobj.limity(borders.second()); } } } }
void Footholdtree::update_fh(PhysicsObject& phobj) const { if (phobj.type == PhysicsObject::FIXATED && phobj.fhid > 0) return; const Foothold& curfh = get_fh(phobj.fhid); bool checkslope = false; double x = phobj.crnt_x(); double y = phobj.crnt_y(); if (phobj.onground) { if (std::floor(x) > curfh.r()) { phobj.fhid = curfh.next(); } else if (std::ceil(x) < curfh.l()) { phobj.fhid = curfh.prev(); } if (phobj.fhid == 0) { phobj.fhid = get_fhid_below(x, y); } else { checkslope = true; } } else { phobj.fhid = get_fhid_below(x, y); } const Foothold& nextfh = get_fh(phobj.fhid); phobj.fhslope = nextfh.slope(); double ground = nextfh.ground_below(x); if (phobj.vspeed == 0.0 && checkslope) { double vdelta = abs(phobj.fhslope); if (phobj.fhslope < 0.0) { vdelta *= (ground - y); } else if (phobj.fhslope > 0.0) { vdelta *= (y - ground); } if (curfh.slope() != 0.0 || nextfh.slope() != 0.0) { if (phobj.hspeed > 0.0 && vdelta <= phobj.hspeed) { phobj.y = ground; } else if (phobj.hspeed < 0.0 && vdelta >= phobj.hspeed) { phobj.y = ground; } } } phobj.onground = phobj.y == ground; if (phobj.enablejd || phobj.is_flag_set(PhysicsObject::CHECKBELOW)) { uint16_t belowid = get_fhid_below(x, nextfh.ground_below(x) + 1.0); if (belowid > 0) { double nextground = get_fh(belowid).ground_below(x); phobj.enablejd = (nextground - ground) < 600.0; phobj.groundbelow = ground + 1.0; } else { phobj.enablejd = false; } phobj.clear_flag(PhysicsObject::CHECKBELOW); } if (phobj.fhlayer == 0 || phobj.onground) { phobj.fhlayer = nextfh.layer(); } }