1) Added network kart type.
2) Modified menu handling for clients (i.e. skip game mode select etc). 3) Added more (currently mostly empty) network functions. 4) Added missing network manager from previous commit. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2222 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
2f2197308d
commit
78f8c60934
@ -37,7 +37,9 @@
|
||||
#else
|
||||
# define CONFIGDIR ".supertuxkart"
|
||||
#endif
|
||||
#include "plib/ul.h"
|
||||
// ul.h includes windows.h, so this define is necessary
|
||||
#define _WINSOCKAPI_
|
||||
#include <plib/ul.h>
|
||||
#include "file_manager.hpp"
|
||||
#include "world.hpp"
|
||||
#include "btBulletDynamicsCommon.h"
|
||||
|
@ -17,7 +17,7 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include <cstdlib>
|
||||
//#include <cstdlib>
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <OpenGL/gl.h>
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include "material.hpp"
|
||||
#include "unlock_manager.hpp"
|
||||
#include "translation.hpp"
|
||||
#include "network_manager.hpp"
|
||||
|
||||
#if defined(WIN32) && !defined(__CYGWIN__)
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
@ -389,10 +391,16 @@ void CharSel::select()
|
||||
}
|
||||
}
|
||||
|
||||
if (race_manager->getMajorMode() == RaceManager::RM_GRAND_PRIX)
|
||||
menu_manager->pushMenu(MENUID_GRANDPRIXSELECT);
|
||||
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
|
||||
{
|
||||
}
|
||||
else
|
||||
menu_manager->pushMenu(MENUID_TRACKSEL);
|
||||
{
|
||||
if (race_manager->getMajorMode() == RaceManager::RM_GRAND_PRIX)
|
||||
menu_manager->pushMenu(MENUID_GRANDPRIXSELECT);
|
||||
else
|
||||
menu_manager->pushMenu(MENUID_TRACKSEL);
|
||||
}
|
||||
} // select
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "translation.hpp"
|
||||
#include "user_config.hpp"
|
||||
#include "unlock_manager.hpp"
|
||||
#include "network_manager.hpp"
|
||||
|
||||
enum WidgetTokens
|
||||
{
|
||||
@ -48,7 +49,8 @@ MainMenu::MainMenu()
|
||||
widget_manager->addTextButtonWgt( WTOK_MULTI, WIDTH, 7, _("Multiplayer") );
|
||||
|
||||
std::vector<const Challenge*> all_challenges=unlock_manager->getActiveChallenges();
|
||||
if(all_challenges.size()>0)
|
||||
// Only allow challenges if not networking for now!
|
||||
if(all_challenges.size()>0 && network_manager->getMode()==NetworkManager::NW_NONE)
|
||||
{
|
||||
widget_manager->addTextButtonWgt( WTOK_CHALLENGES, WIDTH, 7, _("Challenges") );
|
||||
}
|
||||
@ -88,7 +90,16 @@ void MainMenu::select()
|
||||
{
|
||||
case WTOK_SINGLE:
|
||||
race_manager->setNumPlayers(1);
|
||||
menu_manager->pushMenu(MENUID_GAMEMODE);
|
||||
// The clients do not do any mode selection, they go immediately
|
||||
// to the character selection screen.
|
||||
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
|
||||
{
|
||||
menu_manager->pushMenu(MENUID_CHARSEL_P1);
|
||||
}
|
||||
else
|
||||
{
|
||||
menu_manager->pushMenu(MENUID_GAMEMODE);
|
||||
}
|
||||
break;
|
||||
case WTOK_MULTI:
|
||||
menu_manager->pushMenu(MENUID_NUMPLAYERS);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "widget_manager.hpp"
|
||||
#include "menu_manager.hpp"
|
||||
#include "translation.hpp"
|
||||
#include "network_manager.hpp"
|
||||
|
||||
enum WidgetTokens
|
||||
{
|
||||
@ -63,7 +64,10 @@ void NumPlayers::select()
|
||||
case WTOK_PLAYER_3:
|
||||
case WTOK_PLAYER_4:
|
||||
race_manager->setNumPlayers(widget_manager->getSelectedWgt());
|
||||
menu_manager->pushMenu(MENUID_GAMEMODE);
|
||||
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
|
||||
menu_manager->pushMenu(MENUID_CHARSEL_P1);
|
||||
else
|
||||
menu_manager->pushMenu(MENUID_GAMEMODE);
|
||||
break;
|
||||
case WTOK_QUIT:
|
||||
menu_manager->popMenu();
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "material_manager.hpp"
|
||||
#include "unlock_manager.hpp"
|
||||
#include "translation.hpp"
|
||||
#include "network_manager.hpp"
|
||||
|
||||
#if defined(WIN32) && !defined(__CYGWIN__)
|
||||
# define snprintf _snprintf
|
||||
#endif
|
||||
@ -53,6 +55,16 @@ enum WidgetTokens
|
||||
|
||||
RaceOptions::RaceOptions()
|
||||
{
|
||||
// First update the server's race_manager with the number of players
|
||||
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
|
||||
{
|
||||
network_manager->sendKartsInformationToServer();
|
||||
}
|
||||
else if(network_manager->getMode()==NetworkManager::NW_SERVER)
|
||||
{
|
||||
network_manager->waitForKartsInformation();
|
||||
}
|
||||
|
||||
m_difficulty=race_manager->getDifficulty();
|
||||
// FIXME: no medium AI atm
|
||||
if(m_difficulty==RaceManager::RD_MEDIUM) m_difficulty=RaceManager::RD_HARD;
|
||||
@ -269,6 +281,14 @@ void RaceOptions::select()
|
||||
}
|
||||
|
||||
menu_manager->pushMenu(MENUID_START_RACE_FEEDBACK);
|
||||
if(network_manager->getMode()==NetworkManager::NW_SERVER)
|
||||
{
|
||||
network_manager->sendRaceInformationToClients();
|
||||
}
|
||||
else if(network_manager->getMode()==NetworkManager::NW_CLIENT)
|
||||
{
|
||||
network_manager->waitForRaceInformation();
|
||||
}
|
||||
break;
|
||||
case WTOK_QUIT:
|
||||
menu_manager->popMenu();
|
||||
|
@ -20,6 +20,8 @@
|
||||
#ifndef HEADER_HERRING_H
|
||||
#define HEADER_HERRING_H
|
||||
|
||||
// num_players triggers 'already defined' messages without the WINSOCKAPI define. Don't ask me :(
|
||||
#define _WINSOCKAPI_
|
||||
#include <plib/sg.h>
|
||||
#include "coord.hpp"
|
||||
|
||||
@ -27,7 +29,7 @@ class Kart;
|
||||
class ssgTransform;
|
||||
class ssgEntity;
|
||||
|
||||
// HE_RED ust be the first, HE_SILVER the last entry. See HerringManager
|
||||
// HE_RED must be the first, HE_SILVER the last entry. See HerringManager
|
||||
enum herringType { HE_RED, HE_GREEN, HE_GOLD, HE_SILVER };
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
File diff suppressed because it is too large
Load Diff
17
src/main.cpp
17
src/main.cpp
@ -29,6 +29,7 @@
|
||||
# ifdef __CYGWIN__
|
||||
# include <unistd.h>
|
||||
# endif
|
||||
# define _WINSOCKAPI_
|
||||
# include <windows.h>
|
||||
# ifdef _MSC_VER
|
||||
# include <io.h>
|
||||
@ -125,7 +126,6 @@ void cmdLineHelp (char* invocation)
|
||||
int handleCmdLine(int argc, char **argv)
|
||||
{
|
||||
int n;
|
||||
char s[80];
|
||||
for(int i=1; i<argc; i++)
|
||||
{
|
||||
if(argv[i][0] != '-') continue;
|
||||
@ -172,11 +172,6 @@ int handleCmdLine(int argc, char **argv)
|
||||
{
|
||||
network_manager->setPort(n);
|
||||
}
|
||||
else if( sscanf(argv[i], "--client=%s", s) )
|
||||
{
|
||||
network_manager->setMode(NetworkManager::NW_CLIENT);
|
||||
network_manager->setServerIP(s);
|
||||
}
|
||||
else if( sscanf(argv[i], "--numclients=%d", &n) )
|
||||
{
|
||||
network_manager->setNumClients(n);
|
||||
@ -534,12 +529,10 @@ int main(int argc, char *argv[] )
|
||||
exit(-3);
|
||||
}
|
||||
|
||||
if(!network_manager->initialiseConnections())
|
||||
{
|
||||
fprintf(stderr, "Problems initialising network connections, aborting.\n");
|
||||
exit(-4);
|
||||
}
|
||||
exit(0);
|
||||
if(!network_manager->initialiseConnections())
|
||||
{
|
||||
fprintf(stderr, "Problems initialising network connections, aborting.\n");
|
||||
}
|
||||
|
||||
// Not replaying
|
||||
// =============
|
||||
|
231
src/network_manager.cpp
Normal file
231
src/network_manager.cpp
Normal file
@ -0,0 +1,231 @@
|
||||
// $Id: network_manager.hpp 2128 2008-06-13 00:53:52Z cosmosninja $
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2008 Joerg Henrichs, Stephen Leak
|
||||
//
|
||||
// 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 "network_manager.hpp"
|
||||
#include "stk_config.hpp"
|
||||
|
||||
NetworkManager* network_manager = 0;
|
||||
|
||||
NetworkManager::NetworkManager()
|
||||
{
|
||||
m_mode = NW_NONE;
|
||||
m_state = NS_SYNCHRONISING;
|
||||
m_port = 12345;
|
||||
m_server_address = "172.31.41.53";
|
||||
m_num_clients = 0;
|
||||
#ifdef HAVE_ENET
|
||||
if (enet_initialize () != 0)
|
||||
{
|
||||
fprintf (stderr, "An error occurred while initializing ENet.\n");
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
} // NetworkManager
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
bool NetworkManager::initialiseConnections()
|
||||
{
|
||||
switch(m_mode)
|
||||
{
|
||||
case NW_NONE: return true;
|
||||
case NW_CLIENT: return initClient();
|
||||
case NW_SERVER: return initServer();
|
||||
}
|
||||
return true;
|
||||
} // NetworkManager
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
NetworkManager::~NetworkManager()
|
||||
{
|
||||
#ifdef HAVE_ENET
|
||||
if(m_mode==NW_SERVER || m_mode==NW_CLIENT) enet_host_destroy(m_host);
|
||||
enet_deinitialize();
|
||||
#endif
|
||||
} // ~NetworkManager
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
bool NetworkManager::initServer()
|
||||
{
|
||||
#ifdef HAVE_ENET
|
||||
fprintf(stderr, "Initialising server, listening on %d\n", m_port);
|
||||
|
||||
ENetAddress address;
|
||||
address.host = ENET_HOST_ANY;
|
||||
address.port = m_port;
|
||||
|
||||
m_host = enet_host_create (& address /* the address to bind the server host to */,
|
||||
stk_config->m_max_karts /* number of connections */,
|
||||
0 /* incoming bandwidth */,
|
||||
0 /* outgoing bandwidth */ );
|
||||
if (m_host == NULL)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"An error occurred while trying to create an ENet server host.\n"
|
||||
"Progressing in non-network mode\n");
|
||||
m_mode = NW_NONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Server initialised, waiting for connections ...\n");
|
||||
return true;
|
||||
#endif
|
||||
} // initServer
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
bool NetworkManager::initClient()
|
||||
{
|
||||
fprintf(stderr, "Initialising client\n");
|
||||
#ifdef HAVE_ENET
|
||||
m_host = enet_host_create (NULL /* create a client host */,
|
||||
1 /* only allow 1 outgoing connection */,
|
||||
0 /* downstream bandwidth unlimited */,
|
||||
0 /* upstream bandwidth unlimited */ );
|
||||
|
||||
if (m_host == NULL)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"An error occurred while trying to create an ENet client host.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ENetAddress address;
|
||||
ENetEvent event;
|
||||
ENetPeer *peer;
|
||||
|
||||
enet_address_set_host (& address, m_server_address.c_str());
|
||||
address.port = m_port;
|
||||
|
||||
/* Initiate the connection, allocating the two channels 0 and 1. */
|
||||
peer = enet_host_connect (m_host, &address, 2);
|
||||
|
||||
if (peer == NULL)
|
||||
{
|
||||
fprintf (stderr,
|
||||
"No available peers for initiating an ENet connection.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Wait up to 5 seconds for the connection attempt to succeed. */
|
||||
if (enet_host_service (m_host, & event, 5000) > 0 &&
|
||||
event.type == ENET_EVENT_TYPE_CONNECT)
|
||||
{
|
||||
fprintf(stderr, "Connection to %s:%d succeeded.",
|
||||
m_server_address.c_str(), m_port);
|
||||
enet_host_service(m_host, &event, 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Either the 5 seconds are up or a disconnect event was */
|
||||
/* received. Reset the peer in the event the 5 seconds */
|
||||
/* had run out without any significant event. */
|
||||
enet_peer_reset (peer);
|
||||
|
||||
fprintf(stderr, "Connection to '%s:%d' failed.",
|
||||
m_server_address.c_str(), m_port);
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif
|
||||
} // initServer
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void NetworkManager::handleNewConnection(ENetEvent *event)
|
||||
{
|
||||
if(m_state!=NS_SYNCHRONISING)
|
||||
{
|
||||
// We don't accept connections atm
|
||||
return;
|
||||
}
|
||||
m_num_clients++;
|
||||
fprintf (stderr, "A new client connected from %x:%u. Connected: %d.\n",
|
||||
event->peer -> address.host,
|
||||
event->peer -> address.port, m_num_clients);
|
||||
|
||||
} // handleNewConnection
|
||||
// ----------------------------------------------------------------------------
|
||||
void NetworkManager::handleDisconnection(ENetEvent *event)
|
||||
{
|
||||
if(m_state!=NS_SYNCHRONISING)
|
||||
{
|
||||
fprintf(stderr, "Disconnect while in race - close your eyes and hope for the best.\n");
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "%x:%d disconected.\n", event->peer->address.host,
|
||||
event->peer->address.port );
|
||||
m_num_clients--;
|
||||
} // handleDisconnection
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void NetworkManager::handleNewMessage(ENetEvent *event)
|
||||
{
|
||||
if(m_state==NS_SYNCHRONISING)
|
||||
{
|
||||
fprintf(stderr, "Received a receive event while waiting for client - ignored.\n");
|
||||
return;
|
||||
}
|
||||
} // handleNewMessage
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void NetworkManager::update(float dt)
|
||||
{
|
||||
ENetEvent event;
|
||||
int result = enet_host_service (m_host, &event, 1);
|
||||
if(result==0) return;
|
||||
if(result<0)
|
||||
{
|
||||
fprintf(stderr, "Error while receiving messages -> ignored.\n");
|
||||
return;
|
||||
}
|
||||
switch (event.type)
|
||||
{
|
||||
case ENET_EVENT_TYPE_CONNECT: handleNewConnection(&event); break;
|
||||
case ENET_EVENT_TYPE_RECEIVE: handleNewMessage(&event); break;
|
||||
case ENET_EVENT_TYPE_DISCONNECT: handleDisconnection(&event); break;
|
||||
case ENET_EVENT_TYPE_NONE: break;
|
||||
}
|
||||
} // update
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Send race_manager->getNumPlayers(), the kart and the name of each
|
||||
player to the server.
|
||||
*/
|
||||
void NetworkManager::sendKartsInformationToServer()
|
||||
{
|
||||
} // sendKartsInformationToServer
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Receive and store the information from sendKartsInformation()
|
||||
*/
|
||||
void NetworkManager::waitForKartsInformation()
|
||||
{
|
||||
} // waitForKartsInformation
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Sends the information from the race_manager to all clients.
|
||||
*/
|
||||
void NetworkManager::sendRaceInformationToClients()
|
||||
{
|
||||
} // sendRaceInformationToClients
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Receives and sets the race_manager information.
|
||||
*/
|
||||
void NetworkManager::waitForRaceInformation()
|
||||
{
|
||||
} // waitForRaceInformation
|
||||
// ----------------------------------------------------------------------------
|
76
src/network_manager.hpp
Normal file
76
src/network_manager.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
// $Id: network_manager.hpp 2128 2008-06-13 00:53:52Z cosmosninja $
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2008 Joerg Henrichs, Stephen Leak
|
||||
//
|
||||
// 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 HEADER_NETWORK_MANAGER_H
|
||||
#define HEADER_NETWORK_MANAGER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef HAVE_ENET
|
||||
# include "enet/enet.h"
|
||||
#endif
|
||||
|
||||
class NetworkManager
|
||||
{
|
||||
public:
|
||||
// The mode the network manager is operating in
|
||||
enum NetworkMode {NW_SERVER, NW_CLIENT, NW_NONE};
|
||||
|
||||
// The current state.
|
||||
enum NetworkState {NS_SYNCHRONISING, NS_RACING};
|
||||
private:
|
||||
NetworkMode m_mode;
|
||||
NetworkState m_state;
|
||||
int m_port;
|
||||
std::string m_server_address;
|
||||
int m_num_clients;
|
||||
#ifdef HAVE_ENET
|
||||
ENetHost *m_host;
|
||||
#endif
|
||||
|
||||
bool initServer();
|
||||
bool initClient();
|
||||
void handleNewConnection(ENetEvent *event);
|
||||
void handleNewMessage (ENetEvent *event);
|
||||
void handleDisconnection(ENetEvent *event);
|
||||
|
||||
|
||||
public:
|
||||
NetworkManager();
|
||||
~NetworkManager();
|
||||
void setMode(NetworkMode m) {m_mode = m; }
|
||||
NetworkMode getMode() const {return m_mode; }
|
||||
void setState(NetworkState s) {m_state = s; }
|
||||
NetworkState getState() const {return m_state; }
|
||||
void setNumClients(int n) {m_num_clients = n; }
|
||||
int getNumClients() const {return m_num_clients;}
|
||||
void setPort(int p) {m_port=p; }
|
||||
void setServerIP(const std::string &s) {m_server_address=s; }
|
||||
bool initialiseConnections();
|
||||
void update(float dt);
|
||||
void sendKartsInformationToServer();
|
||||
void waitForKartsInformation();
|
||||
void sendRaceInformationToClients();
|
||||
void waitForRaceInformation();
|
||||
};
|
||||
|
||||
extern NetworkManager *network_manager;
|
||||
|
||||
#endif
|
||||
|
@ -161,13 +161,13 @@ void PlayerKart::update(float dt)
|
||||
m_penalty_time=1.0;
|
||||
// A warning gets displayed in RaceGUI
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
// The call to update is necessary here (even though the kart
|
||||
// The call to update is necessary here (even though the kart
|
||||
// shouldn't actually change) to update m_transform. Otherwise
|
||||
// the camera gets the wrong position.
|
||||
Kart::update(dt);
|
||||
}
|
||||
// the camera gets the wrong position.
|
||||
Kart::update(dt);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1,274 +1,276 @@
|
||||
// $Id$
|
||||
//
|
||||
// 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 <iostream>
|
||||
|
||||
#include "track_manager.hpp"
|
||||
#include "game_manager.hpp"
|
||||
#include "kart_properties_manager.hpp"
|
||||
#include "race_manager.hpp"
|
||||
#include "unlock_manager.hpp"
|
||||
#include "gui/menu_manager.hpp"
|
||||
#include "world.hpp"
|
||||
#include "scene.hpp"
|
||||
#include "user_config.hpp"
|
||||
#include "stk_config.hpp"
|
||||
|
||||
|
||||
RaceManager* race_manager= NULL;
|
||||
|
||||
RaceManager::RaceManager()
|
||||
{
|
||||
m_num_karts = user_config->m_karts;
|
||||
m_difficulty = RD_HARD;
|
||||
m_major_mode = RM_SINGLE;
|
||||
m_minor_mode = RM_QUICK_RACE;
|
||||
m_track_number = 0;
|
||||
m_active_race = false;
|
||||
m_score_for_position = stk_config->m_scores;
|
||||
m_coin_target = 0;
|
||||
setTrack("race");
|
||||
setPlayerKart(0, "tuxkart");
|
||||
} // RaceManager
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
RaceManager::~RaceManager()
|
||||
{
|
||||
} // ~RaceManager
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::reset()
|
||||
{
|
||||
m_num_finished_karts = 0;
|
||||
m_num_finished_players = 0;
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::setPlayerKart(unsigned int player, const std::string& kart)
|
||||
{
|
||||
if (player >= 0 && player < 4)
|
||||
{
|
||||
if (player >= getNumPlayers())
|
||||
setNumPlayers(player+1);
|
||||
m_player_karts[player] = kart;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Warning: player '%d' does not exists.\n", player);
|
||||
}
|
||||
} // setPlayerKart
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::setNumPlayers(int num)
|
||||
{
|
||||
m_player_karts.resize(num);
|
||||
for(PlayerKarts::iterator i = m_player_karts.begin(); i != m_player_karts.end(); ++i)
|
||||
{
|
||||
if (i->empty())
|
||||
{
|
||||
*i = "tuxkart";
|
||||
}
|
||||
}
|
||||
} // setNumPlayers
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::setDifficulty(Difficulty diff)
|
||||
{
|
||||
if(diff==RD_SKIDDING)
|
||||
{
|
||||
m_difficulty = RD_HARD;
|
||||
user_config->m_skidding = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_difficulty = diff;
|
||||
user_config->m_skidding = false;
|
||||
}
|
||||
} // setDifficulty
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::setTrack(const std::string& track)
|
||||
{
|
||||
m_tracks.clear();
|
||||
m_tracks.push_back(track);
|
||||
} // setTrack
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::startNew()
|
||||
{
|
||||
if(m_major_mode==RM_GRAND_PRIX) // GP: get tracks and laps from grand prix
|
||||
{
|
||||
m_tracks = m_grand_prix.getTracks();
|
||||
m_num_laps = m_grand_prix.getLaps();
|
||||
}
|
||||
assert(m_player_karts.size() > 0);
|
||||
|
||||
// command line parameters: negative numbers=all karts
|
||||
if(m_num_karts < 0 ) m_num_karts = stk_config->m_max_karts;
|
||||
if((size_t)m_num_karts < m_player_karts.size())
|
||||
m_num_karts = (int)m_player_karts.size();
|
||||
|
||||
// Create the list of all kart names to use
|
||||
// ========================================
|
||||
std::vector<std::string> kart_names;
|
||||
kart_names.resize(m_num_karts);
|
||||
for(unsigned int i = 0; i < m_player_karts.size(); i++)
|
||||
{
|
||||
/*Players position is behind the AI in the first race*/
|
||||
kart_names[m_num_karts-1 - i] = m_player_karts[m_player_karts.size() - 1 - i];
|
||||
}
|
||||
kart_properties_manager->fillWithRandomKarts(kart_names);
|
||||
|
||||
// Create the kart status data structure to keep track of scores, times, ...
|
||||
// ==========================================================================
|
||||
const int num_ai_karts = m_num_karts - (int)m_player_karts.size();
|
||||
m_kart_status.clear();
|
||||
for(int i=0; i<m_num_karts; i++)
|
||||
{
|
||||
// AI karts have -1 as player
|
||||
bool is_player = i>=num_ai_karts; // players start at the back
|
||||
m_kart_status.push_back(KartStatus(kart_names[i], i,
|
||||
is_player ? i-num_ai_karts : -1 ) );
|
||||
} // for i<m_num_karts
|
||||
|
||||
// Then start the race with the first track
|
||||
// ========================================
|
||||
m_track_number = 0;
|
||||
startNextRace();
|
||||
} // startNew
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::startNextRace()
|
||||
{
|
||||
|
||||
m_num_finished_karts = 0;
|
||||
m_num_finished_players = 0;
|
||||
|
||||
// if subsequent race, sort kart status structure
|
||||
// ==============================================
|
||||
if (m_track_number > 0)
|
||||
{
|
||||
// In follow the leader mode do not change the first kart,
|
||||
// since it's always the leader.
|
||||
int offset = (m_minor_mode==RM_FOLLOW_LEADER) ? 1 : 0;
|
||||
|
||||
std::sort(m_kart_status.begin()+offset, m_kart_status.end());
|
||||
//reverse kart order if flagged in stk_config
|
||||
if (stk_config->m_grid_order)
|
||||
{
|
||||
std::reverse(m_kart_status.begin()+offset, m_kart_status.end());
|
||||
}
|
||||
} // not first race
|
||||
|
||||
// the constructor assigns this object to the global
|
||||
// variable world. Admittedly a bit ugly, but simplifies
|
||||
// handling of objects which get created in the constructor
|
||||
// and need world to be defined.
|
||||
new World();
|
||||
|
||||
m_active_race = true;
|
||||
} // startNextRace
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::next()
|
||||
{
|
||||
m_num_finished_karts = 0;
|
||||
m_num_finished_players = 0;
|
||||
m_track_number++;
|
||||
if(m_track_number<(int)m_tracks.size())
|
||||
{
|
||||
scene->clear();
|
||||
startNextRace();
|
||||
}
|
||||
else
|
||||
{
|
||||
exit_race();
|
||||
}
|
||||
} // next
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::exit_race()
|
||||
{
|
||||
// Only display the grand prix result screen if all tracks
|
||||
// were finished, and not when a race is aborted.
|
||||
if(m_major_mode==RM_GRAND_PRIX && m_track_number==(int)m_tracks.size())
|
||||
{
|
||||
unlock_manager->grandPrixFinished();
|
||||
menu_manager->switchToGrandPrixEnding();
|
||||
}
|
||||
else
|
||||
{
|
||||
menu_manager->switchToMainMenu();
|
||||
}
|
||||
scene->clear();
|
||||
delete world;
|
||||
world = 0;
|
||||
m_track_number = 0;
|
||||
m_active_race = false;
|
||||
} // exit_Race
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Kart kart has finished the race at the specified time (which can be different
|
||||
// from world->getClock() in case of setting extrapolated arrival times).
|
||||
void RaceManager::RaceFinished(const Kart *kart, float time)
|
||||
{
|
||||
unsigned i;
|
||||
for(i=0; i<m_kart_status.size(); i++)
|
||||
{
|
||||
if(kart->getIdent()==m_kart_status[i].m_ident) break;
|
||||
} // for i
|
||||
if(i>=m_kart_status.size())
|
||||
{
|
||||
fprintf(stderr, "Kart '%s' not found. Ignored.\n",kart->getName().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// In follow the leader mode, kart 0 does not get any points,
|
||||
// so the position of each kart is actually one better --> decrease pos
|
||||
int pos = kart->getPosition();
|
||||
if(m_minor_mode==RM_FOLLOW_LEADER)
|
||||
{
|
||||
pos--;
|
||||
// If the position is negative (i.e. follow leader and kart on
|
||||
// position 0) set the score of this kart to the lowest possible
|
||||
// score, since the kart is ahead of the leader
|
||||
if(pos<=0) pos=stk_config->m_max_karts;
|
||||
}
|
||||
|
||||
m_kart_status[i].m_score += m_score_for_position[pos-1];
|
||||
m_kart_status[i].m_last_score = m_score_for_position[pos-1];
|
||||
m_kart_status[i].m_overall_time += time;
|
||||
m_kart_status[i].m_last_time = time;
|
||||
m_num_finished_karts ++;
|
||||
if(kart->isPlayerKart()) m_num_finished_players++;
|
||||
} // raceFinished
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::rerunRace()
|
||||
{
|
||||
// Subtract last score from all karts:
|
||||
for(int i=0; i<m_num_karts; i++)
|
||||
{
|
||||
m_kart_status[i].m_score -= m_kart_status[i].m_last_score;
|
||||
m_kart_status[i].m_overall_time -= m_kart_status[i].m_last_time;
|
||||
}
|
||||
world->restartRace();
|
||||
} // rerunRace
|
||||
|
||||
/* EOF */
|
||||
// $Id$
|
||||
//
|
||||
// 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 <iostream>
|
||||
|
||||
#include "track_manager.hpp"
|
||||
#include "game_manager.hpp"
|
||||
#include "kart_properties_manager.hpp"
|
||||
#include "race_manager.hpp"
|
||||
#include "unlock_manager.hpp"
|
||||
#include "gui/menu_manager.hpp"
|
||||
#include "world.hpp"
|
||||
#include "scene.hpp"
|
||||
#include "user_config.hpp"
|
||||
#include "stk_config.hpp"
|
||||
|
||||
|
||||
RaceManager* race_manager= NULL;
|
||||
|
||||
RaceManager::RaceManager()
|
||||
{
|
||||
m_num_karts = user_config->m_karts;
|
||||
m_difficulty = RD_HARD;
|
||||
m_major_mode = RM_SINGLE;
|
||||
m_minor_mode = RM_QUICK_RACE;
|
||||
m_track_number = 0;
|
||||
m_active_race = false;
|
||||
m_score_for_position = stk_config->m_scores;
|
||||
m_coin_target = 0;
|
||||
setTrack("race");
|
||||
setPlayerKart(0, "tuxkart");
|
||||
} // RaceManager
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
RaceManager::~RaceManager()
|
||||
{
|
||||
} // ~RaceManager
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::reset()
|
||||
{
|
||||
m_num_finished_karts = 0;
|
||||
m_num_finished_players = 0;
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::setPlayerKart(unsigned int player, const std::string& kart)
|
||||
{
|
||||
if (player >= 0 && player < 4)
|
||||
{
|
||||
if (player >= getNumPlayers())
|
||||
setNumPlayers(player+1);
|
||||
m_player_karts[player] = kart;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Warning: player '%d' does not exists.\n", player);
|
||||
}
|
||||
} // setPlayerKart
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::setNumPlayers(int num)
|
||||
{
|
||||
m_player_karts.resize(num);
|
||||
for(PlayerKarts::iterator i = m_player_karts.begin(); i != m_player_karts.end(); ++i)
|
||||
{
|
||||
if (i->empty())
|
||||
{
|
||||
*i = "tuxkart";
|
||||
}
|
||||
}
|
||||
} // setNumPlayers
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::setDifficulty(Difficulty diff)
|
||||
{
|
||||
if(diff==RD_SKIDDING)
|
||||
{
|
||||
m_difficulty = RD_HARD;
|
||||
user_config->m_skidding = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_difficulty = diff;
|
||||
user_config->m_skidding = false;
|
||||
}
|
||||
} // setDifficulty
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::setTrack(const std::string& track)
|
||||
{
|
||||
m_tracks.clear();
|
||||
m_tracks.push_back(track);
|
||||
} // setTrack
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::startNew()
|
||||
{
|
||||
if(m_major_mode==RM_GRAND_PRIX) // GP: get tracks and laps from grand prix
|
||||
{
|
||||
m_tracks = m_grand_prix.getTracks();
|
||||
m_num_laps = m_grand_prix.getLaps();
|
||||
}
|
||||
assert(m_player_karts.size() > 0);
|
||||
|
||||
// command line parameters: negative numbers=all karts
|
||||
if(m_num_karts < 0 ) m_num_karts = stk_config->m_max_karts;
|
||||
if((size_t)m_num_karts < m_player_karts.size())
|
||||
m_num_karts = (int)m_player_karts.size();
|
||||
|
||||
// Create the list of all kart names to use
|
||||
// ========================================
|
||||
std::vector<std::string> kart_names;
|
||||
kart_names.resize(m_num_karts);
|
||||
for(unsigned int i = 0; i < m_player_karts.size(); i++)
|
||||
{
|
||||
/*Players position is behind the AI in the first race*/
|
||||
kart_names[m_num_karts-1 - i] = m_player_karts[m_player_karts.size() - 1 - i];
|
||||
}
|
||||
kart_properties_manager->fillWithRandomKarts(kart_names);
|
||||
|
||||
// Create the kart status data structure to keep track of scores, times, ...
|
||||
// ==========================================================================
|
||||
const int num_ai_karts = m_num_karts - (int)m_player_karts.size();
|
||||
m_kart_status.clear();
|
||||
for(int i=0; i<m_num_karts; i++)
|
||||
{
|
||||
// AI karts have -1 as player
|
||||
bool is_player = i>=num_ai_karts; // players start at the back
|
||||
m_kart_status.push_back(KartStatus(kart_names[i], i,
|
||||
is_player ? i-num_ai_karts : -1,
|
||||
is_player ? KT_PLAYER: KT_AI
|
||||
) );
|
||||
} // for i<m_num_karts
|
||||
|
||||
// Then start the race with the first track
|
||||
// ========================================
|
||||
m_track_number = 0;
|
||||
startNextRace();
|
||||
} // startNew
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::startNextRace()
|
||||
{
|
||||
|
||||
m_num_finished_karts = 0;
|
||||
m_num_finished_players = 0;
|
||||
|
||||
// if subsequent race, sort kart status structure
|
||||
// ==============================================
|
||||
if (m_track_number > 0)
|
||||
{
|
||||
// In follow the leader mode do not change the first kart,
|
||||
// since it's always the leader.
|
||||
int offset = (m_minor_mode==RM_FOLLOW_LEADER) ? 1 : 0;
|
||||
|
||||
std::sort(m_kart_status.begin()+offset, m_kart_status.end());
|
||||
//reverse kart order if flagged in stk_config
|
||||
if (stk_config->m_grid_order)
|
||||
{
|
||||
std::reverse(m_kart_status.begin()+offset, m_kart_status.end());
|
||||
}
|
||||
} // not first race
|
||||
|
||||
// the constructor assigns this object to the global
|
||||
// variable world. Admittedly a bit ugly, but simplifies
|
||||
// handling of objects which get created in the constructor
|
||||
// and need world to be defined.
|
||||
new World();
|
||||
|
||||
m_active_race = true;
|
||||
} // startNextRace
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::next()
|
||||
{
|
||||
m_num_finished_karts = 0;
|
||||
m_num_finished_players = 0;
|
||||
m_track_number++;
|
||||
if(m_track_number<(int)m_tracks.size())
|
||||
{
|
||||
scene->clear();
|
||||
startNextRace();
|
||||
}
|
||||
else
|
||||
{
|
||||
exit_race();
|
||||
}
|
||||
} // next
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::exit_race()
|
||||
{
|
||||
// Only display the grand prix result screen if all tracks
|
||||
// were finished, and not when a race is aborted.
|
||||
if(m_major_mode==RM_GRAND_PRIX && m_track_number==(int)m_tracks.size())
|
||||
{
|
||||
unlock_manager->grandPrixFinished();
|
||||
menu_manager->switchToGrandPrixEnding();
|
||||
}
|
||||
else
|
||||
{
|
||||
menu_manager->switchToMainMenu();
|
||||
}
|
||||
scene->clear();
|
||||
delete world;
|
||||
world = 0;
|
||||
m_track_number = 0;
|
||||
m_active_race = false;
|
||||
} // exit_Race
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Kart kart has finished the race at the specified time (which can be different
|
||||
// from world->getClock() in case of setting extrapolated arrival times).
|
||||
void RaceManager::RaceFinished(const Kart *kart, float time)
|
||||
{
|
||||
unsigned i;
|
||||
for(i=0; i<m_kart_status.size(); i++)
|
||||
{
|
||||
if(kart->getIdent()==m_kart_status[i].m_ident) break;
|
||||
} // for i
|
||||
if(i>=m_kart_status.size())
|
||||
{
|
||||
fprintf(stderr, "Kart '%s' not found. Ignored.\n",kart->getName().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// In follow the leader mode, kart 0 does not get any points,
|
||||
// so the position of each kart is actually one better --> decrease pos
|
||||
int pos = kart->getPosition();
|
||||
if(m_minor_mode==RM_FOLLOW_LEADER)
|
||||
{
|
||||
pos--;
|
||||
// If the position is negative (i.e. follow leader and kart on
|
||||
// position 0) set the score of this kart to the lowest possible
|
||||
// score, since the kart is ahead of the leader
|
||||
if(pos<=0) pos=stk_config->m_max_karts;
|
||||
}
|
||||
|
||||
m_kart_status[i].m_score += m_score_for_position[pos-1];
|
||||
m_kart_status[i].m_last_score = m_score_for_position[pos-1];
|
||||
m_kart_status[i].m_overall_time += time;
|
||||
m_kart_status[i].m_last_time = time;
|
||||
m_num_finished_karts ++;
|
||||
if(kart->isPlayerKart()) m_num_finished_players++;
|
||||
} // raceFinished
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceManager::rerunRace()
|
||||
{
|
||||
// Subtract last score from all karts:
|
||||
for(int i=0; i<m_num_karts; i++)
|
||||
{
|
||||
m_kart_status[i].m_score -= m_kart_status[i].m_last_score;
|
||||
m_kart_status[i].m_overall_time -= m_kart_status[i].m_last_time;
|
||||
}
|
||||
world->restartRace();
|
||||
} // rerunRace
|
||||
|
||||
/* EOF */
|
||||
|
@ -22,8 +22,8 @@
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "grand_prix_data.hpp"
|
||||
|
||||
/** The race manager has two functions:
|
||||
@ -49,7 +49,7 @@ public:
|
||||
enum RaceModeType { RM_GRAND_PRIX, RM_SINGLE, // The two current major modes
|
||||
RM_QUICK_RACE, RM_TIME_TRIAL, RM_FOLLOW_LEADER };
|
||||
enum Difficulty { RD_EASY, RD_MEDIUM, RD_HARD, RD_SKIDDING };
|
||||
|
||||
enum KartType { KT_PLAYER, KT_NETWORK_PLAYER, KT_AI, KT_LEADER, KT_GHOST };
|
||||
private:
|
||||
struct KartStatus
|
||||
{
|
||||
@ -59,13 +59,15 @@ private:
|
||||
double m_overall_time; // sum of times of all races
|
||||
double m_last_time; // needed for restart
|
||||
int m_prev_finish_pos; // previous finished position
|
||||
KartType m_kart_type; // Kart type: AI, player, network player etc.
|
||||
int m_player_id; // player controling the kart, for AI: -1
|
||||
|
||||
KartStatus(const std::string& ident, const int& prev_finish_pos,
|
||||
const int& player_id) :
|
||||
const int& player_id, KartType kt) :
|
||||
m_ident(ident), m_score(0), m_last_score(0),
|
||||
m_overall_time(0.0f), m_last_time(0.0f),
|
||||
m_prev_finish_pos(prev_finish_pos), m_player_id(player_id)
|
||||
m_prev_finish_pos(prev_finish_pos), m_kart_type(kt),
|
||||
m_player_id(player_id)
|
||||
{}
|
||||
|
||||
}; // KartStatus
|
||||
@ -139,7 +141,7 @@ public:
|
||||
int allPlayerFinished() const {return
|
||||
m_num_finished_players==m_player_karts.size(); }
|
||||
int raceIsActive() const { return m_active_race; }
|
||||
bool isPlayer(int kart) const {return m_kart_status[kart].m_player_id>-1; }
|
||||
KartType getKartType(int kart) const {return m_kart_status[kart].m_kart_type; }
|
||||
|
||||
void setMirror() {/*FIXME*/}
|
||||
void setReverse(){/*FIXME*/}
|
||||
|
@ -117,16 +117,21 @@ World::World()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (race_manager->isPlayer(i))
|
||||
switch(race_manager->getKartType(i))
|
||||
{
|
||||
case RaceManager::KT_PLAYER:
|
||||
newkart = new PlayerKart(kart_name, position,
|
||||
&(user_config->m_player[player_id]),
|
||||
init_pos, player_id);
|
||||
m_player_karts[player_id] = (PlayerKart*)newkart;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
case RaceManager::KT_NETWORK_PLAYER:
|
||||
break;
|
||||
case RaceManager::KT_AI:
|
||||
newkart = loadRobot(kart_name, position, init_pos);
|
||||
break;
|
||||
case RaceManager::KT_GHOST:
|
||||
break;
|
||||
}
|
||||
} // if !user_config->m_profile
|
||||
if(user_config->m_replay_history)
|
||||
|
Loading…
Reference in New Issue
Block a user