Merge branch 'master' of https://github.com/supertuxkart/stk-code
This commit is contained in:
commit
b3d59de288
@ -4,7 +4,7 @@ out vec4 FragColor;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec3 eyedir = vec3(gl_FragCoord.xy / screen, 1.);
|
||||
vec3 eyedir = vec3(mod(gl_FragCoord.xy, screen) / screen, 1.);
|
||||
eyedir = 2.0 * eyedir - 1.0;
|
||||
vec4 tmp = (InverseProjectionMatrix * vec4(eyedir, 1.));
|
||||
tmp /= tmp.w;
|
||||
|
@ -8,28 +8,28 @@
|
||||
<summary>A racing game</summary>
|
||||
<description>
|
||||
<p>
|
||||
SuperTuxKart is a fun 3D kart racing game.
|
||||
You can play with up to 4 friends on one PC, racing against each other or
|
||||
just try to beat the computer.
|
||||
Supertuxkart is a free 3D kart racing game, with a focus on having fun over
|
||||
realism. You can play with up to 4 friends on one PC, racing against each
|
||||
other, or try to beat the computer in single-player mode.
|
||||
</p>
|
||||
<p>
|
||||
See the great lighthouse or drive through the sand and visit the pyramids.
|
||||
Race underground or in space, watching the stars passing by.
|
||||
Have some rest under the palms on the beach (watching the other karts
|
||||
overtaking you :) ).
|
||||
But don't eat the bananas! Watch for bowling balls, plungers, bubble gum
|
||||
and cakes thrown by opponents.
|
||||
Race underground or in space, watching the stars pass by. Or rest under the
|
||||
palm trees on the beach, watching the other karts overtake you. But don't eat
|
||||
the bananas! Watch for bowling balls, plungers, bubble gum and cakes thrown by
|
||||
your opponents.
|
||||
</p>
|
||||
<p>
|
||||
You can do a single race against other karts, compete in one of several
|
||||
Grand Prix, try to beat the high score in time trials on your own, play
|
||||
battle mode against your friends, and more!
|
||||
You can do a single race against other karts, compete in one of several Grand
|
||||
Prix, try to beat the high score in time trials on your own, play battle mode
|
||||
against the computer or your friends, and more!
|
||||
</p>
|
||||
</description>
|
||||
<url type="homepage">http://supertuxkart.sourceforge.net/</url>
|
||||
<screenshots>
|
||||
<screenshot type="default">http://supertuxkart.sourceforge.net/persistent/images/4/4d/SuperTuxKart_0.8_screenshot.jpg</screenshot>
|
||||
<screenshot>http://supertuxkart.sourceforge.net/persistent/images/1/1f/SuperTuxKart_0.8_screenshot4.jpg</screenshot>
|
||||
<screenshot type="default">http://supertuxkart.sourceforge.net/persistent/images/4/4e/Supertuxkart-0.9-screenshot-2.jpg</screenshot>
|
||||
<screenshot>http://supertuxkart.sourceforge.net/persistent/images/a/a9/Supertuxkart-0.9-screenshot-1.jpg</screenshot>
|
||||
<screenshot>http://supertuxkart.sourceforge.net/persistent/images/6/63/Supertuxkart-0.9-screenshot-3.jpg</screenshot>
|
||||
</screenshots>
|
||||
<updatecontact>supertuxkart-devel@lists.sourceforge.net</updatecontact>
|
||||
</application>
|
||||
|
@ -289,17 +289,18 @@ void AIBaseController::checkPosition(const Vec3 &point,
|
||||
{
|
||||
// Convert to local coordinates from the point of view of current kart
|
||||
btQuaternion q(btVector3(0, 1, 0), -m_kart->getHeading());
|
||||
Vec3 p = point - m_kart->getXYZ();
|
||||
Vec3 p = point - m_kart->getXYZ();
|
||||
Vec3 local_coordinates = quatRotate(q, p);
|
||||
|
||||
// Save local coordinates for later use if needed
|
||||
if (lc) *lc = local_coordinates;
|
||||
|
||||
// on_side: tell whether it's left or right hand side
|
||||
if (pos_data == NULL) return;
|
||||
// lhs: tell whether it's left or right hand side
|
||||
if (local_coordinates.getX() < 0)
|
||||
pos_data->on_side = true;
|
||||
pos_data->lhs = true;
|
||||
else
|
||||
pos_data->on_side = false;
|
||||
pos_data->lhs = false;
|
||||
|
||||
// behind: tell whether it's behind or not
|
||||
if (local_coordinates.getZ() < 0)
|
||||
|
@ -65,7 +65,7 @@ protected:
|
||||
static int m_test_ai;
|
||||
|
||||
/** Position info structure of targets. */
|
||||
struct posData {bool behind; bool on_side; float angle; float distance;};
|
||||
struct posData {bool behind; bool lhs; float angle; float distance;};
|
||||
|
||||
void setControllerName(const std::string &name);
|
||||
float steerToPoint(const Vec3 &point);
|
||||
|
@ -243,7 +243,7 @@ void ArenaAI::handleArenaSteering(const float dt)
|
||||
#endif
|
||||
if (m_cur_kart_pos_data.behind)
|
||||
{
|
||||
m_adjusting_side = m_cur_kart_pos_data.on_side;
|
||||
m_adjusting_side = m_cur_kart_pos_data.lhs;
|
||||
m_is_uturn = true;
|
||||
}
|
||||
else
|
||||
@ -278,7 +278,7 @@ void ArenaAI::handleArenaSteering(const float dt)
|
||||
#endif
|
||||
if (m_cur_kart_pos_data.behind)
|
||||
{
|
||||
m_adjusting_side = m_cur_kart_pos_data.on_side;
|
||||
m_adjusting_side = m_cur_kart_pos_data.lhs;
|
||||
m_is_uturn = true;
|
||||
}
|
||||
else
|
||||
@ -318,7 +318,7 @@ void ArenaAI::handleArenaBanana()
|
||||
{
|
||||
// Check whether it's straight ahead towards a banana
|
||||
// If so, adjust target point
|
||||
banana_lc = (banana_pos.on_side ? banana_lc + Vec3 (2, 0, 0) :
|
||||
banana_lc = (banana_pos.lhs ? banana_lc + Vec3 (2, 0, 0) :
|
||||
banana_lc - Vec3 (2, 0, 0));
|
||||
m_target_point = m_kart->getTrans()(banana_lc);
|
||||
m_target_node = BattleGraph::get()
|
||||
@ -490,16 +490,22 @@ void ArenaAI::stringPull(const Vec3& start_pos, const Vec3& end_pos)
|
||||
*/
|
||||
void ArenaAI::handleArenaBraking()
|
||||
{
|
||||
m_controls->m_brake = false;
|
||||
|
||||
if (getCurrentNode() == BattleGraph::UNKNOWN_POLY ||
|
||||
m_target_node == BattleGraph::UNKNOWN_POLY) 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.
|
||||
const float MIN_SPEED = 5.0f;
|
||||
|
||||
if (forceBraking() && m_kart->getSpeed() > MIN_SPEED)
|
||||
{
|
||||
// Brake now
|
||||
return;
|
||||
}
|
||||
|
||||
m_controls->m_brake = false;
|
||||
|
||||
if (getCurrentNode() == BattleGraph::UNKNOWN_POLY ||
|
||||
m_target_node == BattleGraph::UNKNOWN_POLY) return;
|
||||
|
||||
float current_curve_radius = determineTurnRadius(m_kart->getXYZ(),
|
||||
m_path_corners[0], (m_path_corners.size() >= 2 ? m_path_corners[1] :
|
||||
m_path_corners[0]));
|
||||
|
@ -120,6 +120,7 @@ private:
|
||||
virtual bool isWaiting() const = 0;
|
||||
virtual void findClosestKart(bool use_difficulty) = 0;
|
||||
virtual void findTarget() = 0;
|
||||
virtual bool forceBraking() { return false; }
|
||||
public:
|
||||
ArenaAI(AbstractKart *kart);
|
||||
virtual ~ArenaAI() {};
|
||||
|
@ -161,12 +161,12 @@ void BattleAI::findTarget()
|
||||
}
|
||||
} // findTarget
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
int BattleAI::getCurrentNode() const
|
||||
{
|
||||
return m_world->getKartNode(m_kart->getWorldKartId());
|
||||
} // getCurrentNode
|
||||
// ------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
bool BattleAI::isWaiting() const
|
||||
{
|
||||
return m_world->isStartPhase();
|
||||
|
@ -49,6 +49,7 @@ SoccerAI::SoccerAI(AbstractKart *kart)
|
||||
#endif
|
||||
m_world = dynamic_cast<SoccerWorld*>(World::getWorld());
|
||||
m_track = m_world->getTrack();
|
||||
m_cur_team = m_world->getKartTeam(m_kart->getWorldKartId());
|
||||
|
||||
// Don't call our own setControllerName, since this will add a
|
||||
// billboard showing 'AIBaseController' to the kart.
|
||||
@ -75,31 +76,15 @@ void SoccerAI::reset()
|
||||
AIBaseController::reset();
|
||||
|
||||
m_saving_ball = false;
|
||||
if (race_manager->getNumPlayers() == 1)
|
||||
{
|
||||
// Same handle in SoccerWorld::createKart
|
||||
if (race_manager->getKartInfo(0).getSoccerTeam() == SOCCER_TEAM_RED)
|
||||
{
|
||||
m_cur_team = (m_kart->getWorldKartId() % 2 == 0 ?
|
||||
SOCCER_TEAM_BLUE : SOCCER_TEAM_RED);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cur_team = (m_kart->getWorldKartId() % 2 == 0 ?
|
||||
SOCCER_TEAM_RED : SOCCER_TEAM_BLUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cur_team = (m_kart->getWorldKartId() % 2 == 0 ?
|
||||
SOCCER_TEAM_BLUE : SOCCER_TEAM_RED);
|
||||
}
|
||||
m_force_brake = false;
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SoccerAI::update(float dt)
|
||||
{
|
||||
m_saving_ball = false;
|
||||
m_force_brake = false;
|
||||
|
||||
if (World::getWorld()->getPhase() == World::GOAL_PHASE)
|
||||
{
|
||||
m_controls->m_brake = false;
|
||||
@ -151,8 +136,8 @@ void SoccerAI::findClosestKart(bool use_difficulty)
|
||||
void SoccerAI::findTarget()
|
||||
{
|
||||
// Check whether any defense is needed
|
||||
if ((m_world->getBallPosition() - NavMesh::get()->getNavPoly(m_world
|
||||
->getGoalNode(m_cur_team)).getCenter()).length_2d() < 50.0f &&
|
||||
if ((m_world->getBallPosition() - m_world->getGoalLocation(m_cur_team,
|
||||
CheckGoal::POINT_CENTER)).length_2d() < 50.0f &&
|
||||
m_world->getDefender(m_cur_team) == (signed)m_kart->getWorldKartId())
|
||||
{
|
||||
m_target_node = m_world->getBallNode();
|
||||
@ -178,86 +163,110 @@ Vec3 SoccerAI::correctBallPosition(const Vec3& orig_pos)
|
||||
{
|
||||
// Notice: Build with AI_DEBUG and change camera target to an AI kart,
|
||||
// to debug or see how AI steer with the ball
|
||||
|
||||
posData ball_pos = {0};
|
||||
posData goal_pos = {0};
|
||||
Vec3 ball_lc(0, 0, 0);
|
||||
Vec3 ball_lc;
|
||||
checkPosition(orig_pos, &ball_pos, &ball_lc);
|
||||
|
||||
// opposite team goal
|
||||
checkPosition(NavMesh::get()->getNavPoly(m_world
|
||||
->getGoalNode(m_cur_team == SOCCER_TEAM_BLUE ?
|
||||
SOCCER_TEAM_RED : SOCCER_TEAM_BLUE)).getCenter(), &goal_pos);
|
||||
// Too far / behind from the ball,
|
||||
// use path finding from arena ai to get close
|
||||
if (!(ball_pos.distance < 3.0f) || ball_pos.behind) return orig_pos;
|
||||
|
||||
if (goal_pos.behind)
|
||||
// Save the opposite team
|
||||
SoccerTeam opp_team = (m_cur_team == SOCCER_TEAM_BLUE ?
|
||||
SOCCER_TEAM_RED : SOCCER_TEAM_BLUE);
|
||||
|
||||
// Prevent lost control when steering with ball
|
||||
const bool need_braking = ball_pos.angle > 0.1f &&
|
||||
m_kart->getSpeed() > 9.0f && ball_pos.distance <2.5f;
|
||||
|
||||
// Goal / own goal detection first, as different aiming method will be used
|
||||
const bool likely_to_goal =
|
||||
ball_pos.angle < 0.2f && isLikelyToGoal(opp_team);
|
||||
if (likely_to_goal)
|
||||
{
|
||||
if (goal_pos.angle > 0.3f && ball_pos.distance < 3.0f &&
|
||||
!ball_pos.behind)
|
||||
if (need_braking)
|
||||
{
|
||||
// Only steer with ball if same sides for ball and goal
|
||||
if (ball_pos.on_side && goal_pos.on_side)
|
||||
{
|
||||
ball_lc = ball_lc + Vec3 (1, 0, 1);
|
||||
return m_kart->getTrans()(ball_lc);
|
||||
}
|
||||
else if (!ball_pos.on_side && !goal_pos.on_side)
|
||||
{
|
||||
ball_lc = ball_lc - Vec3 (1, 0, 0) + Vec3 (0, 0, 1);
|
||||
return m_kart->getTrans()(ball_lc);
|
||||
}
|
||||
else
|
||||
m_controls->m_brake = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This case is facing straight ahead opposite goal
|
||||
// (which is straight behind itself), apply more
|
||||
// offset for skidding, to save the ball from behind
|
||||
// scored.
|
||||
// Notice: this assume map maker make soccer field
|
||||
// with two goals facing each other straight
|
||||
ball_lc = (goal_pos.on_side ? ball_lc - Vec3 (2, 0, 0) +
|
||||
Vec3 (0, 0, 2) : ball_lc + Vec3 (2, 0, 2));
|
||||
|
||||
if (ball_pos.distance < 3.0f &&
|
||||
(m_cur_difficulty == RaceManager::DIFFICULTY_HARD ||
|
||||
m_cur_difficulty == RaceManager::DIFFICULTY_BEST))
|
||||
m_saving_ball = true;
|
||||
return m_kart->getTrans()(ball_lc);
|
||||
m_controls->m_brake = true;
|
||||
m_force_brake = true;
|
||||
// Prevent keep pushing by aiming a nearer point
|
||||
return m_kart->getTrans()(ball_lc - Vec3(0, 0, 1));
|
||||
}
|
||||
// Keep pushing the ball straight to the goal
|
||||
return orig_pos;
|
||||
}
|
||||
|
||||
if (ball_pos.distance < 3.0f &&
|
||||
!ball_pos.behind && !goal_pos.behind)
|
||||
const bool likely_to_own_goal =
|
||||
ball_pos.angle < 0.2f && isLikelyToGoal(m_cur_team);
|
||||
if (likely_to_own_goal)
|
||||
{
|
||||
if (goal_pos.angle < 0.5f)
|
||||
return orig_pos;
|
||||
else
|
||||
{
|
||||
// Same with above
|
||||
if (ball_pos.on_side && goal_pos.on_side)
|
||||
{
|
||||
ball_lc = ball_lc + Vec3 (1, 0, 1);
|
||||
return m_kart->getTrans()(ball_lc);
|
||||
}
|
||||
else if (!ball_pos.on_side && !goal_pos.on_side)
|
||||
{
|
||||
ball_lc = ball_lc - Vec3 (1, 0, 0) + Vec3 (0, 0, 1);
|
||||
return m_kart->getTrans()(ball_lc);
|
||||
}
|
||||
else
|
||||
m_controls->m_brake = true;
|
||||
}
|
||||
// It's getting likely to own goal, apply more
|
||||
// offset for skidding, to save the ball from behind
|
||||
// scored.
|
||||
if (m_cur_difficulty == RaceManager::DIFFICULTY_HARD ||
|
||||
m_cur_difficulty == RaceManager::DIFFICULTY_BEST)
|
||||
m_saving_ball = true;
|
||||
return m_kart->getTrans()(ball_pos.lhs ?
|
||||
ball_lc - Vec3(2, 0, 0) + Vec3(0, 0, 2) :
|
||||
ball_lc + Vec3(2, 0, 2));
|
||||
}
|
||||
return orig_pos;
|
||||
|
||||
// Now try to make the ball face towards the goal
|
||||
// Aim at upper/lower left/right corner of ball depends on location
|
||||
posData goal_pos = {0};
|
||||
checkPosition(m_world->getGoalLocation(opp_team, CheckGoal::POINT_CENTER),
|
||||
&goal_pos);
|
||||
Vec3 corrected_pos;
|
||||
if (ball_pos.lhs && goal_pos.lhs)
|
||||
{
|
||||
corrected_pos = ball_lc + Vec3(1, 0, 1);
|
||||
}
|
||||
else if (!ball_pos.lhs && !goal_pos.lhs)
|
||||
{
|
||||
corrected_pos = ball_lc - Vec3(1, 0, 0) + Vec3(0, 0, 1);
|
||||
}
|
||||
else if (!ball_pos.lhs && goal_pos.lhs)
|
||||
{
|
||||
corrected_pos = ball_lc + Vec3(1, 0, 0) - Vec3(0, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
corrected_pos = ball_lc - Vec3(1, 0, 1);
|
||||
}
|
||||
if (need_braking)
|
||||
{
|
||||
m_controls->m_brake = true;
|
||||
m_force_brake = true;
|
||||
}
|
||||
return m_kart->getTrans()(corrected_pos);
|
||||
|
||||
} // correctBallPosition
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SoccerAI::isLikelyToGoal(SoccerTeam team) const
|
||||
{
|
||||
// Use local coordinate for easy compare
|
||||
Vec3 first_pos;
|
||||
Vec3 last_pos;
|
||||
checkPosition(m_world->getGoalLocation(team, CheckGoal::POINT_FIRST),
|
||||
NULL, &first_pos);
|
||||
checkPosition(m_world->getGoalLocation(team, CheckGoal::POINT_LAST),
|
||||
NULL, &last_pos);
|
||||
|
||||
// If the kart lies between the first and last pos, and faces
|
||||
// in front of them, than it's likely to goal
|
||||
if ((first_pos.z() > 0.0f && last_pos.z() > 0.0f) &&
|
||||
((first_pos.x() < 0.0f && last_pos.x() > 0.0f) ||
|
||||
(last_pos.x() < 0.0f && first_pos.x() > 0.0f)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
} // isLikelyToGoal
|
||||
//-----------------------------------------------------------------------------
|
||||
int SoccerAI::getCurrentNode() const
|
||||
{
|
||||
return m_world->getKartNode(m_kart->getWorldKartId());
|
||||
} // getCurrentNode
|
||||
// ------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SoccerAI::isWaiting() const
|
||||
{
|
||||
return m_world->isStartPhase();
|
||||
|
@ -36,14 +36,17 @@ private:
|
||||
|
||||
SoccerTeam m_cur_team;
|
||||
bool m_saving_ball;
|
||||
bool m_force_brake;
|
||||
|
||||
Vec3 correctBallPosition(const Vec3&);
|
||||
bool isLikelyToGoal(SoccerTeam team) const;
|
||||
|
||||
virtual void findClosestKart(bool use_difficulty);
|
||||
virtual void findTarget();
|
||||
virtual int getCurrentNode() const;
|
||||
virtual bool isWaiting() const;
|
||||
virtual bool canSkid(float steer_fraction) { return m_saving_ball; }
|
||||
virtual bool forceBraking() OVERRIDE { return m_force_brake; }
|
||||
public:
|
||||
SoccerAI(AbstractKart *kart);
|
||||
~SoccerAI();
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "karts/controller/soccer_ai.hpp"
|
||||
#include "physics/physics.hpp"
|
||||
#include "states_screens/race_gui_base.hpp"
|
||||
#include "tracks/check_goal.hpp"
|
||||
#include "tracks/check_manager.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/track_object_manager.hpp"
|
||||
@ -54,6 +53,8 @@ SoccerWorld::SoccerWorld() : WorldWithRank()
|
||||
}
|
||||
|
||||
m_use_highscores = false;
|
||||
m_red_ai = 0;
|
||||
m_blue_ai = 0;
|
||||
} // SoccerWorld
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -76,8 +77,11 @@ void SoccerWorld::init()
|
||||
m_display_rank = false;
|
||||
m_goal_timer = 0.0f;
|
||||
m_ball_hitter = -1;
|
||||
m_red_check_goal = NULL;
|
||||
m_blue_check_goal = NULL;
|
||||
m_goal_target = race_manager->getMaxGoal();
|
||||
m_goal_sound = SFXManager::get()->createSoundSource("goal_scored");
|
||||
initGoal();
|
||||
|
||||
} // init
|
||||
|
||||
@ -129,8 +133,7 @@ void SoccerWorld::reset()
|
||||
}
|
||||
|
||||
initKartList();
|
||||
resetAllNodes();
|
||||
initGoalNodes();
|
||||
resetAllPosition();
|
||||
resetBall();
|
||||
|
||||
} // reset
|
||||
@ -355,22 +358,10 @@ AbstractKart *SoccerWorld::createKart(const std::string &kart_ident, int index,
|
||||
|
||||
if (kart_type == RaceManager::KT_AI)
|
||||
{
|
||||
if (race_manager->getNumPlayers() == 1)
|
||||
{
|
||||
// Make AI even when single player choose a different team
|
||||
if (race_manager->getKartInfo(0).getSoccerTeam() == SOCCER_TEAM_RED)
|
||||
{
|
||||
team = (index % 2 == 0 ? SOCCER_TEAM_BLUE : SOCCER_TEAM_RED);
|
||||
}
|
||||
else
|
||||
{
|
||||
team = (index % 2 == 0 ? SOCCER_TEAM_RED : SOCCER_TEAM_BLUE);
|
||||
}
|
||||
}
|
||||
if (index < m_red_ai)
|
||||
team = SOCCER_TEAM_RED;
|
||||
else
|
||||
{
|
||||
team = (index % 2 == 0 ? SOCCER_TEAM_BLUE : SOCCER_TEAM_RED);
|
||||
}
|
||||
team = SOCCER_TEAM_BLUE;
|
||||
m_kart_team_map[index] = team;
|
||||
}
|
||||
else
|
||||
@ -484,9 +475,7 @@ void SoccerWorld::updateBallPosition(float dt)
|
||||
} // updateBallPosition
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Localize two goals on the navigation mesh.
|
||||
*/
|
||||
void SoccerWorld::initGoalNodes()
|
||||
void SoccerWorld::initGoal()
|
||||
{
|
||||
if (!m_track->hasNavMesh()) return;
|
||||
|
||||
@ -500,20 +489,18 @@ void SoccerWorld::initGoalNodes()
|
||||
{
|
||||
if (goal->getTeam())
|
||||
{
|
||||
m_blue_goal_node = BattleGraph::get()->pointToNode(m_blue_goal_node,
|
||||
goal->convertTo3DCenter(), true/*ignore_vertical*/);
|
||||
m_blue_check_goal = goal;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_red_goal_node = BattleGraph::get()->pointToNode(m_red_goal_node,
|
||||
goal->convertTo3DCenter(), true/*ignore_vertical*/);
|
||||
m_red_check_goal = goal;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // initGoalNodes
|
||||
} // initGoal
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SoccerWorld::resetAllNodes()
|
||||
void SoccerWorld::resetAllPosition()
|
||||
{
|
||||
m_kart_on_node.clear();
|
||||
m_kart_on_node.resize(m_karts.size());
|
||||
@ -521,9 +508,7 @@ void SoccerWorld::resetAllNodes()
|
||||
m_kart_on_node[n] = BattleGraph::UNKNOWN_POLY;
|
||||
m_ball_on_node = BattleGraph::UNKNOWN_POLY;
|
||||
m_ball_position = Vec3(0, 0, 0);
|
||||
m_red_goal_node = BattleGraph::UNKNOWN_POLY;
|
||||
m_blue_goal_node = BattleGraph::UNKNOWN_POLY;
|
||||
} // resetAllNodes
|
||||
} // resetAllPosition
|
||||
//-----------------------------------------------------------------------------
|
||||
SoccerTeam SoccerWorld::getKartTeam(unsigned int kart_id) const
|
||||
{
|
||||
@ -571,9 +556,8 @@ void SoccerWorld::updateDefenders()
|
||||
getKartTeam(m_karts[i]->getWorldKartId()) != SOCCER_TEAM_RED)
|
||||
continue;
|
||||
|
||||
Vec3 d = NavMesh::get()->getNavPoly(this
|
||||
->getGoalNode(SOCCER_TEAM_RED)).getCenter()
|
||||
- m_karts[i]->getXYZ();
|
||||
Vec3 d = this->getGoalLocation(SOCCER_TEAM_RED,
|
||||
CheckGoal::POINT_CENTER) - m_karts[i]->getXYZ();
|
||||
|
||||
if (d.length_2d() <= distance)
|
||||
{
|
||||
@ -593,9 +577,8 @@ void SoccerWorld::updateDefenders()
|
||||
getKartTeam(m_karts[i]->getWorldKartId()) != SOCCER_TEAM_BLUE)
|
||||
continue;
|
||||
|
||||
Vec3 d = NavMesh::get()->getNavPoly(this
|
||||
->getGoalNode(SOCCER_TEAM_BLUE)).getCenter()
|
||||
- m_karts[i]->getXYZ();
|
||||
Vec3 d = this->getGoalLocation(SOCCER_TEAM_BLUE,
|
||||
CheckGoal::POINT_CENTER) - m_karts[i]->getXYZ();
|
||||
|
||||
if (d.length_2d() <= distance)
|
||||
{
|
||||
@ -642,3 +625,52 @@ void SoccerWorld::resetBall()
|
||||
m_ball->reset();
|
||||
m_ball->getPhysicalObject()->reset();
|
||||
} // resetBall
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void SoccerWorld::setAITeam()
|
||||
{
|
||||
const int total_player = race_manager->getNumPlayers();
|
||||
const int total_karts = race_manager->getNumberOfKarts();
|
||||
|
||||
// No AI
|
||||
if ((total_karts - total_player) == 0) return;
|
||||
|
||||
int red_player = 0;
|
||||
int blue_player = 0;
|
||||
for (int i = 0; i < total_player; i++)
|
||||
{
|
||||
SoccerTeam team = race_manager->getKartInfo(i).getSoccerTeam();
|
||||
assert(team != SOCCER_TEAM_NONE);
|
||||
team == SOCCER_TEAM_BLUE ? blue_player++ : red_player++;
|
||||
}
|
||||
|
||||
int available_ai = total_karts - red_player - blue_player;
|
||||
while (available_ai > 0)
|
||||
{
|
||||
if ((m_red_ai + red_player) > (m_blue_ai + blue_player))
|
||||
{
|
||||
m_blue_ai++;
|
||||
available_ai--;
|
||||
}
|
||||
else if ((m_blue_ai + blue_player) > (m_red_ai + red_player))
|
||||
{
|
||||
m_red_ai++;
|
||||
available_ai--;
|
||||
}
|
||||
else if ((m_blue_ai + blue_player) == (m_red_ai + red_player))
|
||||
{
|
||||
blue_player > red_player ? m_red_ai++ : m_blue_ai++;
|
||||
available_ai--;
|
||||
}
|
||||
}
|
||||
Log::debug("SoccerWorld","blue AI: %d red AI: %d", m_blue_ai, m_red_ai);
|
||||
|
||||
} // setAITeam
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
const Vec3& SoccerWorld::getGoalLocation(SoccerTeam team,
|
||||
CheckGoal::PointLocation point) const
|
||||
{
|
||||
return (team == SOCCER_TEAM_BLUE ? m_blue_check_goal->getPoint(point) :
|
||||
m_red_check_goal->getPoint(point));
|
||||
} // getGoalLocation
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "modes/world_with_rank.hpp"
|
||||
#include "states_screens/race_gui_base.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "tracks/check_goal.hpp"
|
||||
|
||||
#include <IMesh.h>
|
||||
#include <string>
|
||||
@ -85,22 +86,26 @@ private:
|
||||
std::vector<int> m_kart_on_node;
|
||||
int m_ball_on_node;
|
||||
Vec3 m_ball_position;
|
||||
int m_red_goal_node;
|
||||
int m_blue_goal_node;
|
||||
|
||||
CheckGoal* m_red_check_goal;
|
||||
CheckGoal* m_blue_check_goal;
|
||||
|
||||
int m_red_defender;
|
||||
int m_blue_defender;
|
||||
|
||||
int m_red_ai;
|
||||
int m_blue_ai;
|
||||
|
||||
/** Set the team for the karts */
|
||||
void initKartList();
|
||||
/** Function to init the locations of two goals on the polygon map */
|
||||
void initGoalNodes();
|
||||
/** Function to save check goal for the getting of coordinate */
|
||||
void initGoal();
|
||||
/** Function to update the locations of all karts on the polygon map */
|
||||
void updateKartNodes();
|
||||
/** Function to update the location the ball on the polygon map */
|
||||
void updateBallPosition(float dt);
|
||||
/** Clean up */
|
||||
void resetAllNodes();
|
||||
void resetAllPosition();
|
||||
/** Reset the ball to original starting position. */
|
||||
void resetBall();
|
||||
/** Function to update the AI which is the closest to its goal to defend. */
|
||||
@ -166,17 +171,18 @@ public:
|
||||
const Vec3& getBallPosition() const
|
||||
{ return m_ball_position; }
|
||||
// ------------------------------------------------------------------------
|
||||
const int getGoalNode(SoccerTeam team) const
|
||||
{
|
||||
return (team == SOCCER_TEAM_BLUE ? m_blue_goal_node : m_red_goal_node);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
bool isCorrectGoal(unsigned int kart_id, bool first_goal) const;
|
||||
// ------------------------------------------------------------------------
|
||||
const int getDefender(SoccerTeam team) const
|
||||
{
|
||||
return (team == SOCCER_TEAM_BLUE ? m_blue_defender : m_red_defender);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void setAITeam();
|
||||
// ------------------------------------------------------------------------
|
||||
const Vec3& getGoalLocation(SoccerTeam team,
|
||||
CheckGoal::PointLocation point) const;
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
}; // SoccerWorld
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
#include "modes/overworld.hpp"
|
||||
#include "modes/profile_world.hpp"
|
||||
#include "modes/soccer_world.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "physics/btKart.hpp"
|
||||
#include "physics/physics.hpp"
|
||||
@ -191,6 +192,11 @@ void World::init()
|
||||
m_karts.push_back(ReplayPlay::get()->getGhostKart(k));
|
||||
}
|
||||
|
||||
// Assign team of AIs for soccer mode before createKart
|
||||
SoccerWorld* sw = dynamic_cast<SoccerWorld*>(this);
|
||||
if (sw)
|
||||
sw->setAITeam();
|
||||
|
||||
for(unsigned int i=0; i<num_karts; i++)
|
||||
{
|
||||
if (race_manager->getKartType(i) == RaceManager::KT_GHOST) continue;
|
||||
|
@ -37,12 +37,12 @@ CheckGoal::CheckGoal(const XMLNode &node, unsigned int index)
|
||||
m_first_goal = false;
|
||||
node.get("first_goal", &m_first_goal);
|
||||
|
||||
Vec3 p1, p2;
|
||||
node.get("p1", &p1);
|
||||
node.get("p2", &p2);
|
||||
node.get("p1", &m_p1);
|
||||
node.get("p2", &m_p3);
|
||||
|
||||
m_line.setLine( core::vector2df(p1.getX(), p1.getZ()),
|
||||
core::vector2df(p2.getX(), p2.getZ()) );
|
||||
m_line.setLine( core::vector2df(m_p1.getX(), m_p1.getZ()),
|
||||
core::vector2df(m_p3.getX(), m_p3.getZ()) );
|
||||
m_p2 = (m_p1 + m_p3) / 2;
|
||||
} // CheckGoal
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -113,11 +113,3 @@ void CheckGoal::reset(const Track &track)
|
||||
}
|
||||
|
||||
} // reset
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
Vec3 CheckGoal::convertTo3DCenter() const
|
||||
{
|
||||
float x = m_line.getMiddle().X;
|
||||
float y = m_line.getMiddle().Y;
|
||||
return Vec3(x, 0, y);
|
||||
}
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <line2d.h>
|
||||
using namespace irr;
|
||||
|
||||
class CheckManager;
|
||||
class XMLNode;
|
||||
class Track;
|
||||
class Vec3;
|
||||
@ -37,6 +36,14 @@ class Vec3;
|
||||
*/
|
||||
class CheckGoal : public CheckStructure
|
||||
{
|
||||
public:
|
||||
/** Used by AIs to test whether the ball is likely to goal. */
|
||||
enum PointLocation
|
||||
{
|
||||
POINT_FIRST,
|
||||
POINT_CENTER,
|
||||
POINT_LAST
|
||||
};
|
||||
private:
|
||||
/** Previois ball position. */
|
||||
Vec3 m_previous_ball_position;
|
||||
@ -47,6 +54,11 @@ private:
|
||||
/** The line that is tested for being crossed. */
|
||||
core::line2df m_line;
|
||||
|
||||
/** Used by AIs to test whether the ball is likely to goal. */
|
||||
Vec3 m_p1;
|
||||
Vec3 m_p2;
|
||||
Vec3 m_p3;
|
||||
|
||||
public:
|
||||
CheckGoal(const XMLNode &node, unsigned int index);
|
||||
virtual ~CheckGoal() {}
|
||||
@ -59,7 +71,11 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
bool getTeam() const { return m_first_goal; }
|
||||
// ------------------------------------------------------------------------
|
||||
Vec3 convertTo3DCenter() const;
|
||||
}; // CheckLine
|
||||
const Vec3& getPoint(PointLocation point) const
|
||||
{
|
||||
return (point == POINT_LAST ? m_p3 :
|
||||
(point == POINT_CENTER ? m_p2 : m_p1));
|
||||
}
|
||||
}; // CheckGoal
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user