Added thunderbird as start referee. Known bugs:

1) Ready, Set, Go is still shown.
2) Orientation of thunderbird is not correct in
   all cases (esp. in battle mode).


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@9822 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2011-09-14 00:48:49 +00:00
parent d3d0b87d93
commit f85556d83a
18 changed files with 452 additions and 13 deletions

View File

@ -264,6 +264,8 @@ set( SRCS ${SRCS} src/main.cpp
src/graphics/post_processing.hpp
src/graphics/rain.cpp
src/graphics/rain.hpp
src/graphics/referee.cpp
src/graphics/referee.hpp
src/graphics/shadow.cpp
src/graphics/shadow.hpp
src/graphics/skid_marks.cpp

BIN
data/models/Tex.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

13
data/models/referee.xml Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!-- model: the model filename to load as referee
{start,end}-rescue-frame: frame numbers for the rescue animation
{start,end}-start-frame: frame numbers for the start animation, -->
<referee model="thunderbird.b3d"
first-rescue-frame="1"
last-rescue-frame="99"
first-start-frame="1"
last-start-frame="26"
start-offset="-1.5 1 3"
scale = "0.3 0.3 0.3"
colors="traffic_light_red.jpg traffic_light_yellow.jpg trafficlight.jpg"
end-start-frame="100"/>

BIN
data/models/thunderbird.b3d Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -94,6 +94,8 @@ supertuxkart_SOURCES = \
graphics/post_processing.hpp \
graphics/rain.cpp \
graphics/rain.hpp \
graphics/referee.cpp \
graphics/referee.hpp \
graphics/shadow.cpp \
graphics/shadow.hpp \
graphics/skid_marks.cpp \

View File

@ -1273,6 +1273,7 @@ void IrrDriver::update(float dt)
irr_driver->getVideoDriver()->enableMaterial2D();
RaceGUIBase *rg = world->getRaceGUI();
rg->update(dt);
for(unsigned int i=0; i<world->getNumKarts(); i++)
{
Kart *kart=world->getKart(i);
@ -1287,7 +1288,7 @@ void IrrDriver::update(float dt)
#endif
kart->getCamera()->activate();
rg->preRenderCallback(*kart);
m_scene_manager->drawAll();
PROFILER_POP_CPU_MARKER();

192
src/graphics/referee.cpp Normal file
View File

@ -0,0 +1,192 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Joerg Henrichs
//
// 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 "graphics/referee.hpp"
#include "graphics/irr_driver.hpp"
#include "karts/kart.hpp"
#include "io/file_manager.hpp"
#include "io/xml_node.hpp"
#include "utils/string_utils.hpp"
int Referee::m_st_first_start_frame = 1;
int Referee::m_st_last_start_frame = 1;
int Referee::m_st_first_rescue_frame = 1;
int Referee::m_st_last_rescue_frame = 1;
int Referee::m_st_traffic_buffer = -1;
Vec3 Referee::m_st_start_offset = Vec3(-2, 2, 2);
Vec3 Referee::m_st_start_rotation = Vec3(0, 180, 0);
Vec3 Referee::m_st_scale = Vec3(1, 1, 1);
scene::IAnimatedMesh *Referee::m_st_referee_mesh = NULL;
video::ITexture *Referee::m_st_traffic_lights[3] = {NULL, NULL, NULL};
// ----------------------------------------------------------------------------
/** Loads the static mesh.
*/
void Referee::init()
{
assert(!m_st_referee_mesh);
const std::string filename=file_manager->getModelFile("referee.xml");
if(filename=="")
{
printf("Can't find referee.xml, aborting.\n");
exit(-1);
}
XMLNode *node = file_manager->createXMLTree(filename);
if(!node)
{
printf("Can't read XML file referee.xml, aborting.\n");
exit(-1);
}
if(node->getName()!="referee")
{
printf("The file referee.xml does not contain a referee"
"node, aborting.\n");
}
std::string model_filename;
node->get("model", &model_filename);
m_st_referee_mesh = irr_driver->getAnimatedMesh(
file_manager->getModelFile(model_filename) );
if(!m_st_referee_mesh)
{
printf("Can't find referee model '%s', aborting.\n", model_filename);
}
node->get("first-rescue-frame", &m_st_first_rescue_frame);
node->get("last-rescue-frame", &m_st_last_rescue_frame );
node->get("first-start-frame", &m_st_first_start_frame );
node->get("last-start-frame", &m_st_last_start_frame );
node->get("start-offset", &m_st_start_offset );
node->get("scale", &m_st_scale );
std::vector<std::string> colors;
node->get("colors", &colors);
if(colors.size()>3)
printf("Too many colors for referee defined, "
"only first three will be used.\n");
if(colors.size()<3)
{
printf("Not enough colors for referee defined, "
"only first three will be used, aborting.\n");
exit(-1);
}
for(unsigned int i=0; i<3; i++)
{
std::string full_path = file_manager->getTextureFile(colors[i]);
if(full_path.size()==0)
{
printf("Can't find texture '%s' for referee, aborting.\n",
colors[i].c_str());
exit(-1);
}
m_st_traffic_lights[i] = irr_driver->getTexture(full_path);
}
for(unsigned int i=0; i<m_st_referee_mesh->getMeshBufferCount(); i++)
{
scene::IMeshBuffer *mb = m_st_referee_mesh->getMeshBuffer(i);
const video::SMaterial &irrMaterial = mb->getMaterial();
video::ITexture* t=irrMaterial.getTexture(0);
std::string name=StringUtils::getBasename(t->getName()
.getInternalName().c_str());
if(name==colors[0] || name==colors[1] ||name==colors[2] )
{
m_st_traffic_buffer = i;
break;
}
}
} // init
// ----------------------------------------------------------------------------
/** Frees the static mesh.
*/
void Referee::cleanup()
{
irr_driver->removeMeshFromCache(m_st_referee_mesh);
} // cleanup
// ----------------------------------------------------------------------------
/** Creates an instance of the referee, using the static values to initialise
* it.
*/
Referee::Referee()
{
assert(m_st_referee_mesh);
// First add a NULL mesh, then set the material to be read only
// (this appears to be the only way to get read only materials).
// This way we only need to adjust the materials in the original
// mesh. ATM it doesn't make any difference, but if we ever should
// decide to use more than one referee model at startup we only
// have to change the textures once, and all models will be in synch.
m_scene_node = irr_driver->addAnimatedMesh(NULL);
m_scene_node->setReadOnlyMaterials(true);
m_scene_node->setMesh(m_st_referee_mesh);
m_scene_node->grab();
m_scene_node->setRotation(m_st_start_rotation.toIrrVector());
m_scene_node->setScale(m_st_scale.toIrrVector());
m_scene_node->setFrameLoop(m_st_first_start_frame, m_st_last_start_frame);
} // Referee
// ----------------------------------------------------------------------------
Referee::~Referee()
{
if(m_scene_node->getParent())
irr_driver->removeNode(m_scene_node);
m_scene_node->drop();
} // ~Referee
// ----------------------------------------------------------------------------
/** Make sure that this referee is attached to the scene graph. This is used
* for the start referee, which is removed from scene graph once the ready-
* set-go phase is over (it is kept in case of a restart of the race).
*/
void Referee::attachToSceneNode()
{
if(!m_scene_node->getParent())
m_scene_node->setParent(irr_driver->getSceneManager()
->getRootSceneNode());
} // attachToSceneNode
// ----------------------------------------------------------------------------
/** Removes the referee's scene node from the scene graph, but still keeps
* the scene node in memory. This is used for the start referee, so that
* it is quickly available in case of a restart.
*/
void Referee::removeFromSceneGraph()
{
if(!isAttached())
irr_driver->removeNode(m_scene_node);
} // removeFromSceneGraph
// ----------------------------------------------------------------------------
/** Selects one of the states 'ready', 'set', or 'go' to be displayed by
* the referee.
* \param rsg 0=ready, 1=set, 2=go.
*/
void Referee::selectReadySetGo(int rsg)
{
if(m_st_traffic_buffer<0) return;
video::SMaterial &m = m_scene_node->getMesh()->getMeshBuffer(m_st_traffic_buffer)->getMaterial();
m.setTexture(0, m_st_traffic_lights[rsg]);
} // selectReadySetGo

96
src/graphics/referee.hpp Normal file
View File

@ -0,0 +1,96 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Joerg Henrichs
//
// 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_REFEREE_HPP
#define HEADER_REFEREE_HPP
#include "irrlicht.h"
using namespace irr;
#include "utils/vec3.hpp"
class Kart;
/**
* \ingroup graphics
* This implements the referee, a character that is displayed at the start
* of the race holding a 'ready-set-go' traffic light (or so)
*/
class Referee
{
private:
/** The static mesh, which is loaded from a static function and shared
* between all instances. */
static scene::IAnimatedMesh *m_st_referee_mesh;
/** The three textures to use for ready, set, go. */
static video::ITexture *m_st_traffic_lights[3];
/** Which mesh buffer to use to show the traffic light texture. */
static int m_st_traffic_buffer;
/** Start frame of start animation. */
static int m_st_first_start_frame;
/** End frame of start animation. */
static int m_st_last_start_frame;
/** Start frame of rescue animation. */
static int m_st_first_rescue_frame;
/** End frame of rescue animation. */
static int m_st_last_rescue_frame;
/** The position the referee should be shown relative to the kart
* when starting the race. */
static Vec3 m_st_start_offset;
/** Scaling to be applied to the referee. */
static Vec3 m_st_scale;
/** A rotation to be applied to the referee before displaying it. */
static Vec3 m_st_start_rotation;
/** The scene node for an instance of the referee. */
scene::IAnimatedMeshSceneNode *m_scene_node;
public:
Referee();
~Referee();
void selectReadySetGo(int rsg);
void attachToSceneNode();
static void init();
static void cleanup();
void removeFromSceneGraph();
// ------------------------------------------------------------------------
/** Moves the referee to the specified position. */
void setPosition(const Vec3 &xyz)
{m_scene_node->setPosition(xyz.toIrrVector()); }
// ------------------------------------------------------------------------
/** Returns true if this referee is attached to the scene graph. */
bool isAttached() const {return m_scene_node->getParent()!=NULL;}
// ------------------------------------------------------------------------
/** Returns the graphical offset the referee should be drawn at at the
* start of a race. */
static const Vec3& getStartOffset() {return m_st_start_offset; }
}; // Referee
#endif
/* EOF */

View File

@ -618,6 +618,7 @@ namespace GUIEngine
#include "guiengine/skin.hpp"
#include "guiengine/widget.hpp"
#include "modes/world.hpp"
#include "states_screens/race_gui_base.hpp"
using namespace irr::gui;
using namespace irr::video;

View File

@ -754,6 +754,10 @@
RelativePath="..\..\graphics\rain.cpp"
>
</File>
<File
RelativePath="..\..\graphics\referee.cpp"
>
</File>
<File
RelativePath="..\..\graphics\shadow.cpp"
>
@ -1844,6 +1848,10 @@
RelativePath="..\..\graphics\rain.hpp"
>
</File>
<File
RelativePath="..\..\graphics\referee.hpp"
>
</File>
<File
RelativePath="..\..\graphics\shadow.hpp"
>

View File

@ -55,6 +55,7 @@
#include "graphics/hardware_skinning.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/referee.hpp"
#include "guiengine/engine.hpp"
#include "input/input_manager.hpp"
#include "input/device_manager.hpp"
@ -863,7 +864,6 @@ void initRest()
attachment_manager = new AttachmentManager ();
highscore_manager = new HighscoreManager ();
network_manager = new NetworkManager ();
KartPropertiesManager::addKartSearchDir(
file_manager->getAddonsFile("karts"));
track_manager->addTrackSearchDir(
@ -888,9 +888,6 @@ void initRest()
race_manager->setMajorMode (RaceManager::MAJOR_MODE_SINGLE);
race_manager->setMinorMode (RaceManager::MINOR_MODE_NORMAL_RACE);
race_manager->setDifficulty((RaceManager::Difficulty)(int)UserConfigParams::m_difficulty);
// race_manager->setDifficulty(RaceManager::RD_HARD);
//menu_manager= new MenuManager();
} // initRest
@ -903,6 +900,7 @@ void cleanSuperTuxKart()
network_http->stopNetworkThread();
//delete in reverse order of what they were created in.
//see InitTuxkart()
Referee::cleanup();
if(race_manager) delete race_manager;
if(network_http) delete network_http;
if(news_manager) delete news_manager;
@ -989,6 +987,7 @@ int main(int argc, char *argv[] )
// implementation) make the temporary materials permanent anyway.
material_manager->addSharedMaterial(materials_file);
}
Referee::init();
powerup_manager -> loadAllPowerups ();
item_manager -> loadDefaultItems();

View File

@ -163,8 +163,9 @@ void World::init()
powerup_manager->updateWeightsForRace(num_karts);
// erase messages left over
RaceGUIBase* m = World::getWorld()->getRaceGUI();
if (m) m->clearAllMessages();
RaceGUIBase* rg = World::getWorld()->getRaceGUI();
rg->init();
if (rg) rg->clearAllMessages();
} // init
//-----------------------------------------------------------------------------
@ -830,7 +831,7 @@ void World::restartRace()
{
// If m_saved_race_gui is set, it means that the restart was done
// when the race result gui was being shown. In this case restore the
// race gui (not that the race result gui is cached and so never really
// race gui (note that the race result gui is cached and so never really
// destroyed).
if(m_saved_race_gui)
{
@ -838,6 +839,7 @@ void World::restartRace()
m_saved_race_gui = NULL;
}
m_race_gui->restartRace();
m_race_gui->clearAllMessages();
m_schedule_pause = false;

View File

@ -143,7 +143,7 @@ void WorldStatus::update(const float dt)
// long, we use the aux timer to force the next phase
// after 3.5 seconds.
if(m_track_intro_sound->getStatus()==SFXManager::SFX_PLAYING
&& m_auxiliary_timer<3.5f)
&& m_auxiliary_timer<3.5f)
return;
m_auxiliary_timer = 0.0f;
m_prestart_sound->play();
@ -188,7 +188,9 @@ void WorldStatus::update(const float dt)
music_manager->startMusic(music_manager->getCurrentMusic());
if(m_auxiliary_timer>3.0f) // how long to display the 'go' message
{
m_phase=MUSIC_PHASE;
}
m_auxiliary_timer += dt;

View File

@ -35,6 +35,7 @@
#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/referee.hpp"
#include "guiengine/scalable_font.hpp"
#include "io/file_manager.hpp"
#include "items/attachment_manager.hpp"
@ -80,13 +81,56 @@ RaceGUIBase::RaceGUIBase()
//I18N: When some GlobalPlayerIcons are hidden, write "Top 10" to show it
m_string_top = _("Top %i");
m_referee = NULL;
} // RaceGUIBase
// ----------------------------------------------------------------------------
/** This is a second initialisation call (after the constructor) for the race
* gui. This is called after the world has been initialised, e.g. all karts
* do exist (while the constructor is called before the karts are created).
* In the base gui this is used to initialise the referee data (which needs
* the start positions of the karts).
*/
void RaceGUIBase::init()
{
// While we actually only need the positions for local players,
// we add all karts, since it's easier to get a world kart id from
// the kart then the local player id (and it avoids problems in
// profile mode where there might be a camera, but no player).
for(unsigned int i=0; i<race_manager->getNumberOfKarts(); i++)
{
const Kart *kart = World::getWorld()->getKart(i);
m_referee_pos.push_back(kart->getTrans()(Referee::getStartOffset()));
}
m_referee = new Referee();
// Do everything else required at a race restart as well, esp.
// resetting the height of the referee.
restartRace();
} // init
//-----------------------------------------------------------------------------
/** This is called when restarting a race. In the race gui base it resets
* height of the referee, so that it can start flying down again.
*/
void RaceGUIBase::restartRace()
{
m_referee_height = 10.0f;
m_referee->attachToSceneNode();
} // restartRace
//-----------------------------------------------------------------------------
/** The destructor removes the marker texture and the referee scene node.
*/
RaceGUIBase::~RaceGUIBase()
{
irr_driver->removeTexture(m_marker);
// If the referee is currently being shown,
// remove it from the scene graph.
delete m_referee;
} // ~RaceGUIBase
//-----------------------------------------------------------------------------
@ -308,6 +352,11 @@ void RaceGUIBase::cleanupMessages(const float dt)
} // cleanupMessages
//-----------------------------------------------------------------------------
/** Draws the powerup icons on the screen (called once for each player).
* \param kart The kart for which to draw the powerup icons.
* \param viewport The viewport into which to draw the icons.
* \param scaling The scaling to use when draing the icons.
*/
void RaceGUIBase::drawPowerupIcons(const Kart* kart,
const core::recti &viewport,
const core::vector2df &scaling)
@ -353,6 +402,60 @@ void RaceGUIBase::renderGlobal(float dt)
} // renderGlobal
// ----------------------------------------------------------------------------
/** Update, called once per frame. This updates the height of the referee
* (to create a flying down animation).
* \param dt Time step size.
*/
void RaceGUIBase::update(float dt)
{
// E.g. a race result gui does not have a referee
if(m_referee)
{
World *world = World::getWorld();
// During GO move the referee up again
if(world->getPhase()==World::SETUP_PHASE)
{
m_referee_height = 10.0f;
m_referee->selectReadySetGo(0); // set red color
}
else if(world->getPhase()==World::GO_PHASE)
{
m_referee_height += dt*5.0f;
m_referee->selectReadySetGo(2);
}
else if(world->getPhase()==World::TRACK_INTRO_PHASE)
{
m_referee->selectReadySetGo(0); // set red color
m_referee_height -= dt*5.0f;
if(m_referee_height<0)
m_referee_height = 0;
}
else if(world->isStartPhase()) // must be ready or set now
{
m_referee_height = 0;
m_referee->selectReadySetGo(world->getPhase()==World::SET_PHASE
? 1 : 0);
}
else if(m_referee->isAttached()) // race phase:
{
m_referee->removeFromSceneGraph();
}
} // if referee node
} // update
// ----------------------------------------------------------------------------
/** This function is called just before rendering the view for each kart. This
* is used here to display the referee during the ready-set-go phase.
* \param kart The kart whose view is rendered next.
*/
void RaceGUIBase::preRenderCallback(const Kart &kart)
{
Vec3 xyz = m_referee_pos[kart.getWorldKartId()];
xyz.setY(xyz.getY()+m_referee_height);
m_referee->setPosition(xyz);
} // preRenderCallback
// ----------------------------------------------------------------------------
void RaceGUIBase::renderPlayerView(const Kart *kart)
{
@ -862,4 +965,3 @@ void RaceGUIBase::drawGlobalPlayerIcons(const KartIconDisplayInfo* info,
} //next position
} // drawGlobalPlayerIcons

View File

@ -30,12 +30,15 @@
namespace irr
{
namespace video { class ITexture; struct S3DVertex; }
namespace scene { class IAnimatedMeshSceneNode; }
}
using namespace irr;
#include "utils/vec3.hpp"
class Kart;
class Material;
class Referee;
/**
* \brief An abstract base class for the two race guis (race_gui and
@ -124,7 +127,18 @@ private:
/** Translated string 'Top %d' displayed every frame. */
core::stringw m_string_top;
/** The position of the referee for all karts. */
std::vector<Vec3> m_referee_pos;
/** The height of the referee. This is used to make the referee fly
* into view. This is the same Y-offset for all karts, so only a
* single value needs to be used. */
float m_referee_height;
/** The referee scene node. */
Referee *m_referee;
protected:
/** Material for the 'plunger in the face' texture. */
Material *m_plunger_face;
@ -153,7 +167,6 @@ protected:
void drawPowerupIcons (const Kart* kart,
const core::recti &viewport,
const core::vector2df &scaling);
void drawGlobalMusicDescription();
void drawGlobalReadySetGo ();
@ -176,6 +189,8 @@ public:
RaceGUIBase();
virtual ~RaceGUIBase();
virtual void renderGlobal(float dt);
virtual void init();
virtual void restartRace();
virtual void renderPlayerView(const Kart *kart);
virtual void addMessage(const irr::core::stringw &m, const Kart *kart,
float time,
@ -183,9 +198,13 @@ public:
video::SColor(255, 255, 0, 255),
bool important=true,
bool big_font=false);
virtual void update(float dt);
virtual void preRenderCallback(const Kart &kart);
// ------------------------------------------------------------------------
/** Returns the size of the texture on which to render the minimap to. */
virtual const core::dimension2du
getMiniMapSize() const = 0;
// ------------------------------------------------------------------------
virtual void clearAllMessages() { m_messages.clear(); }
/** Set the flag that a lightning should be shown. */