Implement dynamic basket ball speed, fix #2783
This commit is contained in:
parent
6f50c234a3
commit
073708c97e
@ -87,6 +87,9 @@
|
||||
power: The power of the kart (the engine power needed to accelerate
|
||||
at a given pace is proportional to mass)
|
||||
max-speed: The base maximum speed of the kart in m/s
|
||||
generic-max-speed: Must have the same value as max-speed. This
|
||||
is the max speed independently of kart type and
|
||||
of handicap, which is used by basket balls.
|
||||
brake-factor: Value used when braking.
|
||||
brake-time-increase: The brake force is multiplied by
|
||||
(1 + brake_time) * brake_time_increase - i.e. the longer the
|
||||
@ -94,7 +97,7 @@
|
||||
max-speed-reverse-ratio is the percentage of max speed for reverse
|
||||
gear.
|
||||
-->
|
||||
<engine power="950" max-speed="25" brake-factor="15"
|
||||
<engine power="950" max-speed="25" generic-max-speed="25" brake-factor="15"
|
||||
brake-time-increase="6" max-speed-reverse-ratio="0.65" />
|
||||
|
||||
<!-- Simulated gears
|
||||
@ -342,15 +345,15 @@
|
||||
<!-- The different difficulties (like easy, medium, hard) -->
|
||||
<difficulties>
|
||||
<characteristic name="easy">
|
||||
<engine power="*0.7" max-speed="*0.6" />
|
||||
<engine power="*0.7" max-speed="*0.6" generic-max-speed="*0.6" />
|
||||
<plunger in-face-time="3" />
|
||||
</characteristic>
|
||||
<characteristic name="medium">
|
||||
<engine power="*0.83" max-speed="*0.8" />
|
||||
<engine power="*0.83" max-speed="*0.8" generic-max-speed="*0.8" />
|
||||
<plunger in-face-time="4" />
|
||||
</characteristic>
|
||||
<characteristic name="hard">
|
||||
<engine power="*0.92" max-speed="*0.92" />
|
||||
<engine power="*0.92" max-speed="*0.92" generic-max-speed="*0.92" />
|
||||
</characteristic>
|
||||
<!-- This doesn't need to be changed because the most fast/heavy/extreme
|
||||
values should also be the default ones. -->
|
||||
|
@ -16,6 +16,22 @@
|
||||
<item name="switch" icon="swap-icon.png" />
|
||||
<item name="swatter" icon="swatter-icon.png" />
|
||||
<!-- interval: How long a single bounce takes.
|
||||
min-speed-offset: The speed of the ball is calculated
|
||||
by adding the speed-offset to the difficulty's
|
||||
max-speed. min-speed-offset is used when the
|
||||
ball is closer than min-offset-distance
|
||||
to the target.
|
||||
max-speed-offset: The additional speed of the ball when
|
||||
farther than max-offset-distance.
|
||||
speed : defines the initial speed. Mainly kept for
|
||||
compatibility with flyable class
|
||||
min-offset-distance: The distance under which the ball is
|
||||
at minimal speed.
|
||||
max-offset-distance: The distance over which the ball is
|
||||
at maximal speed. If it is not equal to
|
||||
min-offset-distance, the ball speeds between
|
||||
both is a weighted average of the min and
|
||||
max speed.
|
||||
max-height: The maximum height of a bounce.
|
||||
min-height: Unused mostly, but defines implicitly
|
||||
the starting height (as average of
|
||||
@ -57,7 +73,12 @@
|
||||
tunneling.
|
||||
-->
|
||||
<item name="rubber-ball" icon="rubber_ball-icon.png"
|
||||
model="rubber_ball.spm" speed="35.0"
|
||||
model="rubber_ball.spm"
|
||||
speed="40.0"
|
||||
min-speed-offset="9.0"
|
||||
max-speed-offset="29.0"
|
||||
min-offset-distance="50.0"
|
||||
max-offset-distance="250.0"
|
||||
interval="1"
|
||||
max-height="4.0" min-height="0"
|
||||
fast-ping-distance="50"
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "items/attachment.hpp"
|
||||
#include "items/projectile_manager.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/rewind_info.hpp"
|
||||
@ -49,6 +50,10 @@ int RubberBall::m_st_delete_ticks;
|
||||
float RubberBall::m_st_max_height_difference;
|
||||
float RubberBall::m_st_fast_ping_distance;
|
||||
float RubberBall::m_st_early_target_factor;
|
||||
float RubberBall::m_st_min_speed_offset;
|
||||
float RubberBall::m_st_max_speed_offset;
|
||||
float RubberBall::m_st_min_offset_distance;
|
||||
float RubberBall::m_st_max_offset_distance;
|
||||
int RubberBall::m_next_id = 0;
|
||||
|
||||
|
||||
@ -305,16 +310,21 @@ void RubberBall::getNextControlPoint()
|
||||
*/
|
||||
void RubberBall::init(const XMLNode &node, scene::IMesh *rubberball)
|
||||
{
|
||||
m_st_interval = 1.0f;
|
||||
m_st_squash_duration = 3.0f;
|
||||
m_st_squash_slowdown = 0.5f;
|
||||
m_st_min_interpolation_distance = 30.0f;
|
||||
m_st_target_distance = 50.0f;
|
||||
m_st_target_max_angle = 25.0f;
|
||||
m_st_interval = 1.0f;
|
||||
m_st_squash_duration = 3.0f;
|
||||
m_st_squash_slowdown = 0.5f;
|
||||
m_st_min_interpolation_distance = 30.0f;
|
||||
m_st_target_distance = 50.0f;
|
||||
m_st_target_max_angle = 25.0f;
|
||||
m_st_delete_ticks = stk_config->time2Ticks(10.0f);
|
||||
m_st_max_height_difference = 10.0f;
|
||||
m_st_fast_ping_distance = 50.0f;
|
||||
m_st_early_target_factor = 1.0f;
|
||||
m_st_max_height_difference = 10.0f;
|
||||
m_st_fast_ping_distance = 50.0f;
|
||||
m_st_early_target_factor = 1.0f;
|
||||
m_st_min_speed_offset = 8.0f;
|
||||
m_st_max_speed_offset = 28.0f;
|
||||
m_st_min_offset_distance = 50.0f;
|
||||
m_st_max_offset_distance = 250.0f;
|
||||
|
||||
|
||||
if(!node.get("interval", &m_st_interval))
|
||||
Log::warn("powerup", "No interval specified for basket ball.");
|
||||
@ -350,6 +360,28 @@ void RubberBall::init(const XMLNode &node, scene::IMesh *rubberball)
|
||||
if(!node.get("early-target-factor", &m_st_early_target_factor))
|
||||
Log::warn("powerup",
|
||||
"No early-target-factor specified for basket ball.");
|
||||
if(!node.get("min-speed-offset", &m_st_min_speed_offset))
|
||||
Log::warn("powerup", "No min-speed-offset specified for basket ball.");
|
||||
if(!node.get("max-speed-offset", &m_st_max_speed_offset))
|
||||
Log::warn("powerup", "No max-speed-offset specified for basket ball.");
|
||||
if(!node.get("min-offset-distance", &m_st_min_offset_distance))
|
||||
Log::warn("powerup", "No min-offset-distance specified for basket ball.");
|
||||
if(!node.get("max-offset-distance", &m_st_max_offset_distance))
|
||||
Log::warn("powerup", "No max-offset-distance specified for basket ball.");
|
||||
|
||||
|
||||
//sanity checks
|
||||
if (m_st_min_speed_offset < 10.0f)
|
||||
m_st_min_speed_offset = 10.0f;
|
||||
if (m_st_min_speed_offset > m_st_max_speed_offset)
|
||||
{
|
||||
m_st_max_speed_offset = m_st_min_speed_offset;
|
||||
}
|
||||
if (m_st_max_offset_distance <= (m_st_min_offset_distance + 10.0f))
|
||||
{
|
||||
m_st_max_offset_distance = m_st_min_offset_distance + 10.0f;
|
||||
}
|
||||
|
||||
Flyable::init(node, rubberball, PowerupManager::POWERUP_RUBBERBALL);
|
||||
} // init
|
||||
|
||||
@ -395,6 +427,9 @@ bool RubberBall::updateAndDelete(int ticks)
|
||||
computeTarget();
|
||||
updateDistanceToTarget();
|
||||
|
||||
//Update the speed
|
||||
updateWeightedSpeed(ticks);
|
||||
|
||||
// Determine the new position. This new position is only temporary,
|
||||
// since it still needs to be adjusted for the height of the terrain.
|
||||
Vec3 next_xyz;
|
||||
@ -507,6 +542,67 @@ void RubberBall::moveTowardsTarget(Vec3 *next_xyz, int ticks)
|
||||
|
||||
} // moveTowardsTarget
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Calculates the current speed of the basket ball.
|
||||
* The base basket ball speed is the target's normal max speed.
|
||||
* Then an offset is applied.
|
||||
* If closer than m_st_min_offset_distance ; it is m_st_min_speed_offset
|
||||
* If farther than m_st_max_offset_distance ; it is m_st_max_speed_offset
|
||||
* Else, it is a weighted average.
|
||||
* It takes up to 5 seconds to fully change its speed
|
||||
* (to avoid sudden big speed changes when the distance change suddenly
|
||||
* at ball throwing, because of paths, shortcuts, etc.)
|
||||
* If there is no target, it will keep its current speed
|
||||
*/
|
||||
void RubberBall::updateWeightedSpeed(int ticks)
|
||||
{
|
||||
// Don't change the speed if there is no target
|
||||
if (m_delete_ticks >= 10)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const KartProperties *kp = m_target->getKartProperties();
|
||||
// Get the speed depending on difficulty but not on kart type/handicap
|
||||
float targeted_speed = kp->getEngineGenericMaxSpeed();
|
||||
|
||||
float dt = stk_config->ticks2Time(ticks);
|
||||
|
||||
//Calculate the targeted weighted speed
|
||||
if (m_distance_to_target <= m_st_min_offset_distance)
|
||||
{
|
||||
targeted_speed += m_st_min_speed_offset;
|
||||
}
|
||||
else if (m_distance_to_target > m_st_max_offset_distance)
|
||||
{
|
||||
targeted_speed += m_st_max_speed_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
float weight = 1.0f;
|
||||
float offset = 0.0f;
|
||||
weight = (m_st_max_offset_distance - m_distance_to_target)
|
||||
/(m_st_max_offset_distance - m_st_min_offset_distance);
|
||||
offset = weight * m_st_min_speed_offset + (1-weight) * m_st_max_speed_offset;
|
||||
targeted_speed += offset;
|
||||
}
|
||||
//Update the real speed
|
||||
//Always >= 0
|
||||
float max_change = (m_st_max_speed_offset - m_st_min_speed_offset)*dt/(5.0f);
|
||||
if (m_speed-targeted_speed <= max_change && m_speed-targeted_speed >= -max_change)
|
||||
{
|
||||
m_speed = targeted_speed;
|
||||
}
|
||||
else if (m_speed < targeted_speed)
|
||||
{
|
||||
m_speed += max_change;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_speed -= max_change;
|
||||
}
|
||||
} // updateWeightedSpeed
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Uses Hermite splines (Catmull-Rom) to interpolate the position of the
|
||||
* ball between the control points. If the next point would be outside of
|
||||
|
@ -82,6 +82,20 @@ private:
|
||||
* ball will be deleted. */
|
||||
static int m_st_delete_ticks;
|
||||
|
||||
/** If the ball is closer to its target than min_offset_distance, the speed
|
||||
* in addition to the difficulty's default max speed. */
|
||||
static float m_st_min_speed_offset;
|
||||
|
||||
/** If the ball is farther to its target than max_offset_distance, the speed
|
||||
* in addition to the difficulty's default max speed. */
|
||||
static float m_st_max_speed_offset;
|
||||
|
||||
/** The distance to target under which the ball is the slowest */
|
||||
static float m_st_min_offset_distance;
|
||||
|
||||
/** The distance to target over which the ball is the fastest */
|
||||
static float m_st_max_offset_distance;
|
||||
|
||||
/** This factor is used to influence how much the rubber ball should aim
|
||||
* at its target early. It used the 'distance to center of track' of its
|
||||
* target, and adjusts the interpolation control points to be more or
|
||||
@ -195,6 +209,7 @@ private:
|
||||
float updateHeight();
|
||||
void interpolate(Vec3 *next_xyz, int ticks);
|
||||
void moveTowardsTarget(Vec3 *next_xyz, int ticks);
|
||||
void updateWeightedSpeed(int ticks);
|
||||
void initializeControlPoints(const Vec3 &xyz);
|
||||
float getTunnelHeight(const Vec3 &next_xyz,
|
||||
const float vertical_offset) const;
|
||||
|
@ -89,6 +89,8 @@ AbstractCharacteristic::ValueType AbstractCharacteristic::getType(
|
||||
return TYPE_FLOAT;
|
||||
case ENGINE_MAX_SPEED:
|
||||
return TYPE_FLOAT;
|
||||
case ENGINE_GENERIC_MAX_SPEED:
|
||||
return TYPE_FLOAT;
|
||||
case ENGINE_BRAKE_FACTOR:
|
||||
return TYPE_FLOAT;
|
||||
case ENGINE_BRAKE_TIME_INCREASE:
|
||||
@ -727,6 +729,18 @@ float AbstractCharacteristic::getEngineMaxSpeed() const
|
||||
return result;
|
||||
} // getEngineMaxSpeed
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
float AbstractCharacteristic::getEngineGenericMaxSpeed() const
|
||||
{
|
||||
float result;
|
||||
bool is_set = false;
|
||||
process(ENGINE_GENERIC_MAX_SPEED, &result, &is_set);
|
||||
if (!is_set)
|
||||
Log::fatal("AbstractCharacteristic", "Can't get characteristic %s",
|
||||
getName(ENGINE_GENERIC_MAX_SPEED).c_str());
|
||||
return result;
|
||||
} // getEngineGenericMaxSpeed
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
float AbstractCharacteristic::getEngineBrakeFactor() const
|
||||
{
|
||||
|
@ -95,6 +95,7 @@ public:
|
||||
// Engine
|
||||
ENGINE_POWER,
|
||||
ENGINE_MAX_SPEED,
|
||||
ENGINE_GENERIC_MAX_SPEED,
|
||||
ENGINE_BRAKE_FACTOR,
|
||||
ENGINE_BRAKE_TIME_INCREASE,
|
||||
ENGINE_MAX_SPEED_REVERSE_RATIO,
|
||||
@ -282,6 +283,7 @@ public:
|
||||
|
||||
float getEnginePower() const;
|
||||
float getEngineMaxSpeed() const;
|
||||
float getEngineGenericMaxSpeed() const;
|
||||
float getEngineBrakeFactor() const;
|
||||
float getEngineBrakeTimeIncrease() const;
|
||||
float getEngineMaxSpeedReverseRatio() const;
|
||||
|
@ -59,7 +59,7 @@ AbstractKart::AbstractKart(const std::string& ident,
|
||||
// Technically the mesh in m_kart_model needs to be grab'ed and
|
||||
// released when the kart is deleted, but since the original
|
||||
// kart_model is stored in the kart_properties all the time,
|
||||
// there is no risk of a mesh being deleted to early.
|
||||
// there is no risk of a mesh being deleted too early.
|
||||
m_kart_model = m_kart_properties->getKartModelCopy(ri);
|
||||
m_kart_width = m_kart_model->getWidth();
|
||||
m_kart_height = m_kart_model->getHeight();
|
||||
|
@ -679,6 +679,12 @@ float KartProperties::getEngineMaxSpeed() const
|
||||
return m_cached_characteristic->getEngineMaxSpeed();
|
||||
} // getEngineMaxSpeed
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
float KartProperties::getEngineGenericMaxSpeed() const
|
||||
{
|
||||
return m_cached_characteristic->getEngineGenericMaxSpeed();
|
||||
} // getEngineMaxSpeed
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
float KartProperties::getEngineBrakeFactor() const
|
||||
{
|
||||
|
@ -396,6 +396,7 @@ public:
|
||||
|
||||
float getEnginePower() const;
|
||||
float getEngineMaxSpeed() const;
|
||||
float getEngineGenericMaxSpeed() const;
|
||||
float getEngineBrakeFactor() const;
|
||||
float getEngineBrakeTimeIncrease() const;
|
||||
float getEngineMaxSpeedReverseRatio() const;
|
||||
|
@ -365,6 +365,8 @@ void XmlCharacteristic::load(const XMLNode *node)
|
||||
&m_values[ENGINE_POWER]);
|
||||
sub_node->get("max-speed",
|
||||
&m_values[ENGINE_MAX_SPEED]);
|
||||
sub_node->get("generic-max-speed",
|
||||
&m_values[ENGINE_GENERIC_MAX_SPEED]);
|
||||
sub_node->get("brake-factor",
|
||||
&m_values[ENGINE_BRAKE_FACTOR]);
|
||||
sub_node->get("brake-time-increase",
|
||||
|
Loading…
x
Reference in New Issue
Block a user