Team indicators added.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/soccer@13167 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
yasin-ghannam 2013-07-10 22:49:51 +00:00
parent c22941d354
commit d16a5a0552
5 changed files with 351 additions and 324 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -283,39 +283,7 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models)
lod_node->add(500, static_model, true); lod_node->add(500, static_model, true);
m_animated_node = static_cast<scene::IAnimatedMeshSceneNode*>(node); m_animated_node = static_cast<scene::IAnimatedMeshSceneNode*>(node);
m_hat_node = NULL; attachHat();
if(m_hat_name.size()>0)
{
scene::IBoneSceneNode *bone = m_animated_node->getJointNode("Head");
if(!bone)
bone = m_animated_node->getJointNode("head");
if(bone)
{
// Till we have all models fixed, accept Head and head as bone naartme
scene::IMesh *hat_mesh =
irr_driver->getAnimatedMesh(
file_manager->getModelFile(m_hat_name));
m_hat_node = irr_driver->addMesh(hat_mesh);
bone->addChild(m_hat_node);
m_animated_node->setCurrentFrame((float)m_animation_frame[AF_STRAIGHT]);
m_animated_node->OnAnimate(0);
bone->updateAbsolutePosition();
// With the hat node attached to the head bone, we have to
// reverse the transformation of the bone, so that the hat
// is still properly placed. Esp. the hat offset needs
// to be rotated.
const core::matrix4 mat = bone->getAbsoluteTransformation();
core::matrix4 inv;
mat.getInverse(inv);
core::vector3df rotated_offset;
inv.rotateVect(rotated_offset, m_hat_offset);
m_hat_node->setPosition(rotated_offset);
m_hat_node->setScale(inv.getScale());
m_hat_node->setRotation(inv.getRotationDegrees());
} // if bone
} // if(m_hat_name)
#ifdef DEBUG #ifdef DEBUG
std::string debug_name = m_model_filename+" (animated-kart-model)"; std::string debug_name = m_model_filename+" (animated-kart-model)";
@ -701,4 +669,40 @@ void KartModel::update(float rotation_dt, float steer, const float suspension[4]
m_animated_node->setCurrentFrame(frame); m_animated_node->setCurrentFrame(frame);
} // update } // update
//-----------------------------------------------------------------------------
void KartModel::attachHat(){
m_hat_node = NULL;
if(m_hat_name.size()>0)
{
scene::IBoneSceneNode *bone = m_animated_node->getJointNode("Head");
if(!bone)
bone = m_animated_node->getJointNode("head");
if(bone)
{
// Till we have all models fixed, accept Head and head as bone naartme
scene::IMesh *hat_mesh =
irr_driver->getAnimatedMesh(
file_manager->getModelFile(m_hat_name));
m_hat_node = irr_driver->addMesh(hat_mesh);
bone->addChild(m_hat_node);
m_animated_node->setCurrentFrame((float)m_animation_frame[AF_STRAIGHT]);
m_animated_node->OnAnimate(0);
bone->updateAbsolutePosition();
// With the hat node attached to the head bone, we have to
// reverse the transformation of the bone, so that the hat
// is still properly placed. Esp. the hat offset needs
// to be rotated.
const core::matrix4 mat = bone->getAbsoluteTransformation();
core::matrix4 inv;
mat.getInverse(inv);
core::vector3df rotated_offset;
inv.rotateVect(rotated_offset, m_hat_offset);
m_hat_node->setPosition(rotated_offset);
m_hat_node->setScale(inv.getScale());
m_hat_node->setRotation(inv.getRotationDegrees());
} // if bone
} // if(m_hat_name)
}

View File

@ -228,9 +228,15 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Name of the hat mesh to use. */ /** Name of the hat mesh to use. */
void setHatMeshName(const std::string &name) {m_hat_name = name; } void setHatMeshName(const std::string &name) {m_hat_name = name; }
// ------------------------------------------------------------------------
void attachHat();
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the array of wheel nodes. */ /** Returns the array of wheel nodes. */
scene::ISceneNode** getWheelNodes() { return m_wheel_node; } scene::ISceneNode** getWheelNodes() { return m_wheel_node; }
// ------------------------------------------------------------------------
scene::IAnimatedMeshSceneNode* getAnimatedNode(){ return m_animated_node; }
// ------------------------------------------------------------------------
core::vector3df getHatOffset() { return m_hat_offset; }
}; // KartModel }; // KartModel
#endif #endif

View File

@ -1,98 +1,98 @@
// SuperTuxKart - a fun racing game with go-kart // SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 SuperTuxKart-Team // Copyright (C) 2006 SuperTuxKart-Team
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License // modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3 // as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version. // of the License, or (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "modes/soccer_world.hpp" #include "modes/soccer_world.hpp"
#include <string> #include <string>
#include <IMeshSceneNode.h> #include <IMeshSceneNode.h>
#include "audio/music_manager.hpp" #include "audio/music_manager.hpp"
#include "io/file_manager.hpp" #include "io/file_manager.hpp"
#include "karts/abstract_kart.hpp" #include "karts/abstract_kart.hpp"
#include "karts/kart_model.hpp" #include "karts/kart_model.hpp"
#include "karts/kart_properties.hpp" #include "karts/kart_properties.hpp"
#include "karts/rescue_animation.hpp" #include "karts/rescue_animation.hpp"
#include "physics/physics.hpp" #include "physics/physics.hpp"
#include "states_screens/race_gui_base.hpp" #include "states_screens/race_gui_base.hpp"
#include "tracks/track.hpp" #include "tracks/track.hpp"
#include "tracks/track_object_manager.hpp" #include "tracks/track_object_manager.hpp"
#include "utils/constants.hpp" #include "utils/constants.hpp"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Constructor. Sets up the clock mode etc. /** Constructor. Sets up the clock mode etc.
*/ */
SoccerWorld::SoccerWorld() : WorldWithRank() SoccerWorld::SoccerWorld() : WorldWithRank()
{ {
WorldStatus::setClockMode(CLOCK_CHRONO); WorldStatus::setClockMode(CLOCK_CHRONO);
m_use_highscores = false; m_use_highscores = false;
} // SoccerWorld } // SoccerWorld
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Initializes the soccer world. It sets up the data structure /** Initializes the soccer world. It sets up the data structure
* to keep track of points etc. for each kart. * to keep track of points etc. for each kart.
*/ */
void SoccerWorld::init() void SoccerWorld::init()
{ {
WorldWithRank::init(); WorldWithRank::init();
m_display_rank = false; m_display_rank = false;
// check for possible problems if AI karts were incorrectly added // check for possible problems if AI karts were incorrectly added
if(getNumKarts() > race_manager->getNumPlayers()) if(getNumKarts() > race_manager->getNumPlayers())
{ {
fprintf(stderr, "No AI exists for this game mode\n"); fprintf(stderr, "No AI exists for this game mode\n");
exit(1); exit(1);
} }
} // init } // init
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Called then a battle is restarted. /** Called then a battle is restarted.
*/ */
void SoccerWorld::reset() void SoccerWorld::reset()
{ {
WorldWithRank::reset(); WorldWithRank::reset();
m_can_score_points = true; m_can_score_points = true;
memset(m_team_goals, 0, sizeof(m_team_goals)); memset(m_team_goals, 0, sizeof(m_team_goals));
initKartList(); initKartList();
} // reset } // reset
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Returns the internal identifier for this race. /** Returns the internal identifier for this race.
*/ */
const std::string& SoccerWorld::getIdent() const const std::string& SoccerWorld::getIdent() const
{ {
return IDENT_SOCCER; return IDENT_SOCCER;
} // getIdent } // getIdent
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Update the world and the track. /** Update the world and the track.
* \param dt Time step size. * \param dt Time step size.
*/ */
void SoccerWorld::update(float dt) void SoccerWorld::update(float dt)
{ {
WorldWithRank::update(dt); WorldWithRank::update(dt);
WorldWithRank::updateTrack(dt); WorldWithRank::updateTrack(dt);
// TODO // TODO
} // update } // update
void SoccerWorld::onCheckGoalTriggered(bool first_goal) void SoccerWorld::onCheckGoalTriggered(bool first_goal)
{ {
// TODO // TODO
if(m_can_score_points){ if(m_can_score_points){
printf("*** GOOOOOOOOOAAAAAAALLLLLL!!!! (team: %d) ***\n", first_goal ? 0 : 1); printf("*** GOOOOOOOOOAAAAAAALLLLLL!!!! (team: %d) ***\n", first_goal ? 0 : 1);
@ -132,202 +132,219 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
// TODO: rescue the karts // TODO: rescue the karts
// TODO: score a point // TODO: score a point
} // onCheckGoalTriggered } // onCheckGoalTriggered
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** The battle is over if only one kart is left, or no player kart. /** The battle is over if only one kart is left, or no player kart.
*/ */
bool SoccerWorld::isRaceOver() bool SoccerWorld::isRaceOver()
{ {
// for tests : never over when we have a single player there :) // for tests : never over when we have a single player there :)
if (race_manager->getNumPlayers() < 2) if (race_manager->getNumPlayers() < 2)
{ {
return false; return false;
} }
// TODO // TODO
return getCurrentNumKarts()==1 || getCurrentNumPlayers()==0; return getCurrentNumKarts()==1 || getCurrentNumPlayers()==0;
} // isRaceOver } // isRaceOver
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Called when the race finishes, i.e. after playing (if necessary) an /** Called when the race finishes, i.e. after playing (if necessary) an
* end of race animation. It updates the time for all karts still racing, * end of race animation. It updates the time for all karts still racing,
* and then updates the ranks. * and then updates the ranks.
*/ */
void SoccerWorld::terminateRace() void SoccerWorld::terminateRace()
{ {
m_can_score_points = false; m_can_score_points = false;
WorldWithRank::terminateRace(); WorldWithRank::terminateRace();
} // terminateRace } // terminateRace
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Returns the data to display in the race gui. /** Returns the data to display in the race gui.
*/ */
void SoccerWorld::getKartsDisplayInfo( void SoccerWorld::getKartsDisplayInfo(
std::vector<RaceGUIBase::KartIconDisplayInfo> *info) std::vector<RaceGUIBase::KartIconDisplayInfo> *info)
{ {
// TODO!! // TODO!!
/* /*
const unsigned int kart_amount = getNumKarts(); const unsigned int kart_amount = getNumKarts();
for(unsigned int i = 0; i < kart_amount ; i++) for(unsigned int i = 0; i < kart_amount ; i++)
{ {
RaceGUIBase::KartIconDisplayInfo& rank_info = (*info)[i]; RaceGUIBase::KartIconDisplayInfo& rank_info = (*info)[i];
// reset color // reset color
rank_info.lap = -1; rank_info.lap = -1;
AbstractKart* kart = getKart(i); AbstractKart* kart = getKart(i);
switch(kart->getSoccerTeam()) switch(kart->getSoccerTeam())
{ {
case SOCCER_TEAM_BLUE: case SOCCER_TEAM_BLUE:
rank_info.r = 0.0f; rank_info.r = 0.0f;
rank_info.g = 0.0f; rank_info.g = 0.0f;
rank_info.b = 0.7f; rank_info.b = 0.7f;
break; break;
case SOCCER_TEAM_RED: case SOCCER_TEAM_RED:
rank_info.r = 0.9f; rank_info.r = 0.9f;
rank_info.g = 0.0f; rank_info.g = 0.0f;
rank_info.b = 0.0f; rank_info.b = 0.0f;
break; break;
default: default:
assert(false && "Soccer team not set to blue or red"); assert(false && "Soccer team not set to blue or red");
rank_info.r = 0.0f; rank_info.r = 0.0f;
rank_info.g = 0.0f; rank_info.g = 0.0f;
rank_info.b = 0.0f; rank_info.b = 0.0f;
} }
} }
*/ */
} // getKartsDisplayInfo } // getKartsDisplayInfo
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Moves a kart to its rescue position. /** Moves a kart to its rescue position.
* \param kart The kart that was rescued. * \param kart The kart that was rescued.
*/ */
void SoccerWorld::moveKartAfterRescue(AbstractKart* kart) void SoccerWorld::moveKartAfterRescue(AbstractKart* kart)
{ {
// find closest point to drop kart on // find closest point to drop kart on
World *world = World::getWorld(); World *world = World::getWorld();
const int start_spots_amount = world->getTrack()->getNumberOfStartPositions(); const int start_spots_amount = world->getTrack()->getNumberOfStartPositions();
assert(start_spots_amount > 0); assert(start_spots_amount > 0);
float largest_accumulated_distance_found = -1; float largest_accumulated_distance_found = -1;
int furthest_id_found = -1; int furthest_id_found = -1;
const float kart_x = kart->getXYZ().getX(); const float kart_x = kart->getXYZ().getX();
const float kart_z = kart->getXYZ().getZ(); const float kart_z = kart->getXYZ().getZ();
for(int n=0; n<start_spots_amount; n++) for(int n=0; n<start_spots_amount; n++)
{ {
// no need for the overhead to compute exact distance with sqrt(), // no need for the overhead to compute exact distance with sqrt(),
// so using the 'manhattan' heuristic which will do fine enough. // so using the 'manhattan' heuristic which will do fine enough.
const btTransform &s = world->getTrack()->getStartTransform(n); const btTransform &s = world->getTrack()->getStartTransform(n);
const Vec3 &v=s.getOrigin(); const Vec3 &v=s.getOrigin();
float accumulatedDistance = .0f; float accumulatedDistance = .0f;
bool spawnPointClear = true; bool spawnPointClear = true;
for(unsigned int k=0; k<getCurrentNumKarts(); k++) for(unsigned int k=0; k<getCurrentNumKarts(); k++)
{ {
const AbstractKart *currentKart = World::getWorld()->getKart(k); const AbstractKart *currentKart = World::getWorld()->getKart(k);
const float currentKart_x = currentKart->getXYZ().getX(); const float currentKart_x = currentKart->getXYZ().getX();
const float currentKartk_z = currentKart->getXYZ().getZ(); const float currentKartk_z = currentKart->getXYZ().getZ();
if(kart_x!=currentKart_x && kart_z !=currentKartk_z) if(kart_x!=currentKart_x && kart_z !=currentKartk_z)
{ {
float absDistance = fabs(currentKart_x - v.getX()) + float absDistance = fabs(currentKart_x - v.getX()) +
fabs(currentKartk_z - v.getZ()); fabs(currentKartk_z - v.getZ());
if(absDistance < CLEAR_SPAWN_RANGE) if(absDistance < CLEAR_SPAWN_RANGE)
{ {
spawnPointClear = false; spawnPointClear = false;
break; break;
} }
accumulatedDistance += absDistance; accumulatedDistance += absDistance;
} }
} }
if(largest_accumulated_distance_found < accumulatedDistance && spawnPointClear) if(largest_accumulated_distance_found < accumulatedDistance && spawnPointClear)
{ {
furthest_id_found = n; furthest_id_found = n;
largest_accumulated_distance_found = accumulatedDistance; largest_accumulated_distance_found = accumulatedDistance;
} }
} }
assert(furthest_id_found != -1); assert(furthest_id_found != -1);
const btTransform &s = world->getTrack()->getStartTransform(furthest_id_found); const btTransform &s = world->getTrack()->getStartTransform(furthest_id_found);
const Vec3 &xyz = s.getOrigin(); const Vec3 &xyz = s.getOrigin();
kart->setXYZ(xyz); kart->setXYZ(xyz);
kart->setRotation(s.getRotation()); kart->setRotation(s.getRotation());
//position kart from same height as in World::resetAllKarts //position kart from same height as in World::resetAllKarts
btTransform pos; btTransform pos;
pos.setOrigin(kart->getXYZ()+btVector3(0, 0.5f*kart->getKartHeight(), 0.0f)); pos.setOrigin(kart->getXYZ()+btVector3(0, 0.5f*kart->getKartHeight(), 0.0f));
pos.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), 0 /* angle */) ); pos.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), 0 /* angle */) );
kart->getBody()->setCenterOfMassTransform(pos); kart->getBody()->setCenterOfMassTransform(pos);
//project kart to surface of track //project kart to surface of track
bool kart_over_ground = m_track->findGround(kart); bool kart_over_ground = m_track->findGround(kart);
if (kart_over_ground) if (kart_over_ground)
{ {
//add vertical offset so that the kart starts off above the track //add vertical offset so that the kart starts off above the track
float vertical_offset = kart->getKartProperties()->getVertRescueOffset() * float vertical_offset = kart->getKartProperties()->getVertRescueOffset() *
kart->getKartHeight(); kart->getKartHeight();
kart->getBody()->translate(btVector3(0, vertical_offset, 0)); kart->getBody()->translate(btVector3(0, vertical_offset, 0));
} }
else else
{ {
fprintf(stderr, "WARNING: invalid position after rescue for kart %s on track %s.\n", fprintf(stderr, "WARNING: invalid position after rescue for kart %s on track %s.\n",
(kart->getIdent().c_str()), m_track->getIdent().c_str()); (kart->getIdent().c_str()), m_track->getIdent().c_str());
} }
} // moveKartAfterRescue } // moveKartAfterRescue
/** Set position and team for the karts */ /** Set position and team for the karts */
void SoccerWorld::initKartList() void SoccerWorld::initKartList()
{ {
const unsigned int kart_amount = m_karts.size(); const unsigned int kart_amount = m_karts.size();
// Set kart positions, ordering them by team // Set kart positions, ordering them by team
for(unsigned int n=0; n<kart_amount; n++) for(unsigned int n=0; n<kart_amount; n++)
{ {
m_karts[n]->setPosition(-1); m_karts[n]->setPosition(-1);
} }
// TODO: remove // TODO: remove
int team_karts_amount[NB_SOCCER_TEAMS]; int team_karts_amount[NB_SOCCER_TEAMS];
memset(team_karts_amount, 0, sizeof(team_karts_amount)); memset(team_karts_amount, 0, sizeof(team_karts_amount));
{ {
// Set the kart teams if they haven't been already set by the setup screen // Set the kart teams if they haven't been already set by the setup screen
// (happens when the setup screen is skipped, with 1 player) // (happens when the setup screen is skipped, with 1 player)
SoccerTeam round_robin_team = SOCCER_TEAM_RED; SoccerTeam round_robin_team = SOCCER_TEAM_RED;
for(unsigned int n=0; n<kart_amount; n++) for(unsigned int n=0; n<kart_amount; n++)
{ {
if(race_manager->getLocalKartInfo(n).getSoccerTeam() == SOCCER_TEAM_NONE) if(race_manager->getLocalKartInfo(n).getSoccerTeam() == SOCCER_TEAM_NONE)
race_manager->setLocalKartSoccerTeam( race_manager->setLocalKartSoccerTeam(
race_manager->getLocalKartInfo(n).getLocalPlayerId(),round_robin_team); race_manager->getLocalKartInfo(n).getLocalPlayerId(),round_robin_team);
team_karts_amount[race_manager->getLocalKartInfo(n).getSoccerTeam()]++; team_karts_amount[race_manager->getLocalKartInfo(n).getSoccerTeam()]++;
round_robin_team = (round_robin_team==SOCCER_TEAM_RED ? round_robin_team = (round_robin_team==SOCCER_TEAM_RED ?
SOCCER_TEAM_BLUE : SOCCER_TEAM_RED); SOCCER_TEAM_BLUE : SOCCER_TEAM_RED);
}// next kart }// next kart
} }
// Compute start positions for each team //Loading the indicator textures
int team_cur_position[NB_SOCCER_TEAMS]; irr::video::ITexture *redTeamTexture = irr_driver->getTexture(
team_cur_position[0] = 1; file_manager->getTextureFile("soccer_player_red.png"));
for(int i=1 ; i < (int)NB_SOCCER_TEAMS ; i++) irr::video::ITexture *blueTeamTexture = irr_driver->getTexture(
team_cur_position[i] = team_karts_amount[i-1] + team_cur_position[i-1]; file_manager->getTextureFile("soccer_player_blue.png"));
//Assigning indicators
// Set kart positions, ordering them by team for(int i=0; i<kart_amount; i++){
for(unsigned int n=0; n<kart_amount; n++) scene::ISceneNode *hatNode;
{ if(race_manager->getLocalKartInfo(i).getSoccerTeam() == SOCCER_TEAM_RED)
hatNode = irr_driver->addBillboard(core::dimension2d<irr::f32>(0.3,0.3)
SoccerTeam team = race_manager->getLocalKartInfo(n).getSoccerTeam(); ,redTeamTexture,m_karts[i]->getKartModel()->getAnimatedNode()->getJointNode("Head"));
m_karts[n]->setPosition(team_cur_position[team]); else
team_cur_position[team]++; hatNode = irr_driver->addBillboard(core::dimension2d<irr::f32>(0.3,0.3)
}// next kart ,blueTeamTexture,m_karts[i]->getKartModel()->getAnimatedNode()->getJointNode("Head"));
} hatNode->setPosition(m_karts[i]->getKartModel()->getHatOffset());
}
// Compute start positions for each team
int team_cur_position[NB_SOCCER_TEAMS];
team_cur_position[0] = 1;
for(int i=1 ; i < (int)NB_SOCCER_TEAMS ; i++)
team_cur_position[i] = team_karts_amount[i-1] + team_cur_position[i-1];
// Set kart positions, ordering them by team
for(unsigned int n=0; n<kart_amount; n++)
{
SoccerTeam team = race_manager->getLocalKartInfo(n).getSoccerTeam();
m_karts[n]->setPosition(team_cur_position[team]);
team_cur_position[team]++;
}// next kart
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int SoccerWorld::getScore(unsigned int i){ int SoccerWorld::getScore(unsigned int i){
return m_team_goals[i]; return m_team_goals[i];