Updated height and interval handling if the ball is getting
closer to the target. Now the ball behaviour keeps being smooth while it is getting closer to the target. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@9323 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
68765a2228
commit
2c3e5395c6
@ -67,10 +67,9 @@ RubberBall::RubberBall(Kart *kart) : Flyable(kart, PowerupManager::POWERUP_RUBBE
|
||||
// target:
|
||||
m_aiming_at_target = false;
|
||||
m_wrapped_around = false;
|
||||
m_previous_height = 0.0f;
|
||||
m_timer = 0.0f;
|
||||
m_interval = m_st_interval;
|
||||
|
||||
m_height = m_max_height;
|
||||
} // RubberBall
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -160,56 +159,62 @@ void RubberBall::update(float dt)
|
||||
m_wrapped_around = old_distance > 0.9f * track_length &&
|
||||
m_distance_along_track < 10.0f;
|
||||
|
||||
|
||||
// FIXME: do we want to test if we have overtaken the target kart?
|
||||
|
||||
LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
|
||||
|
||||
float target_distance =
|
||||
world->getDistanceDownTrackForKart(m_target->getWorldKartId());
|
||||
|
||||
|
||||
float x = target_distance - m_distance_along_track;
|
||||
if(x<0)
|
||||
x+=track_length;
|
||||
|
||||
// When the ball hits the floor, we adjust maximum height and
|
||||
// interval so that the ball bounces faster when it is getting
|
||||
// closer to the target.
|
||||
m_timer += dt;
|
||||
if(m_timer>m_interval)
|
||||
{
|
||||
m_timer -= m_interval;
|
||||
|
||||
float height;
|
||||
if(x>50)
|
||||
{
|
||||
// Consider f(x) = x*(x-m_intervall), which is a parabolic function
|
||||
// with f(0) = 0, f(m_intervall)=0. We then scale this function to
|
||||
// fulfill: f(m_intervall/2) = m_max_height, or:
|
||||
// f(m_interval/2) = -m_interval^2/4 = m_max_height
|
||||
// --> scale with m_max_height / -m_interval^2/4
|
||||
float f = m_max_height / (-0.25f*m_interval*m_interval);
|
||||
height = m_timer * (m_timer-m_interval) * f;
|
||||
LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
|
||||
float target_distance =
|
||||
world->getDistanceDownTrackForKart(m_target->getWorldKartId());
|
||||
|
||||
// If we start the squashing as soon as the height is smaller than
|
||||
// height of the ball, it looks to extreme. So a ratio r of the height
|
||||
// of the ball and the current height of the object is used to tweak
|
||||
// the look a bit.
|
||||
float r = 2.0f;
|
||||
if(r*height<m_extend.getY())
|
||||
m_node->setScale(core::vector3df(1.0f, r*height/m_extend.getY(),
|
||||
1.0f));
|
||||
float distance = target_distance - m_distance_along_track;
|
||||
if(distance<0)
|
||||
distance+=track_length;
|
||||
if(distance<50)
|
||||
{
|
||||
// Some experimental formulas
|
||||
m_height = 0.5f*sqrt(distance);
|
||||
m_interval = m_height / 10.0f;
|
||||
}
|
||||
else
|
||||
m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
{
|
||||
// Reset the values in case that the ball was already trying
|
||||
// to get closer to the target, and then the target disappears
|
||||
// (e.g. is eliminated or finishes the race).
|
||||
m_interval = m_st_interval;
|
||||
m_height = m_max_height;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
height = 0.5f*sqrt(x)*fabsf(sinf(10.0f*log(0.005f*(x+5.0f))));
|
||||
}
|
||||
#if 0
|
||||
printf("ball z %f dt %f x %f h %f, ah %f\n",
|
||||
next_xyz.getZ(),dt,
|
||||
x, height1, average_height);
|
||||
#endif
|
||||
|
||||
// Consider f(x) = x*(x-m_intervall), which is a parabolic function
|
||||
// with f(0) = 0, f(m_intervall)=0. We then scale this function to
|
||||
// fulfill: f(m_intervall/2) = m_height, or:
|
||||
// f(m_interval/2) = -m_interval^2/4 = m_height
|
||||
// --> scale with m_height / -m_interval^2/4
|
||||
float f = m_height / (-0.25f*m_interval*m_interval);
|
||||
float height = m_timer * (m_timer-m_interval) * f;
|
||||
next_xyz.setY(getHoT() + height);
|
||||
|
||||
// If we start squashing the ball as soon as the height is smaller than
|
||||
// height of the ball, it looks to extreme. So a ratio r of the height
|
||||
// of the ball and the current height of the object is used to tweak
|
||||
// the look a bit.
|
||||
float r = 2.0f;
|
||||
if(r*height<m_extend.getY())
|
||||
m_node->setScale(core::vector3df(1.0f, r*height/m_extend.getY(),
|
||||
1.0f));
|
||||
else
|
||||
m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
|
||||
setXYZ(next_xyz);
|
||||
} // update
|
||||
|
||||
|
@ -45,17 +45,9 @@ private:
|
||||
* point we aimed at and have to aim at the next point. */
|
||||
float m_distance_along_track;
|
||||
|
||||
/** Since the distance between target and ball can vary a bit,
|
||||
* using it to determine height on a formula is not smooth (e.g.
|
||||
* ball can actually go up a bit during one frame while actually
|
||||
* going down). Therefore we use a weighted average of previous
|
||||
* height newly determined height. */
|
||||
float m_previous_height;
|
||||
|
||||
/** A class variable to store the default interval size. */
|
||||
static float m_st_interval;
|
||||
|
||||
|
||||
/** How long it takes from one bounce of the ball to the next. */
|
||||
float m_interval;
|
||||
|
||||
@ -63,6 +55,10 @@ private:
|
||||
* It is always between 0 and m_interval. */
|
||||
float m_timer;
|
||||
|
||||
/** The maximum height of the ball. This value will be reduced if the
|
||||
* ball gets closer to the target. */
|
||||
float m_height;
|
||||
|
||||
/** True if the ball just crossed the start line, i.e. its
|
||||
* distance changed from close to length of track in the
|
||||
* previous time step to a bit over zero now. */
|
||||
|
Loading…
Reference in New Issue
Block a user