Fix swatter issue

This commit is contained in:
Benau 2015-12-08 16:47:42 +08:00
parent c789b1a8df
commit 140a229f71
4 changed files with 137 additions and 194 deletions

View File

@ -59,7 +59,10 @@ Swatter::Swatter(AbstractKart *kart, bool was_bomb,
: AttachmentPlugin(kart)
{
m_animation_phase = SWATTER_AIMING;
m_discard_now = false;
m_discard_timeout = 0.0f;
m_target = NULL;
m_closest_kart = NULL;
m_removing_bomb = was_bomb;
m_bomb_scene_node = bomb_scene_node;
m_swat_bomb_frame = 0.0f;
@ -112,7 +115,8 @@ Swatter::~Swatter()
*/
bool Swatter::updateAndTestFinished(float dt)
{
bool discard_now = false;
if (!m_discard_now)
{
if (m_removing_bomb)
{
m_swat_bomb_frame += dt*25.0f;
@ -122,10 +126,10 @@ bool Swatter::updateAndTestFinished(float dt)
if (m_swat_bomb_frame >= 32.5f && m_bomb_scene_node != NULL)
{
m_bomb_scene_node->setPosition(m_bomb_scene_node->getPosition() +
core::vector3df(-dt*15.0f, 0.0f, 0.0f) );
m_bomb_scene_node->setRotation(m_bomb_scene_node->getRotation() +
core::vector3df(-dt*15.0f, 0.0f, 0.0f) );
m_bomb_scene_node->setPosition(m_bomb_scene_node
->getPosition() + core::vector3df(-dt*15.0f, 0.0f, 0.0f) );
m_bomb_scene_node->setRotation(m_bomb_scene_node
->getRotation() + core::vector3df(-dt*15.0f, 0.0f, 0.0f) );
}
if (m_swat_bomb_frame >= m_scene_node->getEndFrame())
@ -150,15 +154,20 @@ bool Swatter::updateAndTestFinished(float dt)
{
chooseTarget();
pointToTarget();
if(!m_target) break;
if(!m_target || !m_closest_kart) break;
// Is the target too near?
float dist_to_target2 =
(m_target->getXYZ()- Vec3(m_scene_node->getAbsolutePosition()))
.length2();
// Get the node corresponding to the joint at the center of the
// swatter (by swatter, I mean the thing hold in the hand, not
// the whole thing)
scene::ISceneNode* swatter_node =
m_scene_node->getJointNode("Swatter");
assert(swatter_node);
Vec3 swatter_pos = swatter_node->getAbsolutePosition();
float dist2 = (m_closest_kart->getXYZ()-swatter_pos).length2();
float min_dist2
= m_kart->getKartProperties()->getSwatterDistance();
if(dist_to_target2 < min_dist2)
if(dist2 < min_dist2)
{
// Start squashing
m_animation_phase = SWATTER_TO_TARGET;
@ -167,13 +176,16 @@ bool Swatter::updateAndTestFinished(float dt)
m_scene_node->setCurrentFrame(0.0f);
m_scene_node->setLoopMode(false);
m_scene_node->setAnimationSpeed(SWATTER_ANIMATION_SPEED);
// Play swat sound
m_swat_sound->setPosition(swatter_pos);
m_swat_sound->play();
}
}
break;
case SWATTER_TO_TARGET:
{
pointToTarget();
const float middle_frame = m_scene_node->getEndFrame()/2.0f;
float current_frame = m_scene_node->getFrameNr();
@ -182,13 +194,15 @@ bool Swatter::updateAndTestFinished(float dt)
{
// Squash the karts and items around and
// change the current phase
if (squashThingsAround() &&
race_manager->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES)
{
//Remove swatter from kart in 3 strikes battle after one successful hit
discard_now = true;
}
squashThingsAround();
m_animation_phase = SWATTER_FROM_TARGET;
if (race_manager->getMinorMode()==
RaceManager::MINOR_MODE_3_STRIKES)
{
// Remove swatter from kart in 3 strikes battle
// after one successful hit
m_discard_now = true;
}
}
}
break;
@ -196,11 +210,11 @@ bool Swatter::updateAndTestFinished(float dt)
case SWATTER_FROM_TARGET:
break;
}
}
else
m_discard_timeout += dt;
// If the swatter is used up, trigger cleaning up
// TODO: use a timeout
// TODO: how does it work currently...?
return (discard_now ? true : false);
return (m_discard_now && m_discard_timeout > 0.5f ? true : false);
} // updateAndTestFinished
// ----------------------------------------------------------------------------
@ -240,6 +254,7 @@ void Swatter::chooseTarget()
}
}
m_target = closest_kart; // may be NULL
m_closest_kart = closest_kart;
}
// ----------------------------------------------------------------------------
@ -267,42 +282,13 @@ void Swatter::pointToTarget()
// ----------------------------------------------------------------------------
/** Squash karts or items that are around the end position (determined using
* a joint) of the swatter.
* \return True if target kart is hit.
*/
bool Swatter::squashThingsAround()
void Swatter::squashThingsAround()
{
const KartProperties *kp = m_kart->getKartProperties();
// Square of the minimum distance
float min_dist2 = kp->getSwatterDistance();
const World* world = World::getWorld();
// Get the node corresponding to the joint at the center of the swatter
// (by swatter, I mean the thing hold in the hand, not the whole thing)
scene::ISceneNode* swatter_node = m_scene_node->getJointNode("Swatter");
assert(swatter_node);
Vec3 swatter_pos = swatter_node->getAbsolutePosition();
m_swat_sound->setPosition(swatter_pos);
m_swat_sound->play();
bool target_is_hit = false;
// Squash karts around
for(unsigned int i = 0; i < world->getNumKarts(); i++)
{
AbstractKart *kart = world->getKart(i);
// TODO: isSwatterReady()
if(kart->isEliminated() || kart==m_kart)
continue;
// don't swat an already hurt kart
if (kart->isInvulnerable() || kart->isSquashed())
continue;
float dist2 = (kart->getXYZ()-swatter_pos).length2();
if(dist2 >= min_dist2) continue; // too far away, ignore this kart
kart->setSquash(kp->getSwatterSquashDuration(), kp->getSwatterSquashSlowdown());
target_is_hit = true;
m_closest_kart->setSquash(kp->getSwatterSquashDuration(),
kp->getSwatterSquashSlowdown());
//Handle achievement if the swatter is used by the current player
const StateManager::ActivePlayer *const ap = m_kart->getController()
@ -313,18 +299,16 @@ bool Swatter::squashThingsAround()
"swatter", 1);
}
if (kart->getAttachment()->getType()==Attachment::ATTACH_BOMB)
if (m_closest_kart->getAttachment()->getType()==Attachment::ATTACH_BOMB)
{ // make bomb explode
kart->getAttachment()->update(10000);
m_closest_kart->getAttachment()->update(10000);
HitEffect *he = new Explosion(m_kart->getXYZ(), "explosion", "explosion.xml");
if(m_kart->getController()->isPlayerController())
he->setPlayerKartHit();
projectile_manager->addHitEffect(he);
ExplosionAnimation::create(kart);
ExplosionAnimation::create(m_closest_kart);
} // if kart has bomb attached
World::getWorld()->kartHit(kart->getWorldKartId());
} // for i < num_kartrs
return target_is_hit;
World::getWorld()->kartHit(m_closest_kart->getWorldKartId());
// TODO: squash items
} // squashThingsAround

View File

@ -49,9 +49,17 @@ private:
enum {SWATTER_AIMING, SWATTER_TO_TARGET, SWATTER_FROM_TARGET}
m_animation_phase;
/** True if the swatter will be discarded now. */
bool m_discard_now;
/** Require for the sfx to complete. */
float m_discard_timeout;
/** The kart the swatter is aiming at. */
Moveable *m_target;
AbstractKart *m_closest_kart;
SFXBase *m_swat_sound;
/** True if the swatter is removing an attached bomb. */
@ -91,7 +99,7 @@ private:
void pointToTarget();
/** Squash karts or items that are around the end position (determined using a joint) of the swatter */
bool squashThingsAround();
void squashThingsAround();
}; // Swatter
#endif

View File

@ -98,18 +98,17 @@ void BattleAI::reset()
{
m_current_node = BattleGraph::UNKNOWN_POLY;
m_target_node = BattleGraph::UNKNOWN_POLY;
m_closest_kart = NULL;
m_closest_kart_node = BattleGraph::UNKNOWN_POLY;
m_closest_kart_point = Vec3(0, 0, 0);
m_closest_kart_pos_data = {0};
m_cur_kart_pos_data = {0};
m_is_stuck = false;
m_is_uturn = false;
m_is_steering_overridden = false;
m_target_point = Vec3(0, 0, 0);
m_time_since_last_shot = 0.0f;
m_time_since_driving = 0.0f;
m_time_since_reversing = 0.0f;
m_time_since_steering_overridden = 0.0f;
m_time_since_uturn = 0.0f;
m_on_node.clear();
m_path_corners.clear();
@ -166,7 +165,6 @@ void BattleAI::update(float dt)
findClosestKart(true);
findTarget();
handleItems(dt);
handleSwatter();
if (m_kart->getSpeed() > 15.0f && m_cur_kart_pos_data.angle < 0.2f)
{
@ -308,22 +306,17 @@ void BattleAI::findClosestKart(bool difficulty)
}
if (!difficulty)
{
m_closest_kart = m_world->getKart(closest_kart_num);
checkPosition(m_closest_kart_point, &m_closest_kart_pos_data);
}
} // findClosestKart
//-----------------------------------------------------------------------------
void BattleAI::findTarget()
{
// Don't try to hit a player continuously with swatter for easy and medium
// mode, which make it too aggressive
const bool continuous_swatter =
m_kart->getAttachment()->getType() == Attachment::ATTACH_SWATTER &&
(m_cur_difficulty == RaceManager::DIFFICULTY_HARD ||
m_cur_difficulty == RaceManager::DIFFICULTY_BEST);
// Find a suitable target to drive to, either powerup or kart
if (m_kart->getPowerup()->getType() == PowerupManager::POWERUP_NOTHING &&
!continuous_swatter)
if (m_kart->getPowerup()->getType() == PowerupManager::POWERUP_NOTHING)
handleItemCollection(&m_target_point , &m_target_node);
else
{
@ -389,19 +382,6 @@ void BattleAI::handleSteering(const float dt)
if (m_current_node == BattleGraph::UNKNOWN_POLY ||
m_target_node == BattleGraph::UNKNOWN_POLY) return;
if (m_is_steering_overridden)
{
// Steering is overridden to avoid collision with the target kart
m_time_since_steering_overridden += dt;
setSteering(-1.0f, dt);
if (m_time_since_steering_overridden > 0.5f)
{
m_is_steering_overridden = false;
m_time_since_steering_overridden = 0.0f;
}
return;
}
if (m_target_node == m_current_node)
{
// Very close to the item, steer directly
@ -452,27 +432,6 @@ void BattleAI::handleSteering(const float dt)
}
} // handleSteering
//-----------------------------------------------------------------------------
/** Make AI avoid collison with target as much as possible when attacking with
* swatter.
*/
void BattleAI::handleSwatter()
{
if (m_is_steering_overridden) return;
if (m_kart->getAttachment()->getType() == Attachment::ATTACH_SWATTER)
{
findClosestKart(false);
if (m_closest_kart_pos_data.angle < 0.25f &&
m_closest_kart_pos_data.distance < 5.0f)
{
// Check whether it's straight ahead towards target
m_is_steering_overridden = true;
}
}
} // handleSwatter
//-----------------------------------------------------------------------------
/** This function finds the polyon edges(portals) that the AI will cross before
* reaching its destination. We start from the current polygon and call
@ -632,18 +591,6 @@ void BattleAI::handleBraking()
{
m_controls->m_brake = false;
if (m_is_steering_overridden && m_kart->getSpeed() > 10.0f)
{
// Hard-brake for too fast
if (m_kart->getSpeed() > 15.0f)
{
m_controls->m_accel = -12.5f;
return;
}
m_controls->m_brake = true;
return;
}
// A kart will not brake when the speed is already slower than this
// value. This prevents a kart from going too slow (or even backwards)
// in tight curves.
@ -741,6 +688,9 @@ void BattleAI::handleItems(const float dt)
// Find a closest kart again, this time we ignore difficulty
findClosestKart(false);
if (!m_closest_kart) return;
m_time_since_last_shot += dt;
float min_bubble_time = 2.0f;
@ -797,7 +747,8 @@ void BattleAI::handleItems(const float dt)
// Leave some time between shots
if (m_time_since_last_shot < 1.0f) break;
if (m_closest_kart_pos_data.distance < 25.0f)
if (m_closest_kart_pos_data.distance < 25.0f &&
!m_closest_kart->isInvulnerable())
{
m_controls->m_fire = true;
m_controls->m_look_back = fire_behind;
@ -829,11 +780,15 @@ void BattleAI::handleItems(const float dt)
case PowerupManager::POWERUP_SWATTER:
{
// Squared distance for which the swatter works
float d2 = m_kart->getKartProperties()->getSwatterDistance();
// if the kart has a shield, do not break it by using a swatter.
if (m_kart->getShieldTime() > min_bubble_time)
break;
if (m_closest_kart_pos_data.distance < 7.0f)
if (!m_closest_kart->isSquashed() &&
m_closest_kart_pos_data.distance < d2 &&
m_closest_kart->getSpeed() < m_kart->getSpeed())
{
m_controls->m_fire = true;
m_controls->m_look_back = false;

View File

@ -61,6 +61,9 @@ private:
int m_closest_kart_node;
Vec3 m_closest_kart_point;
/** Pointer to the closest kart around this kart. */
AbstractKart *m_closest_kart;
posData m_closest_kart_pos_data;
posData m_cur_kart_pos_data;
@ -71,10 +74,6 @@ private:
* counting down. */
bool m_is_stuck;
/** Indicates that the steering of kart is overridden, and
* m_time_since_steering_overridden is counting down. */
bool m_is_steering_overridden;
/** Indicates that the kart need a uturn to reach a node behind, and
* m_time_since_uturn is counting down. */
bool m_is_uturn;
@ -108,9 +107,6 @@ private:
/** This is a timer that counts down when the kart is starting to drive. */
float m_time_since_driving;
/** This is a timer that counts down when the steering of kart is overridden. */
float m_time_since_steering_overridden;
/** This is a timer that counts down when the kart is doing u-turn. */
float m_time_since_uturn;