diff --git a/data/gui/materials.xml b/data/gui/materials.xml index 16927e83e..8b9a7fb69 100644 --- a/data/gui/materials.xml +++ b/data/gui/materials.xml @@ -4,5 +4,7 @@ + + \ No newline at end of file diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index 04bdc7aa6..8bb0b230b 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -850,12 +850,14 @@ PerCameraNode *IrrDriver::addPerCameraMesh(scene::IMesh* mesh, */ scene::ISceneNode *IrrDriver::addBillboard(const core::dimension2d< f32 > size, video::ITexture *texture, - scene::ISceneNode* parent) + scene::ISceneNode* parent, bool alphaTesting) { scene::IBillboardSceneNode* node = m_scene_manager->addBillboardSceneNode(parent, size); assert(node->getMaterialCount() > 0); node->setMaterialTexture(0, texture); + if(alphaTesting) + node->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF); return node; } // addMesh diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index a7d6b3082..125fa9f60 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -159,7 +159,7 @@ public: scene::ISceneNode *parent = NULL); scene::ISceneNode *addBillboard(const core::dimension2d< f32 > size, video::ITexture *texture, - scene::ISceneNode* parent=NULL); + scene::ISceneNode* parent=NULL, bool alphaTesting = false); scene::IParticleSystemSceneNode *addParticleNode(bool default_emitter=true); diff --git a/src/karts/kart_model.cpp b/src/karts/kart_model.cpp index 814f64ede..730dbb549 100644 --- a/src/karts/kart_model.cpp +++ b/src/karts/kart_model.cpp @@ -278,39 +278,7 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models) lod_node->add(500, static_model, true); m_animated_node = static_cast(node); - 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) + attachHat(); #ifdef DEBUG std::string debug_name = m_model_filename+" (animated-kart-model)"; @@ -704,4 +672,40 @@ void KartModel::update(float rotation_dt, float steer, const float suspension[4] m_animated_node->setCurrentFrame(frame); } // 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) +} diff --git a/src/karts/kart_model.hpp b/src/karts/kart_model.hpp index 326f7bcca..9fdb3eea9 100644 --- a/src/karts/kart_model.hpp +++ b/src/karts/kart_model.hpp @@ -231,9 +231,15 @@ public: // ------------------------------------------------------------------------ /** Name of the hat mesh to use. */ void setHatMeshName(const std::string &name) {m_hat_name = name; } + // ------------------------------------------------------------------------ + void attachHat(); // ------------------------------------------------------------------------ /** Returns the array of wheel nodes. */ scene::ISceneNode** getWheelNodes() { return m_wheel_node; } + // ------------------------------------------------------------------------ + scene::IAnimatedMeshSceneNode* getAnimatedNode(){ return m_animated_node; } + // ------------------------------------------------------------------------ + core::vector3df getHatOffset() { return m_hat_offset; } }; // KartModel #endif diff --git a/src/modes/soccer_world.cpp b/src/modes/soccer_world.cpp index 0d05351e6..621ce2acb 100644 --- a/src/modes/soccer_world.cpp +++ b/src/modes/soccer_world.cpp @@ -1,242 +1,411 @@ -// SuperTuxKart - a fun racing game with go-kart -// Copyright (C) 2006 SuperTuxKart-Team -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 3 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include "modes/soccer_world.hpp" - -#include -#include - -#include "audio/music_manager.hpp" -#include "io/file_manager.hpp" -#include "karts/abstract_kart.hpp" -#include "karts/kart_model.hpp" -#include "karts/kart_properties.hpp" -#include "karts/rescue_animation.hpp" -#include "physics/physics.hpp" -#include "states_screens/race_gui_base.hpp" -#include "tracks/track.hpp" -#include "tracks/track_object_manager.hpp" -#include "utils/constants.hpp" - -//----------------------------------------------------------------------------- -/** Constructor. Sets up the clock mode etc. - */ -SoccerWorld::SoccerWorld() : WorldWithRank() -{ - WorldStatus::setClockMode(CLOCK_CHRONO); - m_use_highscores = false; -} // SoccerWorld - -//----------------------------------------------------------------------------- -/** Initializes the soccer world. It sets up the data structure - * to keep track of points etc. for each kart. - */ -void SoccerWorld::init() -{ - WorldWithRank::init(); - m_display_rank = false; - - // check for possible problems if AI karts were incorrectly added - if(getNumKarts() > race_manager->getNumPlayers()) - { - fprintf(stderr, "No AI exists for this game mode\n"); - exit(1); - } -} // init - -//----------------------------------------------------------------------------- -/** Called then a battle is restarted. - */ -void SoccerWorld::reset() -{ - WorldWithRank::reset(); - - m_can_score_points = true; - memset(m_team_goals, 0, sizeof(m_team_goals)); - - initKartList(); -} // reset - -//----------------------------------------------------------------------------- -/** Returns the internal identifier for this race. - */ -const std::string& SoccerWorld::getIdent() const -{ - return IDENT_SOCCER; -} // getIdent - -//----------------------------------------------------------------------------- -/** Update the world and the track. - * \param dt Time step size. - */ -void SoccerWorld::update(float dt) -{ - WorldWithRank::update(dt); - WorldWithRank::updateTrack(dt); - - // TODO -} // update - -void SoccerWorld::onCheckGoalTriggered(bool first_goal) -{ - // TODO - if(m_can_score_points) - printf("*** GOOOOOOOOOAAAAAAALLLLLL!!!! (team: %d) ***\n", first_goal ? 0 : 1); - - //m_check_goals_enabled = false; // TODO: remove? - - // Reset original positions for the soccer balls - TrackObjectManager* tom = getTrack()->getTrackObjectManager(); - assert(tom); - - PtrVector& objects = tom->getObjects(); - for(int i=0; iisSoccerBall()) - continue; - - obj->reset(); - } - - //for(int i=0 ; i < getNumKarts() ; i++ - - /*if(World::getWorld()->getTrack()->isAutoRescueEnabled() && - !getKartAnimation() && fabs(getRoll())>60*DEGREE_TO_RAD && - fabs(getSpeed())<3.0f ) - { - new RescueAnimation(this, true); - }*/ - - // TODO: rescue the karts - // TODO: score a point -} // onCheckGoalTriggered - -//----------------------------------------------------------------------------- -/** The battle is over if only one kart is left, or no player kart. - */ -bool SoccerWorld::isRaceOver() -{ - // for tests : never over when we have a single player there :) - if (race_manager->getNumPlayers() < 2) - { - return false; - } - - // TODO - return getCurrentNumKarts()==1 || getCurrentNumPlayers()==0; -} // isRaceOver - -//----------------------------------------------------------------------------- -/** 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, - * and then updates the ranks. - */ -void SoccerWorld::terminateRace() -{ - m_can_score_points = false; - WorldWithRank::terminateRace(); -} // terminateRace - -//----------------------------------------------------------------------------- -/** Returns the data to display in the race gui. - */ -void SoccerWorld::getKartsDisplayInfo( - std::vector *info) -{ - // TODO!! - /* - const unsigned int kart_amount = getNumKarts(); - for(unsigned int i = 0; i < kart_amount ; i++) - { - RaceGUIBase::KartIconDisplayInfo& rank_info = (*info)[i]; - - // reset color - rank_info.lap = -1; - - AbstractKart* kart = getKart(i); - switch(kart->getSoccerTeam()) - { - case SOCCER_TEAM_BLUE: - rank_info.r = 0.0f; - rank_info.g = 0.0f; - rank_info.b = 0.7f; - break; - case SOCCER_TEAM_RED: - rank_info.r = 0.9f; - rank_info.g = 0.0f; - rank_info.b = 0.0f; - break; - default: - assert(false && "Soccer team not set to blue or red"); - rank_info.r = 0.0f; - rank_info.g = 0.0f; - rank_info.b = 0.0f; - } - } - */ -} // getKartsDisplayInfo - -// ---------------------------------------------------------------------------- -/** Set position and team for the karts */ -void SoccerWorld::initKartList() -{ - const unsigned int kart_amount = m_karts.size(); - - // Set kart positions, ordering them by team - for(unsigned int n=0; nsetPosition(-1); - } - // TODO: remove -/* - const unsigned int kart_amount = m_karts.size(); - - int team_karts_amount[NB_SOCCER_TEAMS]; - memset(team_karts_amount, 0, sizeof(team_karts_amount)); - - { - // 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) - SoccerTeam round_robin_team = SOCCER_TEAM_RED; - for(unsigned int n=0; ngetSoccerTeam() == SOCCER_TEAM_NONE) - m_karts[n]->setSoccerTeam(round_robin_team); - - team_karts_amount[m_karts[n]->getSoccerTeam()]++; - - round_robin_team = (round_robin_team==SOCCER_TEAM_RED ? - SOCCER_TEAM_BLUE : SOCCER_TEAM_RED); - }// next kart - } - - // 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; ngetSoccerTeam(); - m_karts[n]->setPosition(team_cur_position[team]); - team_cur_position[team]++; - }// next kart -*/ -} +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2006 SuperTuxKart-Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "modes/soccer_world.hpp" + +#include +#include + +#include "audio/music_manager.hpp" +#include "io/file_manager.hpp" +#include "karts/abstract_kart.hpp" +#include "karts/kart.hpp" +#include "karts/kart_model.hpp" +#include "karts/kart_properties.hpp" +#include "karts/rescue_animation.hpp" +#include "karts/controller/player_controller.hpp" +#include "physics/physics.hpp" +#include "states_screens/race_gui_base.hpp" +#include "tracks/track.hpp" +#include "tracks/track_object_manager.hpp" +#include "utils/constants.hpp" + +//----------------------------------------------------------------------------- +/** Constructor. Sets up the clock mode etc. + */ +SoccerWorld::SoccerWorld() : WorldWithRank() +{ + WorldStatus::setClockMode(CLOCK_CHRONO); + m_use_highscores = false; +} // SoccerWorld + +//----------------------------------------------------------------------------- +/** Initializes the soccer world. It sets up the data structure + * to keep track of points etc. for each kart. + */ +void SoccerWorld::init() +{ + WorldWithRank::init(); + m_display_rank = false; + + // check for possible problems if AI karts were incorrectly added + if(getNumKarts() > race_manager->getNumPlayers()) + { + fprintf(stderr, "No AI exists for this game mode\n"); + exit(1); + } + m_goal_target = race_manager->getMaxGoal(); + printf("Max Goal: %d\n", m_goal_target); +} // init + +//----------------------------------------------------------------------------- +/** Called then a battle is restarted. + */ +void SoccerWorld::reset() +{ + WorldWithRank::reset(); + + m_can_score_points = true; + memset(m_team_goals, 0, sizeof(m_team_goals)); + + initKartList(); +} // reset + +//----------------------------------------------------------------------------- +/** Returns the internal identifier for this race. + */ +const std::string& SoccerWorld::getIdent() const +{ + return IDENT_SOCCER; +} // getIdent + +//----------------------------------------------------------------------------- +/** Update the world and the track. + * \param dt Time step size. + */ +void SoccerWorld::update(float dt) +{ + WorldWithRank::update(dt); + WorldWithRank::updateTrack(dt); + + // TODO +} // update + +void SoccerWorld::onCheckGoalTriggered(bool first_goal) +{ + // TODO + if(m_can_score_points){ + printf("*** GOOOOOOOOOAAAAAAALLLLLL!!!! (team: %d) ***\n", first_goal ? 0 : 1); + m_team_goals[first_goal]++; + printf("Score:\nTeam One %d : %d Team Two\n", m_team_goals[0], m_team_goals[1]); + } + + //m_check_goals_enabled = false; // TODO: remove? + + // Reset original positions for the soccer balls + TrackObjectManager* tom = getTrack()->getTrackObjectManager(); + assert(tom); + + PtrVector& objects = tom->getObjects(); + for(int i=0; iisSoccerBall()) + continue; + + obj->reset(); + obj->getPhysics()->reset(); + } + + //Resetting the ball triggers the goal check line one more time. + //This ensures that only one goal is counted, and the second is ignored. + m_can_score_points = !m_can_score_points; + + //for(int i=0 ; i < getNumKarts() ; i++ + + /*if(World::getWorld()->getTrack()->isAutoRescueEnabled() && + !getKartAnimation() && fabs(getRoll())>60*DEGREE_TO_RAD && + fabs(getSpeed())<3.0f ) + { + new RescueAnimation(this, true); + }*/ + + // TODO: rescue the karts + // TODO: score a point +} // onCheckGoalTriggered + +//----------------------------------------------------------------------------- +/** The battle is over if only one kart is left, or no player kart. + */ +bool SoccerWorld::isRaceOver() +{ + // for tests : never over when we have a single player there :) + if (race_manager->getNumPlayers() < 2) + { + return false; + } + // One team scored the target goals ... + else if(getScore(0) >= m_goal_target || + getScore(1) >= m_goal_target){ + return true; + } + // TODO + return getCurrentNumKarts()==1 || getCurrentNumPlayers()==0; +} // isRaceOver + +//----------------------------------------------------------------------------- +/** 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, + * and then updates the ranks. + */ +void SoccerWorld::terminateRace() +{ + m_can_score_points = false; + WorldWithRank::terminateRace(); +} // terminateRace + +//----------------------------------------------------------------------------- +/** Returns the data to display in the race gui. + */ +void SoccerWorld::getKartsDisplayInfo( + std::vector *info) +{ + // TODO!! + /* + const unsigned int kart_amount = getNumKarts(); + for(unsigned int i = 0; i < kart_amount ; i++) + { + RaceGUIBase::KartIconDisplayInfo& rank_info = (*info)[i]; + + // reset color + rank_info.lap = -1; + + AbstractKart* kart = getKart(i); + switch(kart->getSoccerTeam()) + { + case SOCCER_TEAM_BLUE: + rank_info.r = 0.0f; + rank_info.g = 0.0f; + rank_info.b = 0.7f; + break; + case SOCCER_TEAM_RED: + rank_info.r = 0.9f; + rank_info.g = 0.0f; + rank_info.b = 0.0f; + break; + default: + assert(false && "Soccer team not set to blue or red"); + rank_info.r = 0.0f; + rank_info.g = 0.0f; + rank_info.b = 0.0f; + } + } + */ +} // getKartsDisplayInfo + +//----------------------------------------------------------------------------- +/** Moves a kart to its rescue position. + * \param kart The kart that was rescued. + */ +void SoccerWorld::moveKartAfterRescue(AbstractKart* kart) +{ + // find closest point to drop kart on + World *world = World::getWorld(); + const int start_spots_amount = world->getTrack()->getNumberOfStartPositions(); + assert(start_spots_amount > 0); + + float largest_accumulated_distance_found = -1; + int furthest_id_found = -1; + + const float kart_x = kart->getXYZ().getX(); + const float kart_z = kart->getXYZ().getZ(); + + for(int n=0; ngetTrack()->getStartTransform(n); + const Vec3 &v=s.getOrigin(); + float accumulatedDistance = .0f; + bool spawnPointClear = true; + + for(unsigned int k=0; kgetKart(k); + const float currentKart_x = currentKart->getXYZ().getX(); + const float currentKartk_z = currentKart->getXYZ().getZ(); + + if(kart_x!=currentKart_x && kart_z !=currentKartk_z) + { + float absDistance = fabs(currentKart_x - v.getX()) + + fabs(currentKartk_z - v.getZ()); + if(absDistance < CLEAR_SPAWN_RANGE) + { + spawnPointClear = false; + break; + } + accumulatedDistance += absDistance; + } + } + + if(largest_accumulated_distance_found < accumulatedDistance && spawnPointClear) + { + furthest_id_found = n; + largest_accumulated_distance_found = accumulatedDistance; + } + } + + assert(furthest_id_found != -1); + const btTransform &s = world->getTrack()->getStartTransform(furthest_id_found); + const Vec3 &xyz = s.getOrigin(); + kart->setXYZ(xyz); + kart->setRotation(s.getRotation()); + + //position kart from same height as in World::resetAllKarts + btTransform pos; + pos.setOrigin(kart->getXYZ()+btVector3(0, 0.5f*kart->getKartHeight(), 0.0f)); + pos.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), 0 /* angle */) ); + + kart->getBody()->setCenterOfMassTransform(pos); + + //project kart to surface of track + bool kart_over_ground = m_track->findGround(kart); + + if (kart_over_ground) + { + //add vertical offset so that the kart starts off above the track + float vertical_offset = kart->getKartProperties()->getVertRescueOffset() * + kart->getKartHeight(); + kart->getBody()->translate(btVector3(0, vertical_offset, 0)); + } + else + { + fprintf(stderr, "WARNING: invalid position after rescue for kart %s on track %s.\n", + (kart->getIdent().c_str()), m_track->getIdent().c_str()); + } +} // moveKartAfterRescue + +/** Set position and team for the karts */ +void SoccerWorld::initKartList() +{ + const unsigned int kart_amount = m_karts.size(); + + // Set kart positions, ordering them by team + for(unsigned int n=0; nsetPosition(-1); + } + // TODO: remove + + int team_karts_amount[NB_SOCCER_TEAMS]; + memset(team_karts_amount, 0, sizeof(team_karts_amount)); + + { + // 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) + SoccerTeam round_robin_team = SOCCER_TEAM_RED; + for(unsigned int n=0; ngetLocalKartInfo(n).getSoccerTeam() == SOCCER_TEAM_NONE) + race_manager->setLocalKartSoccerTeam( + race_manager->getLocalKartInfo(n).getLocalPlayerId(),round_robin_team); + + team_karts_amount[race_manager->getLocalKartInfo(n).getSoccerTeam()]++; + + round_robin_team = (round_robin_team==SOCCER_TEAM_RED ? + SOCCER_TEAM_BLUE : SOCCER_TEAM_RED); + }// next kart + } + + //Loading the indicator textures + irr::video::ITexture *redTeamTexture = irr_driver->getTexture( + file_manager->getTextureFile("soccer_player_red.png")); + irr::video::ITexture *blueTeamTexture = irr_driver->getTexture( + file_manager->getTextureFile("soccer_player_blue.png")); + //Assigning indicators + for(int i=0; igetLocalKartInfo(i).getSoccerTeam() == SOCCER_TEAM_RED) + hatNode = irr_driver->addBillboard(core::dimension2d(0.3,0.3) + ,redTeamTexture,m_karts[i]->getNode(), true); + else + hatNode = irr_driver->addBillboard(core::dimension2d(0.3,0.3) + ,blueTeamTexture,m_karts[i]->getNode(),true); + 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; ngetLocalKartInfo(n).getSoccerTeam(); + m_karts[n]->setPosition(team_cur_position[team]); + team_cur_position[team]++; + }// next kart +} +//----------------------------------------------------------------------------- +int SoccerWorld::getScore(unsigned int i){ + return m_team_goals[i]; +} +//----------------------------------------------------------------------------- +int SoccerWorld::getTeamLeader(unsigned int team){ + for(int i = 0; i< m_karts.size(); i++){ + if(race_manager->getLocalKartInfo(i).getSoccerTeam() == (SoccerTeam) team) + return i; + } + return -1; + } +//----------------------------------------------------------------------------- +AbstractKart *SoccerWorld::createKart(const std::string &kart_ident, int index, + int local_player_id, int global_player_id, + RaceManager::KartType kart_type) +{ + int posIndex = index; + if(race_manager->getLocalKartInfo(index).getSoccerTeam() == SOCCER_TEAM_RED){ + if(index % 2 != 0) posIndex += 1; + } + else if(race_manager->getLocalKartInfo(index).getSoccerTeam() == SOCCER_TEAM_BLUE){ + if(index % 2 != 1) posIndex += 1; + } + int position = index+1; + btTransform init_pos = m_track->getStartTransform(posIndex); + AbstractKart *new_kart = new Kart(kart_ident, index, position, init_pos); + new_kart->init(race_manager->getKartType(index)); + Controller *controller = NULL; + switch(kart_type) + { + case RaceManager::KT_PLAYER: + controller = new PlayerController(new_kart, + StateManager::get()->getActivePlayer(local_player_id), + local_player_id); + m_num_players ++; + break; + case RaceManager::KT_NETWORK_PLAYER: + break; // Avoid compiler warning about enum not handled. + //controller = new NetworkController(kart_ident, position, init_pos, + // global_player_id); + //m_num_players++; + //break; + case RaceManager::KT_AI: + controller = loadAIController(new_kart); + break; + case RaceManager::KT_GHOST: + break; + case RaceManager::KT_LEADER: + break; + } + + new_kart->setController(controller); + + return new_kart; +} // createKart \ No newline at end of file diff --git a/src/modes/soccer_world.hpp b/src/modes/soccer_world.hpp index 591c0659a..ff09af2a2 100644 --- a/src/modes/soccer_world.hpp +++ b/src/modes/soccer_world.hpp @@ -1,79 +1,94 @@ -// -// SuperTuxKart - a fun racing game with go-kart -// Copyright (C) 2004 SuperTuxKart-Team -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 3 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#ifndef SOCCER_WORLD_HPP -#define SOCCER_WORLD_HPP - -#include "modes/world_with_rank.hpp" -#include "states_screens/race_gui_base.hpp" -#include "karts/abstract_kart.hpp" - -#include - -#include - -#define CLEAR_SPAWN_RANGE 5 - -class PhysicalObject; - -/** - * \brief An implementation of World, to provide the soccer game mode - * \ingroup modes - */ -class SoccerWorld : public WorldWithRank -{ -private: - /** Number of goals each team scored - */ - int m_team_goals[NB_SOCCER_TEAMS]; - - /** Whether or not goals can be scored (they are disabled when a point is scored - and re-enabled when the next game can be played)*/ - bool m_can_score_points; - -public: - - SoccerWorld(); - virtual ~SoccerWorld() {} - - virtual void init(); - - // clock events - virtual bool isRaceOver(); - virtual void terminateRace(); - - // overriding World methods - virtual void reset(); - - virtual bool useFastMusicNearEnd() const { return false; } - virtual void getKartsDisplayInfo( - std::vector *info); - virtual bool raceHasLaps(){ return false; } - - virtual const std::string& getIdent() const; - - virtual void update(float dt); - - void onCheckGoalTriggered(bool first_goal); - -private: - void initKartList(); -}; // SoccerWorld - - -#endif +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2004 SuperTuxKart-Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef SOCCER_WORLD_HPP +#define SOCCER_WORLD_HPP + +#include "modes/world_with_rank.hpp" +#include "states_screens/race_gui_base.hpp" +#include "karts/abstract_kart.hpp" + + +#include + +#include + +#define CLEAR_SPAWN_RANGE 5 + +class PhysicalObject; +class AbstractKart; +class Controller; + +/** + * \brief An implementation of World, to provide the soccer game mode + * \ingroup modes + */ +class SoccerWorld : public WorldWithRank +{ +private: + /** Number of goals each team scored + */ + int m_team_goals[NB_SOCCER_TEAMS]; + /** Number of goals needed to win + */ + int m_goal_target; + /** Whether or not goals can be scored (they are disabled when a point is scored + and re-enabled when the next game can be played)*/ + bool m_can_score_points; + + /** Team karts */ + + +public: + + SoccerWorld(); + virtual ~SoccerWorld() {} + + virtual void init(); + + // clock events + virtual bool isRaceOver(); + virtual void terminateRace(); + + // overriding World methods + virtual void reset(); + + virtual bool useFastMusicNearEnd() const { return false; } + virtual void getKartsDisplayInfo( + std::vector *info); + int getScore(unsigned int i); + virtual bool raceHasLaps(){ return false; } + virtual void moveKartAfterRescue(AbstractKart* kart); + + virtual const std::string& getIdent() const; + + virtual void update(float dt); + + void onCheckGoalTriggered(bool first_goal); + int getTeamLeader(unsigned int i); + +private: + void initKartList(); +protected: + virtual AbstractKart *createKart(const std::string &kart_ident, int index, + int local_player_id, int global_player_id, + RaceManager::KartType type); +}; // SoccerWorld + + +#endif diff --git a/src/modes/world_with_rank.hpp b/src/modes/world_with_rank.hpp index 6f3207bd9..887ca1028 100644 --- a/src/modes/world_with_rank.hpp +++ b/src/modes/world_with_rank.hpp @@ -76,6 +76,7 @@ public: virtual btTransform getRescueTransform(unsigned int index) const OVERRIDE; + }; // WorldWithRank #endif diff --git a/src/network/remote_kart_info.hpp b/src/network/remote_kart_info.hpp index 507458d08..cde5cda72 100644 --- a/src/network/remote_kart_info.hpp +++ b/src/network/remote_kart_info.hpp @@ -55,7 +55,7 @@ public: void setHostId(int id) { m_host_id = id; } void setLocalPlayerId(int id) { m_local_player_id = id; } void setGlobalPlayerId(int id) { m_global_player_id = id; } - void setSoccerTeam(SoccerTeam team) { m_soccer_team = team; } + const void setSoccerTeam(SoccerTeam team) { m_soccer_team = team; } int getHostId() const { return m_host_id; } int getLocalPlayerId() const { return m_local_player_id; } diff --git a/src/race/race_manager.hpp b/src/race/race_manager.hpp index 82028b227..57be3b6e4 100644 --- a/src/race/race_manager.hpp +++ b/src/race/race_manager.hpp @@ -331,6 +331,7 @@ private: int m_coin_target; bool m_has_time_target; float m_time_target; + int m_goal_target; void startNextRace(); // start a next race @@ -390,6 +391,10 @@ public: bool hasTimeTarget() const { return m_has_time_target; } + void setMaxGoal(int maxGoal){ m_goal_target = maxGoal; } + + int getMaxGoal(){ return m_goal_target; } + /** Sort karts and update the m_gp_rank KartStatus member, in preparation * for future calls to RaceManager::getKartGPRank or * RaceManager::getKartWithGPRank diff --git a/src/states_screens/race_gui.cpp b/src/states_screens/race_gui.cpp index d3cc53344..f8f89e93b 100644 --- a/src/states_screens/race_gui.cpp +++ b/src/states_screens/race_gui.cpp @@ -44,6 +44,7 @@ using namespace irr; #include "modes/follow_the_leader.hpp" #include "modes/linear_world.hpp" #include "modes/world.hpp" +#include "modes/soccer_world.hpp" #include "race/race_manager.hpp" #include "tracks/track.hpp" #include "utils/constants.hpp" @@ -191,6 +192,8 @@ void RaceGUI::renderGlobal(float dt) { drawGlobalPlayerIcons(m_map_height); } + + if(world->getTrack()->isSoccer()) drawScores(); } // renderGlobal //----------------------------------------------------------------------------- @@ -226,6 +229,63 @@ void RaceGUI::renderPlayerView(const Camera *camera, float dt) RaceGUIBase::renderPlayerView(camera, dt); } // renderPlayerView +//----------------------------------------------------------------------------- +void RaceGUI::drawScores() +{ + SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld(); + int offsetY = 5; + int offsetX = 5; + gui::ScalableFont* font = GUIEngine::getFont(); + static video::SColor color = video::SColor(255,255,255,255); + + //Draw kart icons above score(denoting teams) + irr::video::ITexture *red_team = irr_driver->getTexture( + file_manager->getTextureFile("soccer_ball_red.png")); + irr::video::ITexture *blue_team = irr_driver->getTexture( + file_manager->getTextureFile("soccer_ball_blue.png")); + + core::rect indicatorPos(offsetX-6, offsetY, + offsetX -6 + red_team->getSize().Width/8, + offsetY + red_team->getSize().Height/8); + core::rect sourceRect(core::position2d(0,0), + red_team->getOriginalSize()); + irr_driver->getVideoDriver()->draw2DImage(red_team,indicatorPos,sourceRect, + NULL,NULL,true); + + + for(unsigned int i=0; igetNumKarts(); i++){ + int j = soccerWorld->getTeamLeader(i); + if(j < 0) break; + + core::rect source(j*m_marker_rendered_size, 0, + (j+1)*m_marker_rendered_size,m_marker_rendered_size); + core::recti position(offsetX, offsetY, + offsetX + 2*m_marker_player_size, offsetY + 2*m_marker_player_size); + irr_driver->getVideoDriver()->draw2DImage(m_marker, position, source, + NULL, NULL, true); + core::stringw score = StringUtils::toWString(soccerWorld->getScore(i)); + int stringWidth = + GUIEngine::getFont()->getDimension(score.c_str()).Width; + int stringHeight = + GUIEngine::getFont()->getDimension(score.c_str()).Height; + core::recti pos(position.UpperLeftCorner.X + 5, + position.LowerRightCorner.Y + offsetY, + position.LowerRightCorner.X, + position.LowerRightCorner.Y + stringHeight); + + font->draw(score.c_str(),pos,color); + offsetX += position.LowerRightCorner.X; + } + offsetX = 80; + offsetY = 5; + indicatorPos = core::rect(offsetX, offsetY, + offsetX + blue_team->getSize().Width/8, + offsetY + blue_team->getSize().Height/8); + sourceRect = core::rect (core::position2d(0,0), + blue_team->getOriginalSize()); + irr_driver->getVideoDriver()->draw2DImage(blue_team,indicatorPos,sourceRect, + NULL,NULL,true); +} //----------------------------------------------------------------------------- /** Displays the racing time on the screen.s */ diff --git a/src/states_screens/race_gui.hpp b/src/states_screens/race_gui.hpp index bfd687bae..a159ded1e 100644 --- a/src/states_screens/race_gui.hpp +++ b/src/states_screens/race_gui.hpp @@ -105,6 +105,8 @@ private: /** Display items that are shown once only (for all karts). */ void drawGlobalMiniMap (); void drawGlobalTimer (); + void drawScores(); + public: diff --git a/src/states_screens/soccer_setup_screen.cpp b/src/states_screens/soccer_setup_screen.cpp index ce7ab72b1..8805236de 100644 --- a/src/states_screens/soccer_setup_screen.cpp +++ b/src/states_screens/soccer_setup_screen.cpp @@ -56,6 +56,7 @@ void SoccerSetupScreen::eventCallback(Widget* widget, const std::string& name, c if(name == "continue") { StateManager::get()->pushScreen( ArenasScreen::getInstance() ); + race_manager->setMaxGoal(getWidget("goalamount")->getValue()); } else if (name == "back") { @@ -221,7 +222,7 @@ GUIEngine::EventPropagation SoccerSetupScreen::filterActions( PlayerAction acti break; } - if(team_switch != SOCCER_TEAM_NONE) // A player wants to change its team? + if(team_switch != SOCCER_TEAM_NONE) // A player wants to change his team? { // Find the corresponding kart view, update its team and update the layout for(int i=0 ; i < nb_players ; i++)