Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/simulation2/components/CCmpUnitMotion_System.cpp
Show First 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | |||||
* Maximum distance-related multiplier. | * Maximum distance-related multiplier. | ||||
* NB: this value interacts with the "minimal pushing" force, | * NB: this value interacts with the "minimal pushing" force, | ||||
* as two perfectly overlapping units exert MAX_DISTANCE_FACTOR * Turn length in ms / REDUCTION_FACTOR | * as two perfectly overlapping units exert MAX_DISTANCE_FACTOR * Turn length in ms / REDUCTION_FACTOR | ||||
* of force on each other each turn. If this is below the minimal pushing force, any 2 units can entirely overlap. | * of force on each other each turn. If this is below the minimal pushing force, any 2 units can entirely overlap. | ||||
*/ | */ | ||||
constexpr entity_pos_t MAX_DISTANCE_FACTOR = entity_pos_t::FromFraction(5, 2); | constexpr entity_pos_t MAX_DISTANCE_FACTOR = entity_pos_t::FromFraction(5, 2); | ||||
/** | /** | ||||
* Maximum pushing multiplier for a single push calculation. | |||||
* This exists for numerical stability of the system between a lightweight and a heavy unit. | |||||
*/ | |||||
constexpr int MAX_PUSHING_MULTIPLIER = 4; | |||||
/** | |||||
* When two units collide, if their movement dot product is below this value, give them a perpendicular nudge instead of trying to push in the regular way. | * When two units collide, if their movement dot product is below this value, give them a perpendicular nudge instead of trying to push in the regular way. | ||||
*/ | */ | ||||
constexpr entity_pos_t PERPENDICULAR_NUDGE_THRESHOLD = entity_pos_t::FromFraction(-1, 10); | constexpr entity_pos_t PERPENDICULAR_NUDGE_THRESHOLD = entity_pos_t::FromFraction(-1, 10); | ||||
/** | /** | ||||
* Pushing is dampened by pushing pressure, but this is capped so that units still get pushed. | * Pushing is dampened by pushing pressure, but this is capped so that units still get pushed. | ||||
*/ | */ | ||||
constexpr int MAX_PUSH_DAMPING_PRESSURE = 160; | constexpr int MAX_PUSH_DAMPING_PRESSURE = 160; | ||||
▲ Show 20 Lines • Show All 659 Lines • ▼ Show 20 Lines | else | ||||
distanceFactor = Clamp((maxDist - offsetLength) / distanceFactor, entity_pos_t::Zero(), MAX_DISTANCE_FACTOR); | distanceFactor = Clamp((maxDist - offsetLength) / distanceFactor, entity_pos_t::Zero(), MAX_DISTANCE_FACTOR); | ||||
// Mark both as needing an update so they actually get moved. | // Mark both as needing an update so they actually get moved. | ||||
a.second.needUpdate = true; | a.second.needUpdate = true; | ||||
b.second.needUpdate = true; | b.second.needUpdate = true; | ||||
CFixedVector2D pushingDir = offset.Multiply(distanceFactor); | CFixedVector2D pushingDir = offset.Multiply(distanceFactor); | ||||
// Divide by an arbitrary constant to avoid pushing too much. | // These cannot be zero, checked in the schema. | ||||
a.second.push += pushingDir.Multiply(dt / PUSHING_REDUCTION_FACTOR); | entity_pos_t aWeight = a.second.cmpUnitMotion->GetWeight(); | ||||
b.second.push -= pushingDir.Multiply(dt / PUSHING_REDUCTION_FACTOR); | entity_pos_t bWeight = b.second.cmpUnitMotion->GetWeight(); | ||||
// Final corrections: | |||||
// - divide by an arbitrary constant to avoid pushing too much. | |||||
// - multiply by the weight ratio (limiting the maximum positive push for numerical accuracy). | |||||
entity_pos_t timeFactor = dt / PUSHING_REDUCTION_FACTOR; | |||||
entity_pos_t maxPushing = timeFactor * MAX_PUSHING_MULTIPLIER; | |||||
a.second.push += pushingDir.Multiply(std::min(bWeight.MulDiv(timeFactor, aWeight), maxPushing)); | |||||
b.second.push -= pushingDir.Multiply(std::min(aWeight.MulDiv(timeFactor, bWeight), maxPushing)); | |||||
// Use a constant factor to get a more general slowdown in crowded area. | // Use a constant factor to get a more general slowdown in crowded area. | ||||
// The distance factor heavily dampens units that are overlapping. | // The distance factor heavily dampens units that are overlapping. | ||||
int addedPressure = std::max(0, (PRESSURE_STATIC_FACTOR + (distanceFactor + entity_pos_t::FromInt(-2)/3) * PRESSURE_DISTANCE_FACTOR).Multiply(m_PushingPressureStrength).ToInt_RoundToZero()); | int addedPressure = std::max(0, (PRESSURE_STATIC_FACTOR + (distanceFactor + entity_pos_t::FromInt(-2)/3) * PRESSURE_DISTANCE_FACTOR).Multiply(m_PushingPressureStrength).ToInt_RoundToZero()); | ||||
a.second.pushingPressure = std::min(MAX_PRESSURE, a.second.pushingPressure + addedPressure); | a.second.pushingPressure = std::min(MAX_PRESSURE, a.second.pushingPressure + addedPressure); | ||||
b.second.pushingPressure = std::min(MAX_PRESSURE, b.second.pushingPressure + addedPressure); | b.second.pushingPressure = std::min(MAX_PRESSURE, b.second.pushingPressure + addedPressure); | ||||
#if DEBUG_RENDER | #if DEBUG_RENDER | ||||
Show All 24 Lines |
Wildfire Games · Phabricator