diff --git a/data/gui/soccer_setup.stkgui b/data/gui/soccer_setup.stkgui
index 4ca6f353b..05691bf84 100644
--- a/data/gui/soccer_setup.stkgui
+++ b/data/gui/soccer_setup.stkgui
@@ -6,7 +6,7 @@
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/src/karts/abstract_kart.cpp b/src/karts/abstract_kart.cpp
index ad6dae9dc..882efa6a8 100644
--- a/src/karts/abstract_kart.cpp
+++ b/src/karts/abstract_kart.cpp
@@ -52,6 +52,8 @@ AbstractKart::AbstractKart(const std::string& ident,
m_kart_width = m_kart_model->getWidth();
m_kart_height = m_kart_model->getHeight();
m_kart_length = m_kart_model->getLength();
+
+ m_soccer_team = SOCCER_TEAM_NONE;
} // AbstractKart
// ----------------------------------------------------------------------------
@@ -71,6 +73,7 @@ void AbstractKart::reset()
delete m_kart_animation;
m_kart_animation = NULL;
}
+ m_soccer_team = SOCCER_TEAM_NONE;
} // reset
// ----------------------------------------------------------------------------
diff --git a/src/karts/abstract_kart.hpp b/src/karts/abstract_kart.hpp
index bbb6d72fc..dabfd45f6 100644
--- a/src/karts/abstract_kart.hpp
+++ b/src/karts/abstract_kart.hpp
@@ -39,6 +39,14 @@ class Powerup;
class Skidding;
class SlipStream;
+enum SoccerTeam
+{
+ SOCCER_TEAM_NONE=-1,
+ SOCCER_TEAM_RED=0,
+ SOCCER_TEAM_BLUE,
+ NB_SOCCER_TEAMS
+};
+
/** An abstract interface for the actual karts. Some functions are actually
* implemented here in order to allow inlining.
* \ingroup karts
@@ -75,6 +83,8 @@ protected:
/** A kart animation object to handle rescue, explosion etc. */
AbstractKartAnimation *m_kart_animation;
+ SoccerTeam m_soccer_team;
+
public:
AbstractKart(const std::string& ident,
int world_kart_id,
@@ -268,6 +278,12 @@ public:
/** Returns the initial position of this kart. */
virtual int getInitialPosition() const = 0;
// ------------------------------------------------------------------------
+ /** Returns the current soccer team */
+ SoccerTeam getSoccerTeam() const {return m_soccer_team;}
+ // ------------------------------------------------------------------------
+ /** Sets the current soccer team */
+ void setSoccerTeam(SoccerTeam team) { m_soccer_team = team; }
+ // ------------------------------------------------------------------------
/** True if the wheels are touching the ground. */
virtual bool isOnGround() const = 0;
// ------------------------------------------------------------------------
diff --git a/src/modes/soccer_world.cpp b/src/modes/soccer_world.cpp
index 0d7a12d35..3e9ed8928 100644
--- a/src/modes/soccer_world.cpp
+++ b/src/modes/soccer_world.cpp
@@ -52,6 +52,7 @@ void SoccerWorld::init()
m_display_rank = false;
m_can_score_points = true;
+ memset(m_team_goals, 0, sizeof(m_team_goals));
// check for possible problems if AI karts were incorrectly added
if(getNumKarts() > race_manager->getNumPlayers())
@@ -60,24 +61,7 @@ void SoccerWorld::init()
exit(1);
}
- const unsigned int kart_amount = m_karts.size();
-
- for(unsigned int n=0; nsetPosition(-1);
- }// next kart
-
-
- SoccerEvent evt;
- evt.m_time = 0.0f;
- evt.m_kart_info = m_kart_info;
- m_soccer_events.push_back(evt);
+ initKartList();
} // SoccerWorld
@@ -136,59 +120,6 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal)
// TODO: score a point
}
-//-----------------------------------------------------------------------------
-/** Updates the ranking of the karts.
- */
-void SoccerWorld::updateKartRanks()
-{
- beginSetKartPositions();
- // sort karts by their times then give each one its position.
- // in battle-mode, long time = good (meaning he survived longer)
-
- const unsigned int NUM_KARTS = getNumKarts();
-
- int *karts_list = new int[NUM_KARTS];
- for( unsigned int n = 0; n < NUM_KARTS; ++n ) karts_list[n] = n;
-
- bool sorted=false;
- do
- {
- sorted = true;
- for( unsigned int n = 0; n < NUM_KARTS-1; ++n )
- {
- const int this_karts_time =
- m_karts[karts_list[n]]->hasFinishedRace()
- ? (int)m_karts[karts_list[n]]->getFinishTime()
- : (int)WorldStatus::getTime();
- const int next_karts_time =
- m_karts[karts_list[n+1]]->hasFinishedRace()
- ? (int)m_karts[karts_list[n+1]]->getFinishTime()
- : (int)WorldStatus::getTime();
-
- // Swap if next kart survived longer or has more lives
- bool swap = next_karts_time > this_karts_time ||
- m_kart_info[karts_list[n+1]].m_goals
- > m_kart_info[karts_list[n]].m_goals;
-
- if(swap)
- {
- int tmp = karts_list[n+1];
- karts_list[n+1] = karts_list[n];
- karts_list[n] = tmp;
- sorted = false;
- break;
- }
- } // for n = 0; n < NUM_KARTS-1
- } while(!sorted);
-
- for( unsigned int n = 0; n < NUM_KARTS; ++n )
- {
- setKartPosition(karts_list[n], n+1);
- }
- delete [] karts_list;
- endSetKartPositions();
-} // updateKartRank
-
//-----------------------------------------------------------------------------
/** The battle is over if only one kart is left, or no player kart.
*/
@@ -212,7 +143,6 @@ bool SoccerWorld::isRaceOver()
void SoccerWorld::terminateRace()
{
m_can_score_points = false;
- updateKartRanks();
WorldWithRank::terminateRace();
} // terminateRace
@@ -224,25 +154,10 @@ void SoccerWorld::restartRace()
WorldWithRank::restartRace();
m_can_score_points = true;
+ memset(m_team_goals, 0, sizeof(m_team_goals));
- const unsigned int kart_amount = m_karts.size();
-
- for(unsigned int n=0; nsetPosition(-1);
- }// next kart
-
- // remove old soccer events
- m_soccer_events.clear();
+ initKartList();
- // add initial occer event
- SoccerEvent evt;
- evt.m_time = 0.0f;
- evt.m_kart_info = m_kart_info;
- m_soccer_events.push_back(evt);
} // restartRace
//-----------------------------------------------------------------------------
@@ -259,14 +174,25 @@ void SoccerWorld::getKartsDisplayInfo(
// reset color
rank_info.lap = -1;
- rank_info.r = 0.5;
- rank_info.g = 0.5;
- rank_info.b = 0.5;
-
- char goals[4];
- sprintf(goals, "%i", m_kart_info[i].m_goals);
-
- rank_info.m_text = goals;
+ 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
@@ -351,3 +277,52 @@ void SoccerWorld::moveKartAfterRescue(AbstractKart* kart)
(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
+/*
+ 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
+*/
+}
diff --git a/src/modes/soccer_world.hpp b/src/modes/soccer_world.hpp
index 338929cc2..b3b6ccb05 100644
--- a/src/modes/soccer_world.hpp
+++ b/src/modes/soccer_world.hpp
@@ -21,6 +21,7 @@
#include "modes/world_with_rank.hpp"
#include "states_screens/race_gui_base.hpp"
+#include "karts/abstract_kart.hpp"
#include
@@ -37,14 +38,9 @@ class PhysicalObject;
class SoccerWorld : public WorldWithRank
{
private:
- struct SoccerInfo
- {
- int m_goals;
- };
-
- /** This vector contains an 'SoccerInfo' struct for every kart in the race.
- */
- std::vector m_kart_info;
+ /** 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)*/
@@ -52,14 +48,6 @@ private:
public:
- /** Used to show a nice graph when battle is over */
- struct SoccerEvent
- {
- float m_time;
- std::vector m_kart_info;
- };
- std::vector m_soccer_events;
-
SoccerWorld();
virtual ~SoccerWorld() {}
@@ -83,7 +71,9 @@ public:
virtual void update(float dt);
void onCheckGoalTriggered(bool first_goal);
- void updateKartRanks();
+
+private:
+ void initKartList();
}; // SoccerWorld
diff --git a/src/states_screens/race_gui_base.cpp b/src/states_screens/race_gui_base.cpp
index e364e1b6d..d7a861666 100644
--- a/src/states_screens/race_gui_base.cpp
+++ b/src/states_screens/race_gui_base.cpp
@@ -720,6 +720,11 @@ void RaceGUIBase::drawGlobalReadySetGo()
*/
void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin)
{
+ // For now, don't draw player icons when in soccer mode
+ const RaceManager::MinorRaceModeType minor_mode = race_manager->getMinorMode();
+ if(minor_mode == RaceManager::MINOR_MODE_SOCCER)
+ return;
+
int x_base = 10;
int y_base = 20;
unsigned int y_space = UserConfigParams::m_height - bottom_margin - y_base;
@@ -806,10 +811,8 @@ void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin)
//x,y is the target position
int lap = info.lap;
- // In battle mode and soccer mode there is no distance along track etc.
- const RaceManager::MinorRaceModeType minor_mode = race_manager->getMinorMode();
- if( minor_mode==RaceManager::MINOR_MODE_3_STRIKES ||
- minor_mode==RaceManager::MINOR_MODE_SOCCER)
+ // In battle mode mode there is no distance along track etc.
+ if( minor_mode==RaceManager::MINOR_MODE_3_STRIKES )
{
x = x_base;
y = previous_y+ICON_PLAYER_WIDTH+2;
diff --git a/src/states_screens/soccer_setup_screen.cpp b/src/states_screens/soccer_setup_screen.cpp
index fbb07b841..64c2f364b 100644
--- a/src/states_screens/soccer_setup_screen.cpp
+++ b/src/states_screens/soccer_setup_screen.cpp
@@ -19,6 +19,15 @@
#include "states_screens/state_manager.hpp"
#include "states_screens/arenas_screen.hpp"
+#include "guiengine/widgets/button_widget.hpp"
+#include "guiengine/widgets/spinner_widget.hpp"
+#include "guiengine/widgets/label_widget.hpp"
+#include "guiengine/widgets/model_view_widget.hpp"
+#include "guiengine/scalable_font.hpp"
+#include "io/file_manager.hpp"
+#include "karts/kart_properties_manager.hpp"
+#include "karts/kart_properties.hpp"
+#include "karts/kart_model.hpp"
using namespace GUIEngine;
DEFINE_SCREEN_SINGLETON( SoccerSetupScreen );
@@ -48,33 +57,182 @@ void SoccerSetupScreen::eventCallback(Widget* widget, const std::string& name, c
}
}
+// -----------------------------------------------------------------------------
+void SoccerSetupScreen::beforeAddingWidget()
+{
+ Widget* central_div = getWidget("central_div");
+
+ /*
+ 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
+ */
+
+ // BEGIN TEST
+ ModelViewWidget* kart_view = new ModelViewWidget();
+ kart_view->m_x = central_div->m_x + 10;
+ kart_view->m_y = central_div->m_y + 10;
+ kart_view->m_w = 200;
+ kart_view->m_h = 200;
+ kart_view->clearModels();
+
+ const std::string default_kart = UserConfigParams::m_default_kart;
+ const KartProperties* props =
+ kart_properties_manager->getKart(default_kart);
+ const KartModel &kart_model = props->getMasterKartModel();
+
+ kart_view->addModel( kart_model.getModel(), Vec3(0,0,0),
+ Vec3(35.0f, 35.0f, 35.0f),
+ kart_model.getBaseFrame() );
+ kart_view->addModel( kart_model.getWheelModel(0),
+ kart_model.getWheelGraphicsPosition(0) );
+ kart_view->addModel( kart_model.getWheelModel(1),
+ kart_model.getWheelGraphicsPosition(1) );
+ kart_view->addModel( kart_model.getWheelModel(2),
+ kart_model.getWheelGraphicsPosition(2) );
+ kart_view->addModel( kart_model.getWheelModel(3),
+ kart_model.getWheelGraphicsPosition(3) );
+ kart_view->setRotateContinuously( 35.0f );
+
+ kart_view->update(0);
+
+ central_div->getChildren().push_back(kart_view);
+ // END TEST
+
+ // Add "VS" label at the center of the rounded box
+ m_label_vs = new LabelWidget(true, false);
+
+ core::dimension2d vs_size = GUIEngine::getTitleFont()->getDimension( L"VS" );
+ m_label_vs->m_x = central_div->m_x + central_div->m_w/2 - vs_size.Width/2;
+ m_label_vs->m_y = central_div->m_y + central_div->m_h/2 - vs_size.Height/2;
+ m_label_vs->m_w = vs_size.Width;
+ m_label_vs->m_h = vs_size.Height;
+
+ central_div->getChildren().push_back(m_label_vs);
+}
+
// -----------------------------------------------------------------------------
void SoccerSetupScreen::init()
{
Screen::init();
+ // TODO: remember in config.xml the last number of goals
+ SpinnerWidget* goalamount = getWidget("goalamount");
+ goalamount->setValue(3);
+
+ // Set focus on "continue"
+ ButtonWidget* bt_continue = getWidget("continue");
+ bt_continue->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
+
+ // "VS" (needs to be done here for the Irrlicht element to be here)
+ m_label_vs->setText("VS", true);
+ /*
Widget* players_table = getWidget("players-table");
assert(players_table != NULL);
- // BEGIN TODO
- /*
- Widget* div = new Widget(WTYPE_DIV);
- div->m_properties[PROP_LAYOUT] = "horizontal-row";
- //widget.m_properties[prop_flag] = core::stringc(prop_name).c_str(); else widget.m_properties[prop_flag] = ""
- div->setParent(players_table->getIrrlichtElement());
- players_table->getChildren().push_back(div);
- //players_table->add();
+ manualAddWidget(new TeamViewWidget(this));
*/
-/* LabelWidget* lbl = new LabelWidget();
- lbl->m_properties[PROP_PROPORTION] = "1";
- lbl->m_properties[PROP_HEIGHT] = "100%";
- lbl->setText(L"bouYou", false);
- lbl->m_properties[PROP_TEXT_ALIGN] = "left";
- //widget.m_properties[prop_flag] = core::stringc(prop_name).c_str(); else widget.m_properties[prop_flag] = ""
- //lbl->setParent(players_table->getIrrlichtElement());
- players_table->getChildren().push_back(lbl);
- calculateLayout();
-*/
- // END TODO
+ /*// ----- Kart model view
+ m_model_view = new ModelViewWidget();
+
+ m_model_view->m_x = model_x;
+ m_model_view->m_y = model_y;
+ m_model_view->m_w = model_w;
+ m_model_view->m_h = model_h;
+ m_model_view->m_properties[PROP_ID] =
+ StringUtils::insertValues("@p%i_model", m_playerID);
+ //m_model_view->setParent(this);
+ m_children.push_back(m_model_view);
+
+ // Init kart model
+ const std::string default_kart = UserConfigParams::m_default_kart;
+ const KartProperties* props =
+ kart_properties_manager->getKart(default_kart);
+
+ if(!props)
+ {
+ // If the default kart can't be found (e.g. previously a addon
+ // kart was used, but the addon package was removed), use the
+ // first kart as a default. This way we don't have to hardcode
+ // any kart names.
+ int id = kart_properties_manager->getKartByGroup(kartGroup, 0);
+ if (id == -1)
+ {
+ props = kart_properties_manager->getKartById(0);
+ }
+ else
+ {
+ props = kart_properties_manager->getKartById(id);
+ }
+
+ if(!props)
+ {
+ fprintf(stderr,
+ "[KartSelectionScreen] WARNING: Can't find default "
+ "kart '%s' nor any other kart.\n",
+ default_kart.c_str());
+ exit(-1);
+ }
+ }
+ m_kartInternalName = props->getIdent();
+
+ const KartModel &kart_model = props->getMasterKartModel();
+
+ m_model_view->addModel( kart_model.getModel(), Vec3(0,0,0),
+ Vec3(35.0f, 35.0f, 35.0f),
+ kart_model.getBaseFrame() );
+ m_model_view->addModel( kart_model.getWheelModel(0),
+ kart_model.getWheelGraphicsPosition(0) );
+ m_model_view->addModel( kart_model.getWheelModel(1),
+ kart_model.getWheelGraphicsPosition(1) );
+ m_model_view->addModel( kart_model.getWheelModel(2),
+ kart_model.getWheelGraphicsPosition(2) );
+ m_model_view->addModel( kart_model.getWheelModel(3),
+ kart_model.getWheelGraphicsPosition(3) );
+ m_model_view->setRotateContinuously( 35.0f );
+
+ // ---- Kart name label
+ m_kart_name = new LabelWidget();
+ m_kart_name->setText(props->getName(), false);
+ m_kart_name->m_properties[PROP_TEXT_ALIGN] = "center";
+ m_kart_name->m_properties[PROP_ID] =
+ StringUtils::insertValues("@p%i_kartname", m_playerID);
+ m_kart_name->m_x = kart_name_x;
+ m_kart_name->m_y = kart_name_y;
+ m_kart_name->m_w = kart_name_w;
+ m_kart_name->m_h = kart_name_h;
+ //m_kart_name->setParent(this);
+ m_children.push_back(m_kart_name);*/
}
diff --git a/src/states_screens/soccer_setup_screen.hpp b/src/states_screens/soccer_setup_screen.hpp
index b53b3b068..6b87caadc 100644
--- a/src/states_screens/soccer_setup_screen.hpp
+++ b/src/states_screens/soccer_setup_screen.hpp
@@ -20,7 +20,7 @@
#include "guiengine/screen.hpp"
-namespace GUIEngine { class Widget; }
+namespace GUIEngine { class Widget; class LabelWidget; }
/**
* \brief Screen with soccer setup options
@@ -32,6 +32,9 @@ class SoccerSetupScreen : public GUIEngine::Screen, public GUIEngine::ScreenSing
SoccerSetupScreen();
+ /** The "VS" text at the center of the screen */
+ GUIEngine::LabelWidget* m_label_vs;
+
public:
/** \brief implement callback from parent class GUIEngine::Screen */
@@ -41,6 +44,9 @@ public:
virtual void eventCallback(GUIEngine::Widget* widget, const std::string& name,
const int playerID) OVERRIDE;
+ /** \brief implement callback from parent class GUIEngine::Screen */
+ virtual void beforeAddingWidget() OVERRIDE;
+
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void init() OVERRIDE;
};