Added 'early targeting': the rubber ball will align its relative position

to the center of the track according to the relative distance of its target
(more precisely: it will move the interpolation control points). This
results in the ball being better align when it switches to aim-directly-at-
target mode, meaning that the target-distance can be reduced, hopefully
reducing the frequency with which tunneling happens.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@10016 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2011-10-18 20:14:03 +00:00
parent 81ce56c358
commit b9e4325560
7 changed files with 108 additions and 27 deletions

View File

@ -43,13 +43,23 @@
squash-duration: How long karts stay squashed.
delete-timer: How long before the ball is removed
if no suitable target is found.
early-target-factor: the rubber ball can use the
relative position of the kart to the
center of the track for improved targeting
(i.e. the ball will align its relative
position to the center of the track early).
This allows a lower target-distance to be
used since the ball is better aligned,
hopefully reducing the frequency of
tunneling.
-->
<item name="rubber-ball" icon="rubber_ball-icon.png"
model="rubber_ball.b3d" speed="35.0"
scale="1 1 1" interval="1"
max-height="4.0" min-height="0"
fast-ping-distance="50"
target-distance="25" target-max-angle = "90"
early-target-factor="1"
target-distance="15" target-max-angle = "90"
min-interpolation-distance="10"
squash-slowdown="0.5" squash-duration="3"
delete-time="5.0" max-height-difference="10" />

View File

@ -37,6 +37,7 @@ float RubberBall::m_st_target_max_angle;
float RubberBall::m_st_delete_time;
float RubberBall::m_st_max_height_difference;
float RubberBall::m_st_fast_ping_distance;
float RubberBall::m_st_early_target_factor;
int RubberBall::m_next_id = 0;
RubberBall::RubberBall(Kart *kart)
@ -64,6 +65,13 @@ RubberBall::RubberBall(Kart *kart)
setAdjustUpVelocity(false);
m_max_lifespan = 9999;
m_target = NULL;
m_aiming_at_target = false;
m_fast_ping = false;
// At the start the ball aims at quads till it gets close enough to the
// target:
m_height_timer = 0.0f;
m_interval = m_st_interval;
m_current_max_height = m_max_height;
m_ping_sfx = sfx_manager->createSoundSource("ball_bounce");
// Just init the previoux coordinates with some value that's not getXYZ()
m_previous_xyz = m_owner->getXYZ();
@ -73,18 +81,10 @@ RubberBall::RubberBall(Kart *kart)
computeTarget();
// initialises the current graph node
TrackSector::update(getXYZ());
initializeControlPoints(m_owner->getXYZ());
// At the start the ball aims at quads till it gets close enough to the
// target:
m_aiming_at_target = false;
m_fast_ping = false;
m_height_timer = 0.0f;
m_interval = m_st_interval;
m_current_max_height = m_max_height;
} // RubberBall
// ----------------------------------------------------------------------------
@ -209,8 +209,26 @@ void RubberBall::getNextControlPoint()
m_last_aimed_graph_node = next;
m_length_cp_2_3 = dist;
m_control_points[3] =
QuadGraph::get()->getQuadOfNode(m_last_aimed_graph_node).getCenter();
const Quad &quad =
QuadGraph::get()->getQuadOfNode(m_last_aimed_graph_node);
Vec3 aim = quad.getCenter();
// If we are close enough for the ball to hop faster, adjust the position
// relative to the center of the track depending on where the target is:
// if(m_fast_ping)
{
LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
float r = world->getTrackSector(m_target->getWorldKartId())
.getRelativeDistanceToCenter();
printf("ratio r %f, adjusting from %f %f ", r,
aim.getX(), aim.getZ());
aim -= m_st_early_target_factor * r
* QuadGraph::get()->getNode(m_last_aimed_graph_node)
.getCenterToRightVector();
printf(" to %f %f\n", aim.getX(), aim.getZ());
}
m_control_points[3] = aim;
} // getNextControlPoint
// ----------------------------------------------------------------------------
@ -230,6 +248,7 @@ void RubberBall::init(const XMLNode &node, scene::IMesh *bowling)
m_st_delete_time = 10.0f;
m_st_max_height_difference = 10.0f;
m_st_fast_ping_distance = 50.0f;
m_st_early_target_factor = 1.0f;
if(!node.get("interval", &m_st_interval))
printf("[powerup] Warning: no interval specified for rubber ball.\n");
@ -265,6 +284,10 @@ void RubberBall::init(const XMLNode &node, scene::IMesh *bowling)
if(m_st_fast_ping_distance < m_st_target_distance)
printf("Warning: ping-distance is smaller than target distance.\n"
"hat should not happen, but is ignored for now.\n");
if(!node.get("early-target-factor", &m_st_early_target_factor))
printf(
"[powerup] Warning: no early-target-factor specified for "
"rubber ball.\n");
Flyable::init(node, bowling, PowerupManager::POWERUP_RUBBERBALL);
} // init

View File

@ -83,6 +83,22 @@ private:
* ball will be deleted. */
static float m_st_delete_time;
/** 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
* less at the same (relative) distance from center. If the factor is
* 1, the rubber ball will aim to be at the same relative distance,
* if the factor is 0, the rubber ball will aim directly at the
* driveline points. A factor of 1 usually means that by the time
* the ball starts aiming directly at the target it is (nearly) on the
* same 'line', meaning it only has to go straight. On the other hand
* in a tunnel this might result in the ball being too far to the
* side, increasing the likelihood of the ball tunneling through
* (which can happen when the ball switches to aim-at-target mode,
* in a tight curve, so that the direct line to the target goes through
* a wall. */
static float m_st_early_target_factor;
/** A pointer to the target kart. */
const Kart *m_target;

View File

@ -61,6 +61,10 @@ GraphNode::GraphNode(unsigned int quad_index, unsigned int node_index)
// Only this 2d point is needed later
m_lower_center_2d = core::vector2df(m_lower_center.getX(),
m_lower_center.getZ() );
// The vector from the center of the quad to the middle of the right
// side of the quad
m_center_to_right = (quad[1]+quad[2])*0.5f - quad.getCenter();
} // GraphNode
// ----------------------------------------------------------------------------

View File

@ -33,7 +33,8 @@
class QuadGraph;
/**
* \brief This class stores a node of the graph, i.e. a list of successor edges.
* \brief This class stores a node of the graph, i.e. a list of successor
* edges.
* \ingroup tracks
*/
class GraphNode
@ -81,6 +82,9 @@ class GraphNode
/** Upper center point of the graph node. */
Vec3 m_upper_center;
/** A vector from the center of the quad to the right edge. */
Vec3 m_center_to_right;
/** Line between lower and upper center, saves computation in
* getDistanceFromLine() later. The line is 2d only since otherwise
* taller karts would have a larger distance from the center. It also
@ -118,6 +122,7 @@ public:
void getDistances(const Vec3 &xyz, Vec3 *result);
float getDistance2FromPoint(const Vec3 &xyz);
void setupPathsToNode();
void setChecklineRequirements(int latest_checkline);
// ------------------------------------------------------------------------
/** Returns the i-th successor node. */
unsigned int getSuccessor(unsigned int i) const
@ -167,7 +172,8 @@ public:
const Vec3& getUpperCenter() const {return m_upper_center;}
// ------------------------------------------------------------------------
/** Returns the center point of this graph node. */
const Vec3 getCenter() const {return (m_upper_center + m_lower_center) / 2.0f;}
const Vec3 getCenter() const
{return (m_upper_center + m_lower_center) / 2.0f;}
// ------------------------------------------------------------------------
/** Returns the length of the quad of this node. */
float getNodeLength() const
@ -193,12 +199,15 @@ public:
// If we have a path to node vector, use its information, otherwise
// (i.e. there is only one successor anyway) use this one successor.
return m_path_to_node.size()>0 ? m_path_to_node[n] : 0;
}
} // getSuccesorToReach
// ------------------------------------------------------------------------
void setChecklineRequirements(int latest_checkline);
const std::vector<int>& getChecklineRequirements() const { return m_checkline_requirements; }
/** Returns a vector from the center of the node to the middle of the
* right side. */
const Vec3 &getCenterToRightVector() const { return m_center_to_right; }
// ------------------------------------------------------------------------
/** Returns the checkline requirements of this graph node. */
const std::vector<int>& getChecklineRequirements() const
{ return m_checkline_requirements; }
}; // GraphNode
#endif

View File

@ -112,3 +112,21 @@ void TrackSector::rescue()
m_last_valid_graph_node = QuadGraph::get()->getNode(m_current_graph_node)
.getPredecessor();
} // rescue
// ----------------------------------------------------------------------------
/** Returns the relative distance of the corresponding kart from the center,
* i.e. a value between -1 and 1 inclusive.
* \return THe relative distance between -1.0f and +1.0f;
*/
float TrackSector::getRelativeDistanceToCenter() const
{
float w = QuadGraph::get()->getNode(m_current_graph_node).getPathWidth();
// w * 0.5 is the distance from center of the quad to the left or right
// This way we get a value between -1 and 1.
float ratio = getDistanceToCenter()/(w*0.5f);
if(ratio>1.0f)
ratio=1.0f;
else if(ratio<-1.0f)
ratio=-1.0f;
return ratio;
} // getRelativeDistanceToCenter

View File

@ -60,6 +60,7 @@ public:
void reset();
void rescue();
void update(const Vec3 &xyz);
float getRelativeDistanceToCenter() const;
// ------------------------------------------------------------------------
/** Returns how far the the object is from the start line. */
float getDistanceFromStart() const { return m_current_track_coords.getZ();}