First iteration of battle mode! It's playable, and the rack selection works. Warning, if you select AI players it won't work. Lives are shown but don't decrease with hits yet.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2339 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria 2008-10-14 20:20:54 +00:00
parent bac6c98e9f
commit ed2f52bee6
17 changed files with 370 additions and 62 deletions

View File

@ -149,6 +149,7 @@ supertuxkart_SOURCES = main.cpp \
modes/clock.cpp modes/clock.hpp \
modes/world.cpp modes/world.hpp \
modes/linear_world.cpp modes/linear_world.hpp \
modes/three_strikes_battle.cpp modes/three_strikes_battle.hpp \
replay_buffer_tpl.hpp \
replay_buffers.hpp replay_buffers.cpp \
replay_base.hpp replay_base.cpp \

View File

@ -32,6 +32,7 @@ enum WidgetTokens
WTOK_QUICK_RACE_SINGLE,
WTOK_TIMETRIAL_SINGLE,
WTOK_FOLLOW_LEADER_SINGLE,
WTOK_3_STRIKES_SINGLE,
WTOK_TITLE_GP,
WTOK_QUICK_RACE_GP,
@ -47,51 +48,63 @@ GameMode::GameMode()
const int HEIGHT = 7;
const int WIDTH = 5;
const WidgetDirection column_1_dir = WGT_DIR_FROM_LEFT;
const float column_1_loc = 0.1f;
const WidgetDirection column_2_dir = WGT_DIR_FROM_RIGHT;
const float column_2_loc = 0.1f;
// First the single race events
// ============================
Widget *w=widget_manager->addTextWgt(WTOK_TITLE_SINGLE, WIDTH,
HEIGHT, _("Single Race"));
widget_manager->hideWgtRect(WTOK_TITLE_SINGLE);
w->setPosition(WGT_DIR_FROM_LEFT, 0.1f, NULL,
w->setPosition(column_1_dir, column_1_loc, NULL,
WGT_DIR_FROM_TOP, 0.2f, NULL);
Widget *w_prev=w;
w=widget_manager->addTextButtonWgt(WTOK_QUICK_RACE_SINGLE, WIDTH, HEIGHT,
_("Quick Race"));
w->setPosition(WGT_DIR_FROM_LEFT, 0.1f, NULL,
w->setPosition(column_1_dir, column_1_loc, NULL,
WGT_DIR_UNDER_WIDGET, 0.0f, w_prev);
w_prev=w;
w=widget_manager->addTextButtonWgt(WTOK_TIMETRIAL_SINGLE, WIDTH, HEIGHT,
_("Time Trial"));
w->setPosition(WGT_DIR_FROM_LEFT, 0.1f, NULL,
w->setPosition(column_1_dir, column_1_loc, NULL,
WGT_DIR_UNDER_WIDGET, 0.0f, w_prev);
w_prev=w;
w=widget_manager->addTextButtonWgt(WTOK_FOLLOW_LEADER_SINGLE, WIDTH, HEIGHT,
_("Follow the Leader"));
w->setPosition(WGT_DIR_FROM_LEFT, 0.1f, NULL,
w->setPosition(column_1_dir, column_1_loc, NULL,
WGT_DIR_UNDER_WIDGET, 0.0f, w_prev);
widget_manager->sameWidth(WTOK_TITLE_SINGLE, WTOK_FOLLOW_LEADER_SINGLE);
w_prev=w;
w=widget_manager->addTextButtonWgt(WTOK_3_STRIKES_SINGLE, WIDTH, HEIGHT,
_("3 Strikes Battle"));
w->setPosition(column_1_dir, column_1_loc, NULL,
WGT_DIR_UNDER_WIDGET, 0.0f, w_prev);
w_prev=w;
widget_manager->sameWidth(WTOK_TITLE_SINGLE, WTOK_3_STRIKES_SINGLE);
// Then the GPs
// ============
w=widget_manager->addTextWgt(WTOK_TITLE_GP, WIDTH,
HEIGHT, _("Grand Prix"));
widget_manager->hideWgtRect(WTOK_TITLE_GP);
w->setPosition(WGT_DIR_FROM_RIGHT, 0.1f, NULL,
w->setPosition(column_2_dir, column_2_loc, NULL,
WGT_DIR_FROM_TOP, 0.2f, NULL);
w_prev=w;
w=widget_manager->addTextButtonWgt(WTOK_QUICK_RACE_GP, WIDTH, HEIGHT,
_("Quick Race"));
w->setPosition(WGT_DIR_FROM_RIGHT, 0.1f, NULL,
w->setPosition(column_2_dir, column_2_loc, NULL,
WGT_DIR_UNDER_WIDGET, 0.0f, w_prev);
w_prev=w;
w=widget_manager->addTextButtonWgt(WTOK_TIMETRIAL_GP, WIDTH, HEIGHT,
_("Time Trial"));
w->setPosition(WGT_DIR_FROM_RIGHT, 0.1f, NULL,
w->setPosition(column_2_dir, column_2_loc, NULL,
WGT_DIR_UNDER_WIDGET, 0.0f, w_prev);
w_prev=w;
w=widget_manager->addTextButtonWgt(WTOK_FOLLOW_LEADER_GP, WIDTH, HEIGHT,
_("Follow the Leader"));
w->setPosition(WGT_DIR_FROM_RIGHT, 0.1f, NULL,
w->setPosition(column_2_dir, column_2_loc, NULL,
WGT_DIR_UNDER_WIDGET, 0.0f, w_prev);
w_prev=w;
widget_manager->sameWidth(WTOK_TITLE_GP, WTOK_FOLLOW_LEADER_GP);
@ -125,11 +138,14 @@ GameMode::GameMode()
// _("Fulfil challenge to unlock"));
}
// help
w=widget_manager->addTextButtonWgt( WTOK_HELP, WIDTH, HEIGHT, _("Game mode help"));
widget_manager->setWgtTextSize( WTOK_HELP, WGT_FNT_SML );
w->setPosition(WGT_DIR_CENTER, 0.0f, NULL, WGT_DIR_UNDER_WIDGET, 0.1f, w_prev);
w_prev=w;
// return button
w=widget_manager->addTextButtonWgt(WTOK_QUIT, WIDTH, HEIGHT, _("Press <ESC> to go back"));
widget_manager->setWgtTextSize( WTOK_QUIT, WGT_FNT_SML );
w->setPosition(WGT_DIR_CENTER, 0.0f, NULL, WGT_DIR_FROM_BOTTOM, 0.0f, w_prev);
@ -161,6 +177,10 @@ void GameMode::select()
race_manager->setMajorMode(RaceManager::MAJOR_MODE_SINGLE);
race_manager->setMinorMode(RaceManager::MINOR_MODE_FOLLOW_LEADER);
break;
case WTOK_3_STRIKES_SINGLE:
race_manager->setMajorMode(RaceManager::MAJOR_MODE_SINGLE);
race_manager->setMinorMode(RaceManager::MINOR_MODE_3_STRIKES);
break;
case WTOK_QUICK_RACE_GP:
race_manager->setMajorMode(RaceManager::MAJOR_MODE_GRAND_PRIX);
race_manager->setMinorMode(RaceManager::MINOR_MODE_QUICK_RACE);

View File

@ -279,6 +279,9 @@ void RaceGUI::drawTimer ()
void RaceGUI::drawMap ()
{
// arenas currently don't have a map.
if(RaceManager::getTrack()->isArena()) return;
glDisable ( GL_TEXTURE_2D ) ;
assert(RaceManager::getWorld() != NULL);
int xLeft = 10;
@ -338,9 +341,9 @@ void RaceGUI::drawPlayerIcons (const KartIconDisplayInfo* info)
{
Kart* kart = RaceManager::getKart(i);
if(kart->isEliminated()) continue;
int position = kart->getPosition();
const int position = kart->getPosition();
y = user_config->m_height*3/4-20 - ((position-1)*(ICON_PLAYER_WIDHT+2));
y = user_config->m_height*3/4-20 - ( (position == -1 ? i : position-1)*(ICON_PLAYER_WIDHT+2));
GLfloat COLOR[] = {info[i].r, info[i].g, info[i].b, 1.0f};
font_race->PrintShadow(info[i].time.c_str(), 30, ICON_PLAYER_WIDHT+x, y+5, COLOR);
@ -390,19 +393,21 @@ void RaceGUI::drawPlayerIcons (const KartIconDisplayInfo* info)
glDisable(GL_CULL_FACE);
char str[256];
sprintf(str, "%d", kart->getPosition());
font_race->PrintShadow(str, 33, x-7, y-4);
// FIXME: translation
if (kart->getPosition() == 1)
font_race->PrintShadow("st", 13, x-7+17, y-4+17);
else if (kart->getPosition() == 2)
font_race->PrintShadow("nd", 13, x-7+17, y-4+17);
else if (kart->getPosition() == 3)
font_race->PrintShadow("rd", 13, x-7+17, y-4+17);
else
font_race->PrintShadow("th", 13, x-7+17, y-4+17);
if(position != -1)
{
sprintf(str, "%d", position);
font_race->PrintShadow(str, 33, x-7, y-4);
// FIXME: translation
if (kart->getPosition() == 1)
font_race->PrintShadow("st", 13, x-7+17, y-4+17);
else if (kart->getPosition() == 2)
font_race->PrintShadow("nd", 13, x-7+17, y-4+17);
else if (kart->getPosition() == 3)
font_race->PrintShadow("rd", 13, x-7+17, y-4+17);
else
font_race->PrintShadow("th", 13, x-7+17, y-4+17);
}
} // next kart
glEnable(GL_CULL_FACE);
@ -633,6 +638,10 @@ void RaceGUI::drawSteering(Kart* kart, int offset_x, int offset_y,
void RaceGUI::drawPosition(Kart* kart, int offset_x, int offset_y,
float ratio_x, float ratio_y )
{
// arenas don't have a position (rank)
if(RaceManager::getTrack()->isArena()) return;
if(kart->getPosition() == -1) return;
char str[256];
offset_x += (int)((user_config->m_width-110)*ratio_x);

View File

@ -42,7 +42,6 @@ class RaceSetup;
struct KartIconDisplayInfo
{
std::string time;
// int rank;
float r, g, b;
std::string special_title;
/** Current lap of this kart, or -1 if irrelevant

View File

@ -150,6 +150,8 @@ void TrackSel::switchGroup()
m_index_avail_tracks.clear();
const std::vector<int> &tracks =
RaceManager::isBattleMode( race_manager->getMinorMode() ) ?
track_manager->getArenasInGroup(user_config->m_track_group) :
track_manager->getTracksInGroup(user_config->m_track_group);
for(unsigned int i=0; i<tracks.size(); i++)
@ -163,7 +165,8 @@ void TrackSel::switchGroup()
// Now add the groups, indicated by a negative number as kart index
// ----------------------------------------------------------------
const std::vector<std::string>& groups=track_manager->getAllGroups();
for(int i =0; i<(int)groups.size(); i++)
const int group_size = (int)groups.size();
for(int i =0; i<group_size; i++)
{
// Only add groups other than the current one
if(groups[i]!=user_config->m_track_group) m_index_avail_tracks.push_back(-i-1);

View File

@ -10,6 +10,8 @@
95065F6A0E9127B800B2C509 /* race_result_message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95065F690E9127B700B2C509 /* race_result_message.cpp */; };
9519653D0E8C592F001BB888 /* linear_world.hpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9519653B0E8C592F001BB888 /* linear_world.hpp */; };
9519653E0E8C592F001BB888 /* linear_world.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9519653C0E8C592F001BB888 /* linear_world.cpp */; };
957A12BE0EA4271500E46BFD /* three_strikes_battle.hpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 957A12BC0EA4271500E46BFD /* three_strikes_battle.hpp */; };
957A12BF0EA4271500E46BFD /* three_strikes_battle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 957A12BD0EA4271500E46BFD /* three_strikes_battle.cpp */; };
95F0F25A0E85C054005F6693 /* callbacks.c in Sources */ = {isa = PBXBuildFile; fileRef = 95923F8B0E808EDC00388BDC /* callbacks.c */; };
95F0F25B0E85C054005F6693 /* list.c in Sources */ = {isa = PBXBuildFile; fileRef = 95923FAF0E808EDC00388BDC /* list.c */; };
95F0F25C0E85C054005F6693 /* host.c in Sources */ = {isa = PBXBuildFile; fileRef = 95923F9B0E808EDC00388BDC /* host.c */; };
@ -252,6 +254,7 @@
95F0F36E0E85C6A6005F6693 /* clock.hpp in CopyFiles */,
95F0F3830E85C76B005F6693 /* world.hpp in CopyFiles */,
9519653D0E8C592F001BB888 /* linear_world.hpp in CopyFiles */,
957A12BE0EA4271500E46BFD /* three_strikes_battle.hpp in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
@ -265,6 +268,8 @@
956F3FAC0E85BE0E006F93B0 /* random_generator.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = random_generator.hpp; sourceTree = "<group>"; };
956F3FAD0E85BE0E006F93B0 /* ssg_help.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ssg_help.cpp; sourceTree = "<group>"; };
956F3FAE0E85BE0E006F93B0 /* ssg_help.hpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = ssg_help.hpp; sourceTree = "<group>"; };
957A12BC0EA4271500E46BFD /* three_strikes_battle.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = three_strikes_battle.hpp; path = modes/three_strikes_battle.hpp; sourceTree = "<group>"; };
957A12BD0EA4271500E46BFD /* three_strikes_battle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = three_strikes_battle.cpp; path = modes/three_strikes_battle.cpp; sourceTree = "<group>"; };
957B11B30E831DA8002A69EA /* standard_race.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = standard_race.hpp; path = modes/standard_race.hpp; sourceTree = "<group>"; };
957B11B40E831DA8002A69EA /* standard_race.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = standard_race.cpp; path = modes/standard_race.cpp; sourceTree = "<group>"; };
957B11D70E8320CD002A69EA /* follow_the_leader.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = follow_the_leader.hpp; path = modes/follow_the_leader.hpp; sourceTree = "<group>"; };
@ -2066,6 +2071,8 @@
9519653B0E8C592F001BB888 /* linear_world.hpp */,
9519653C0E8C592F001BB888 /* linear_world.cpp */,
957B11B40E831DA8002A69EA /* standard_race.cpp */,
957A12BC0EA4271500E46BFD /* three_strikes_battle.hpp */,
957A12BD0EA4271500E46BFD /* three_strikes_battle.cpp */,
);
name = modes;
sourceTree = "<group>";
@ -2335,6 +2342,7 @@
95F0F3840E85C76B005F6693 /* world.cpp in Sources */,
9519653E0E8C592F001BB888 /* linear_world.cpp in Sources */,
95065F6A0E9127B800B2C509 /* race_result_message.cpp in Sources */,
957A12BF0EA4271500E46BFD /* three_strikes_battle.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -58,7 +58,8 @@ protected:
void forceRescue(Kart* kart, KartInfo& kart_info, bool shortcut);
void doLapCounting ( KartInfo& kart_info, Kart* kart );
float estimateFinishTimeForKart (Kart* kart, KartInfo& kart_info);
void updateRacePosition ( Kart* kart, KartInfo& kart_info );
public:
LinearWorld();
virtual ~LinearWorld();
@ -84,8 +85,6 @@ public:
virtual void terminateRace();
virtual void restartRace();
float estimateFinishTimeForKart (Kart* kart, KartInfo& kart_info);
void updateRacePosition ( Kart* kart, KartInfo& kart_info );
virtual bool raceHasLaps(){ return true; }
};

View File

@ -0,0 +1,170 @@
// 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/three_strikes_battle.hpp"
#include "gui/race_gui.hpp"
#include <string>
ThreeStrikesBattle::ThreeStrikesBattle() : World()
{
TimedRace::setClockMode(CHRONO);
// FIXME - disable AI karts in the GUI
if(race_manager->getNumKarts() > race_manager->getNumPlayers())
{
fprintf(stderr, "No AI exists for this game mode");
exit(1);
}
const unsigned int kart_amount = m_kart.size();
m_kart_display_info = new KartIconDisplayInfo[kart_amount];
for(unsigned int n=0; n<kart_amount; n++)
{
// create the struct that ill hold each player's lives
BattleInfo info;
info.m_lives = 3;
m_kart_info.push_back(info);
// no positions in this mode
m_kart[n]->setPosition(-1);
}// next kart
// TODO - implement
}
ThreeStrikesBattle::~ThreeStrikesBattle()
{
}
void ThreeStrikesBattle::onGo()
{
// Reset the brakes now that the prestart
// phase is over (braking prevents the karts
// from sliding downhill)
for(unsigned int i=0; i<m_kart.size(); i++)
{
m_kart[i]->resetBrakes();
}
}
void ThreeStrikesBattle::terminateRace()
{
// TODO - implement
}
std::string ThreeStrikesBattle::getInternalCode() const
{
return "BATTLE_3_STRIKES";
}
void ThreeStrikesBattle::update(float delta)
{
World::update(delta);
}
void ThreeStrikesBattle::restartRace()
{
}
//void ThreeStrikesBattle::getDefaultCollectibles(int& collectible_type, int& amount)
KartIconDisplayInfo* ThreeStrikesBattle::getKartsDisplayInfo(const RaceGUI* caller)
{
const unsigned int kart_amount = race_manager->getNumKarts();
for(unsigned int i = 0; i < kart_amount ; i++)
{
KartIconDisplayInfo& rank_info = m_kart_display_info[i];
// reset color
rank_info.lap = -1;
switch(m_kart_info[i].m_lives)
{
case 3:
rank_info.r = 0.0;
rank_info.g = 1.0;
rank_info.b = 0.0;
break;
case 2:
rank_info.r = 1.0;
rank_info.g = 0.9;
rank_info.b = 0.0;
break;
case 1:
rank_info.r = 1.0;
rank_info.g = 0.0;
rank_info.b = 0.0;
break;
case 0:
rank_info.r = 0.5;
rank_info.g = 0.5;
rank_info.b = 0.5;
break;
}
char lives[4];
sprintf(lives, "%i", m_kart_info[i].m_lives);
rank_info.time = lives; // FIXME - rename 'time' to something more generic
}
return m_kart_display_info;
}
void ThreeStrikesBattle::moveKartAfterRescue(Kart* kart, btRigidBody* body)
{
// find closest point to drop kart on
const int start_spots_amount = RaceManager::getTrack()->m_start_positions.size();
assert(start_spots_amount > 0);
int smallest_distance_found = -1, closest_id_found = -1;
const int kart_x = kart->getXYZ()[0];
const int kart_y = kart->getXYZ()[1];
for(int n=0; n<start_spots_amount; n++)
{
// no need for the overhead to compute exact distance with sqrt(), so using the
// 'manhattan' heuristic which will do fine enough.
const int dist_n = abs(kart_x - RaceManager::getTrack()->m_start_positions[n][0]) +
abs(kart_y - RaceManager::getTrack()->m_start_positions[n][1]);
if(dist_n < smallest_distance_found || closest_id_found == -1)
{
closest_id_found = n;
smallest_distance_found = dist_n;
}
}
assert(closest_id_found != -1);
kart->setXYZ( Vec3(RaceManager::getTrack()->m_start_positions[closest_id_found]) );
// FIXME - implement heading
// btQuaternion heading(btVector3(0.0f, 0.0f, 1.0f),
// DEGREE_TO_RAD(RaceManager::getTrack()->m_angle[info.m_track_sector]) );
// kart->setRotation(heading);
// A certain epsilon is added here to the Z coordinate (0.1), in case
// that the points are somewhat under the track. Otherwise, the
// kart will be placed a little bit under the track, triggering
// a rescue, ...
btTransform pos;
pos.setOrigin(kart->getXYZ()+btVector3(0, 0, 0.5f*kart->getKartHeight()+0.1f));
//pos.setRotation(btQuaternion(btVector3(0.0f, 0.0f, 1.0f),
// DEGREE_TO_RAD(RaceManager::getTrack()->m_angle[info.m_track_sector])));
body->setCenterOfMassTransform(pos);
}

View File

@ -0,0 +1,63 @@
// $Id: world.hpp 2326 2008-10-04 18:50:45Z auria $
//
// 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 THREE_STRIKES_HPP
#define THREE_STRIKES_HPP
#include "modes/world.hpp"
#include <string>
class KartIconDisplayInfo;
struct BattleInfo
{
int m_lives;
};
class ThreeStrikesBattle : public World
{
KartIconDisplayInfo* m_kart_display_info;
/** This vector contains an 'BattleInfo' struct for every kart in the race.
*/
std::vector<BattleInfo> m_kart_info;
public:
ThreeStrikesBattle();
virtual ~ThreeStrikesBattle();
// clock events
virtual void onGo();
virtual void terminateRace();
// overriding World methods
virtual void update(float delta);
virtual void restartRace();
//virtual void getDefaultCollectibles(int& collectible_type, int& amount);
//virtual bool useRedHerring();
virtual bool useFastMusicNearEnd() const { return false; }
virtual KartIconDisplayInfo* getKartsDisplayInfo(const RaceGUI* caller);
virtual bool raceHasLaps(){ return false; }
virtual void moveKartAfterRescue(Kart* kart, btRigidBody* body);
virtual std::string getInternalCode() const;
};
#endif

View File

@ -98,7 +98,7 @@ World::World() : TimedRace()
for(unsigned int i=0; i<race_manager->getNumKarts(); i++)
{
int position = i+1; // position start with 1
btTransform init_pos=m_track->getStartTransform(position);
btTransform init_pos=m_track->getStartTransform(i);
Kart* newkart;
const std::string& kart_name = race_manager->getKartName(i);
int local_player_id = race_manager->getKartLocalPlayerId(i);

View File

@ -104,7 +104,6 @@ protected:
*/
bool m_use_highscores;
//void updateRacePosition(int k);
void updateHighscores ();
void loadTrack ();
void resetAllKarts ();

View File

@ -32,6 +32,7 @@
#include "network/network_manager.hpp"
#include "modes/standard_race.hpp"
#include "modes/follow_the_leader.hpp"
#include "modes/three_strikes_battle.hpp"
RaceManager* race_manager= NULL;
@ -262,6 +263,7 @@ void RaceManager::startNextRace()
// and need world to be defined.
if(m_minor_mode==MINOR_MODE_FOLLOW_LEADER) new FollowTheLeaderRace();
else if(m_minor_mode==MINOR_MODE_QUICK_RACE || m_minor_mode==MINOR_MODE_TIME_TRIAL) new StandardRace();
else if(m_minor_mode==MINOR_MODE_3_STRIKES) new ThreeStrikesBattle();
else{ fprintf(stderr,"Could not create given race mode\n"); assert(0); }
m_active_race = true;

View File

@ -84,7 +84,7 @@ public:
MINOR_MODE_TIME_TRIAL = LINEAR_RACE(1, true),
MINOR_MODE_FOLLOW_LEADER = LINEAR_RACE(2, false),
MINOR_MODE_LAST_ALIVE = BATTLE_ARENA(0)
MINOR_MODE_3_STRIKES = BATTLE_ARENA(0)
};
#undef LINEAR_RACE
#undef BATTLE_ARENA

View File

@ -67,7 +67,7 @@ Track::Track( std::string filename_, float w, float h, bool stretch )
m_screenshot = "";
m_top_view = "";
m_has_final_camera = false;
m_is_arena = false;
loadTrack(m_filename);
loadDriveline();
@ -419,26 +419,38 @@ const Vec3& Track::trackToSpatial(const int SECTOR ) const
//-----------------------------------------------------------------------------
/** Returns the start coordinates for a kart on a given position pos
(with 0<=pos).
*/
btTransform Track::getStartTransform(unsigned int pos) const {
// Bug fix/workaround: sometimes the first kart would be too close
// to the first driveline point and not to the last one -->
// This kart would not get any lap counting done in the first
// lap! Therefor -1.5 is subtracted from the y position - which
// is a somewhat arbitrary value.
Vec3 orig;
pos--; // adjust from "1 to n" index to "0 to n-1"
orig.setX( pos<m_start_x.size() ? m_start_x[pos] : ((pos%2==0)?1.5f:-1.5f) );
orig.setY( pos<m_start_y.size() ? m_start_y[pos] : -1.5f*pos-1.5f );
orig.setZ( pos<m_start_z.size() ? m_start_z[pos] : 1.0f );
btTransform start;
start.setOrigin(orig);
start.setRotation(btQuaternion(btVector3(0, 0, 1),
pos<m_start_heading.size()
? DEGREE_TO_RAD(m_start_heading[pos])
: 0.0f ));
return start;
(with pos ranging from 0 to kart_num-1).
*/
btTransform Track::getStartTransform(unsigned int pos) const
{
Vec3 orig;
if(isArena())
{
assert(pos < m_start_positions.size());
orig.setX( m_start_positions[pos][0] );
orig.setY( m_start_positions[pos][1] );
orig.setZ( m_start_positions[pos][2] );
}
else
{
// Bug fix/workaround: sometimes the first kart would be too close
// to the first driveline point and not to the last one -->
// This kart would not get any lap counting done in the first
// lap! Therefor -1.5 is subtracted from the y position - which
// is a somewhat arbitrary value.
orig.setX( pos<m_start_x.size() ? m_start_x[pos] : ((pos%2==0)?1.5f:-1.5f) );
orig.setY( pos<m_start_y.size() ? m_start_y[pos] : -1.5f*pos-1.5f );
orig.setZ( pos<m_start_z.size() ? m_start_z[pos] : 1.0f );
}
btTransform start;
start.setOrigin(orig);
start.setRotation(btQuaternion(btVector3(0, 0, 1),
pos<m_start_heading.size()
? DEGREE_TO_RAD(m_start_heading[pos])
: 0.0f ));
return start;
} // getStartTransform
//-----------------------------------------------------------------------------
@ -845,6 +857,7 @@ void Track::loadTrack(std::string filename_)
LISP->get ("sun-specular", m_specular_col);
LISP->get ("sun-diffuse", m_diffuse_col);
LISP->get ("gravity", m_gravity);
LISP->get ("arena", m_is_arena);
LISP->get ("AI-angle-adjust", m_AI_angle_adjustment);
LISP->get ("AI-curve-speed-adjust", m_AI_curve_speed_adjustment);
LISP->getVector("groups", m_groups);
@ -1164,7 +1177,7 @@ void Track::loadTrackModel()
int need_hat = false ;
int fit_skin = false ;
char fname [ 1024 ] ;
sgCoord loc ;
sgCoord loc;
sgZeroVec3 ( loc.xyz ) ;
sgZeroVec3 ( loc.hpr ) ;
@ -1180,6 +1193,11 @@ void Track::loadTrackModel()
{
herring_command (&loc.xyz, htype, true) ;
}
else if ( sscanf ( s, "START,%f,%f,%f",
&(loc.xyz[0]), &(loc.xyz[1]), &(loc.xyz[2]) ) == 3 )
{
m_start_positions.push_back(Vec3(loc.xyz[0], loc.xyz[1], loc.xyz[2]));
}
else if ( s[0] == '\"' )
{
if ( sscanf ( s, "\"%[^\"]\",%f,%f,%f,%f,%f,%f",

View File

@ -62,6 +62,8 @@ private:
bool m_has_final_camera;
Vec3 m_camera_final_position;
Vec3 m_camera_final_hpr;
bool m_is_arena;
public:
enum RoadSide{ RS_DONT_KNOW = -1, RS_LEFT = 0, RS_RIGHT = 1 };
@ -105,6 +107,9 @@ public:
std::vector<SGfloat> m_path_width;
std::vector<SGfloat> m_angle;
/** Start positions for arenas (unused in linear races) */
std::vector<Vec3> m_start_positions;
//Left and Right drivelines for overhead map rendering.
//(Should probably be private as they are only use internally right now)
std::vector<Vec3> m_left_driveline;
@ -126,6 +131,7 @@ public:
Track (std::string filename,float w=100,
float h=100, bool stretch=1);
~Track ();
bool isArena () const { return m_is_arena; }
void cleanup ();
void addDebugToScene (int type ) const;
void draw2Dview (float x_offset,

View File

@ -115,7 +115,7 @@ std::vector<std::string> TrackManager::getAllTrackIdentifiers()
} // getAllTrackNames
//-----------------------------------------------------------------------------
/** Loads all track from the track directory (data/track).
/** Loads all tracks from the track directory (data/track).
*/
void TrackManager::loadTrackList ()
{
@ -155,11 +155,19 @@ void TrackManager::loadTrackList ()
void TrackManager::updateGroups(const Track* track)
{
const std::vector<std::string>& new_groups = track->getGroups();
for(unsigned int i=0; i<new_groups.size(); i++)
const bool isArena = track->isArena();
const unsigned int groups_amount = new_groups.size();
for(unsigned int i=0; i<groups_amount; i++)
{
if(m_groups.find(new_groups[i])==m_groups.end())
// if we didn't yet have this group in memory, add it to the global list
if(m_groups.find(new_groups[i])==m_groups.end() &&
m_arena_groups.find(new_groups[i])==m_arena_groups.end())
m_all_groups.push_back(new_groups[i]);
m_groups[new_groups[i]].push_back(m_tracks.size()-1);
// add this track to its group
if(isArena) m_arena_groups[new_groups[i]].push_back(m_tracks.size()-1);
else m_groups[new_groups[i]].push_back(m_tracks.size()-1);
}
} // updateGroups

View File

@ -34,6 +34,7 @@ private:
typedef std::vector<Track*> Tracks;
Tracks m_tracks;
std::map<std::string, std::vector<int> > m_groups;
std::map<std::string, std::vector<int> > m_arena_groups;
std::vector<std::string> m_all_groups;
/** Flag if this track is available or not. Tracks are set unavailable
* if they are not available on all clients (applies only to network mode)
@ -56,6 +57,8 @@ public:
bool isAvailable(unsigned int n) const {return m_track_avail[n];}
const std::vector<int>&
getTracksInGroup(const std::string& g) {return m_groups[g];}
const std::vector<int>&
getArenasInGroup(const std::string& g) {return m_arena_groups[g];}
std::vector<std::string> getAllTrackIdentifiers();
/** load all .track files from all directories */
void loadTrackList ();