Big refactoring: the camera for a kart is now not part of the

kart anymore, instead they are managed by static functions
in Camera. This allows us to have several cameras for one
kart now (can be useful for debugging; or for three-screen setup
where you have one monitor for left, right, and center; or potentially
for an back mirrir). Also 'rain' is moved into camera now (where it
belongs more naturally then in kart), and several loops over all
karts searching for a camera are now replaced by simpler loops over
all cameras (though a few loops were added to handle code for all
cameras now, while before there as no loop).
Main advantage: handling post-processing will be easier to do now.
Also this fixes a bug: in split screen mode, when a kart is eliminated
(ftl) the camera for this kart was supposed to show the
leader facing backwards, which didn't work (it just showed the previous
location of the elimintaed kart) - now it works.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@12541 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2013-03-06 22:08:41 +00:00
parent c5a9b4b6a5
commit 502042432c
32 changed files with 342 additions and 272 deletions

View File

@ -28,6 +28,7 @@
#include "audio/music_manager.hpp" #include "audio/music_manager.hpp"
#include "config/user_config.hpp" #include "config/user_config.hpp"
#include "graphics/irr_driver.hpp" #include "graphics/irr_driver.hpp"
#include "graphics/rain.hpp"
#include "io/xml_node.hpp" #include "io/xml_node.hpp"
#include "karts/abstract_kart.hpp" #include "karts/abstract_kart.hpp"
#include "karts/explosion_animation.hpp" #include "karts/explosion_animation.hpp"
@ -39,15 +40,19 @@
#include "utils/aligned_array.hpp" #include "utils/aligned_array.hpp"
#include "utils/constants.hpp" #include "utils/constants.hpp"
#include <ICameraSceneNode.h> #include "ICameraSceneNode.h"
#include <ISceneManager.h> #include "ISceneManager.h"
AlignedArray<Camera::EndCameraInformation> Camera::m_end_cameras; AlignedArray<Camera::EndCameraInformation> Camera::m_end_cameras;
std::vector<Camera*> Camera::m_all_cameras;
Camera::Camera(int camera_index, AbstractKart* kart) // ============================================================================
Camera::Camera(int camera_index, AbstractKart* kart) : m_kart(NULL)
{ {
m_mode = CM_NORMAL; m_mode = CM_NORMAL;
m_index = camera_index; m_index = camera_index;
m_rain = NULL;
m_original_kart = kart;
m_camera = irr_driver->addCameraSceneNode(); m_camera = irr_driver->addCameraSceneNode();
#ifdef DEBUG #ifdef DEBUG
@ -56,7 +61,7 @@ Camera::Camera(int camera_index, AbstractKart* kart)
setupCamera(); setupCamera();
m_distance = kart->getKartProperties()->getCameraDistance(); m_distance = kart->getKartProperties()->getCameraDistance();
m_kart = kart; setKart(kart);
m_ambient_light = World::getWorld()->getTrack()->getDefaultAmbientColor(); m_ambient_light = World::getWorld()->getTrack()->getDefaultAmbientColor();
// TODO: Put these values into a config file // TODO: Put these values into a config file
@ -83,6 +88,7 @@ Camera::Camera(int camera_index, AbstractKart* kart)
*/ */
Camera::~Camera() Camera::~Camera()
{ {
if(m_rain) delete m_rain;
irr_driver->removeCameraSceneNode(m_camera); irr_driver->removeCameraSceneNode(m_camera);
} // ~Camera } // ~Camera
@ -90,12 +96,16 @@ Camera::~Camera()
/** Changes the owner of this camera to the new kart. /** Changes the owner of this camera to the new kart.
* \param new_kart The new kart to use this camera. * \param new_kart The new kart to use this camera.
*/ */
void Camera::changeOwner(AbstractKart *new_kart) void Camera::setKart(AbstractKart *new_kart)
{ {
m_kart->setCamera(NULL);
m_kart = new_kart; m_kart = new_kart;
new_kart->setCamera(this); #ifdef DEBUG
} // changeOwner std::string name = new_kart->getIdent()+"'s camera";
if(new_kart)
getCameraSceneNode()->setName(name.c_str() );
#endif
} // setKart
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** This function clears all end camera data structure. This is necessary /** This function clears all end camera data structure. This is necessary
@ -203,6 +213,13 @@ void Camera::setupCamera()
m_camera->setFOV(m_fov); m_camera->setFOV(m_fov);
m_camera->setAspectRatio(m_aspect); m_camera->setAspectRatio(m_aspect);
m_camera->setFarValue(World::getWorld()->getTrack()->getCameraFar()); m_camera->setFarValue(World::getWorld()->getTrack()->getCameraFar());
if (UserConfigParams::m_weather_effects &&
World::getWorld()->getTrack()->getWeatherType() == WEATHER_RAIN)
{
m_rain = new Rain(this, NULL);
}
} // setupCamera } // setupCamera
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -252,6 +269,7 @@ Camera::Mode Camera::getMode()
*/ */
void Camera::reset() void Camera::reset()
{ {
m_kart = m_original_kart;
setMode(CM_NORMAL); setMode(CM_NORMAL);
setInitialTransform(); setInitialTransform();
} // reset } // reset
@ -422,6 +440,16 @@ void Camera::getCameraSettings(float *above_kart, float *cam_angle,
*/ */
void Camera::update(float dt) void Camera::update(float dt)
{ {
if (UserConfigParams::m_graphical_effects)
{
if (m_rain)
{
m_rain->setPosition( getCameraSceneNode()->getPosition() );
m_rain->update(dt);
}
} // UserConfigParams::m_graphical_effects
// The following settings give a debug camera which shows the track from // The following settings give a debug camera which shows the track from
// high above the kart straight down. // high above the kart straight down.
if(UserConfigParams::m_camera_debug) if(UserConfigParams::m_camera_debug)

View File

@ -21,23 +21,26 @@
#ifndef HEADER_CAMERA_HPP #ifndef HEADER_CAMERA_HPP
#define HEADER_CAMERA_HPP #define HEADER_CAMERA_HPP
#include "io/xml_node.hpp"
#include "utils/no_copy.hpp"
#include "utils/aligned_array.hpp"
#include "utils/leak_check.hpp"
#include "utils/vec3.hpp"
#include "SColor.h"
#include "vector2d.h"
#include "rect.h"
#include <vector> #include <vector>
#include <SColor.h>
#include <vector2d.h>
#include <rect.h>
namespace irr namespace irr
{ {
namespace scene { class ICameraSceneNode; } namespace scene { class ICameraSceneNode; }
} }
using namespace irr; using namespace irr;
#include "io/xml_node.hpp"
#include "utils/no_copy.hpp"
#include "utils/aligned_array.hpp"
#include "utils/vec3.hpp"
class AbstractKart; class AbstractKart;
class Rain;
/** /**
* \brief Handles the game camera * \brief Handles the game camera
@ -91,6 +94,11 @@ private:
* since in profile mode the camera might change its owner. */ * since in profile mode the camera might change its owner. */
AbstractKart *m_kart; AbstractKart *m_kart;
/** A pointer to the original kart the camera was pointing at when it
* was created. Used when restarting a race (since the camera might
* get attached to another kart if a kart is elimiated). */
AbstractKart *m_original_kart;
/** The list of viewports for this cameras. */ /** The list of viewports for this cameras. */
core::recti m_viewport; core::recti m_viewport;
@ -113,6 +121,13 @@ private:
* modern style. Should default to modern. */ * modern style. Should default to modern. */
Style m_camera_style; Style m_camera_style;
/** List of all cameras. */
static std::vector<Camera*> m_all_cameras;
/** Used to show rain graphical effects. */
Rain *m_rain;
/** A class that stores information about the different end cameras /** A class that stores information about the different end cameras
* which can be specified in the scene.xml file. */ * which can be specified in the scene.xml file. */
class EndCameraInformation class EndCameraInformation
@ -190,9 +205,41 @@ private:
bool *smoothing); bool *smoothing);
void positionCamera(float dt, float above_kart, float cam_angle, void positionCamera(float dt, float above_kart, float cam_angle,
float side_way, float distance, float smoothing); float side_way, float distance, float smoothing);
public:
Camera(int camera_index, AbstractKart* kart); Camera(int camera_index, AbstractKart* kart);
~Camera(); ~Camera();
public:
LEAK_CHECK()
/** Returns the number of cameras used. */
static unsigned int getNumCameras() { return m_all_cameras.size(); }
// ------------------------------------------------------------------------
/** Returns a camera. */
static Camera *getCamera(unsigned int n) { return m_all_cameras[n]; }
// ------------------------------------------------------------------------
/** Remove all cameras. */
static void removeAllCameras()
{
for(unsigned int i=0; i<m_all_cameras.size(); i++)
delete m_all_cameras[i];
m_all_cameras.clear();
} // removeAllCameras
// ------------------------------------------------------------------------
/** Creates a camera and adds it to the list of all cameras. Also the
* camera index (which determines which viewport to use in split screen)
* is set.
*/
static Camera* createCamera(AbstractKart* kart)
{
Camera *c = new Camera(m_all_cameras.size(), kart);
m_all_cameras.push_back(c);
return c;
} // createCamera
// ------------------------------------------------------------------------
static void readEndCamera(const XMLNode &root); static void readEndCamera(const XMLNode &root);
static void clearEndCameras(); static void clearEndCameras();
void setMode (Mode mode_); /** Set the camera to the given mode */ void setMode (Mode mode_); /** Set the camera to the given mode */
@ -203,7 +250,15 @@ public:
void setInitialTransform(); void setInitialTransform();
void activate(); void activate();
void update (float dt); void update (float dt);
void changeOwner (AbstractKart *new_kart); void setKart (AbstractKart *new_kart);
// ------------------------------------------------------------------------
/** Returns the kart to which this camera is attached. */
const AbstractKart* getKart() const { return m_kart; }
// ------------------------------------------------------------------------
/** Returns the kart to which this camera is attached. */
AbstractKart* getKart() { return m_kart; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Sets the ambient light for this camera. */ /** Sets the ambient light for this camera. */

View File

@ -1655,20 +1655,18 @@ void IrrDriver::update(float dt)
if (rg) rg->update(dt); if (rg) rg->update(dt);
for(unsigned int i=0; i<world->getNumKarts(); i++) for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{ {
// We can't loop over player karts, since in profile/demo Camera *camera = Camera::getCamera(i);
// mode a non-player kart will have a camera
AbstractKart *kart=world->getKart(i);
if(!kart->getCamera()) continue;
#ifdef ENABLE_PROFILER #ifdef ENABLE_PROFILER
std::ostringstream oss; std::ostringstream oss;
oss << "drawAll() for kart " << i << std::flush; oss << "drawAll() for kart " << i << std::flush;
PROFILER_PUSH_CPU_MARKER(oss.str().c_str(), (i+1)*60, PROFILER_PUSH_CPU_MARKER(oss.str().c_str(), (i+1)*60,
0x00, 0x00); 0x00, 0x00);
#endif #endif
kart->getCamera()->activate(); camera->activate();
rg->preRenderCallback(*kart); // adjusts start referee rg->preRenderCallback(camera); // adjusts start referee
m_scene_manager->drawAll(); m_scene_manager->drawAll();
PROFILER_POP_CPU_MARKER(); PROFILER_POP_CPU_MARKER();
@ -1692,15 +1690,14 @@ void IrrDriver::update(float dt)
UserConfigParams::m_width, UserConfigParams::m_width,
UserConfigParams::m_height)); UserConfigParams::m_height));
for(unsigned int i=0; i<world->getNumKarts(); i++) for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{ {
AbstractKart *kart = world->getKart(i); Camera *camera = Camera::getCamera(i);
if(!kart->getCamera()) continue;
char marker_name[100]; char marker_name[100];
sprintf(marker_name, "renderPlayerView() for kart %d", i); sprintf(marker_name, "renderPlayerView() for kart %d", i);
PROFILER_PUSH_CPU_MARKER(marker_name, 0x00, 0x00, (i+1)*60); PROFILER_PUSH_CPU_MARKER(marker_name, 0x00, 0x00, (i+1)*60);
rg->renderPlayerView(kart, dt); rg->renderPlayerView(camera, dt);
PROFILER_POP_CPU_MARKER(); PROFILER_POP_CPU_MARKER();
} // for i<getNumKarts } // for i<getNumKarts

View File

@ -41,11 +41,12 @@ const float TEXTURE_X_TILES[RAIN_RING_COUNT] = { 2.0f, 2.5f, 3.5f, 5.0f, 8.0f };
const float TEXTURE_Y_TILES[RAIN_RING_COUNT] = { 8.0f, 7.0f, 6.0f, 4.0f, 4.0f }; const float TEXTURE_Y_TILES[RAIN_RING_COUNT] = { 8.0f, 7.0f, 6.0f, 4.0f, 4.0f };
Rain::Rain(irr::scene::ICameraSceneNode* camera, irr::scene::ISceneNode* parent, bool lightning) Rain::Rain(Camera *camera, irr::scene::ISceneNode* parent)
{ {
m_lightning = lightning; m_lightning = camera->getIndex()==0;
if (lightning) m_thunder_sound = sfx_manager->createSoundSource("thunder"); if (m_lightning)
m_thunder_sound = sfx_manager->createSoundSource("thunder");
Material* m = material_manager->getMaterial("rain.png"); Material* m = material_manager->getMaterial("rain.png");
assert(m != NULL); assert(m != NULL);
@ -108,7 +109,9 @@ Rain::Rain(irr::scene::ICameraSceneNode* camera, irr::scene::ISceneNode* parent,
mesh->addMeshBuffer(buffer); mesh->addMeshBuffer(buffer);
mesh->recalculateBoundingBox(); mesh->recalculateBoundingBox();
m_node[r] = irr_driver->addPerCameraMesh(mesh, camera, parent); m_node[r] = irr_driver->addPerCameraMesh(mesh,
camera->getCameraSceneNode(),
parent);
mesh->drop(); mesh->drop();
buffer->drop(); buffer->drop();

View File

@ -19,6 +19,7 @@
#ifndef HEADER_RAIN_HPP #ifndef HEADER_RAIN_HPP
#define HEADER_RAIN_HPP #define HEADER_RAIN_HPP
class Camera;
class PerCameraNode; class PerCameraNode;
#include <vector3d.h> #include <vector3d.h>
@ -47,7 +48,7 @@ class Rain
SFXBase* m_thunder_sound; SFXBase* m_thunder_sound;
public: public:
Rain(irr::scene::ICameraSceneNode* camera, irr::scene::ISceneNode* parent, bool lightning); Rain(Camera* camera, irr::scene::ISceneNode* parent);
~Rain(); ~Rain();
void update(float dt); void update(float dt);

View File

@ -118,15 +118,7 @@ void InputManager::handleStaticAction(int key, int value)
if(!ProfileWorld::isProfileMode() || !world) break; if(!ProfileWorld::isProfileMode() || !world) break;
int kart_id = key - KEY_KEY_1; int kart_id = key - KEY_KEY_1;
if(kart_id<0 || kart_id>=(int)world->getNumKarts()) break; if(kart_id<0 || kart_id>=(int)world->getNumKarts()) break;
for(unsigned int i=0; i<world->getNumKarts(); i++) Camera::getCamera(0)->setKart(world->getKart(kart_id));
{
if(world->getKart(i)->getCamera())
{
world->getKart(i)->getCamera()
->changeOwner(world->getKart(kart_id));
}
}
break; break;
} }
#endif #endif

View File

@ -29,7 +29,6 @@ class Attachment;
class btKart; class btKart;
class btQuaternion; class btQuaternion;
class btUprightConstraint; class btUprightConstraint;
class Camera;
class Controller; class Controller;
class Item; class Item;
class KartModel; class KartModel;
@ -81,7 +80,7 @@ public:
int position, const btTransform& init_transform); int position, const btTransform& init_transform);
virtual ~AbstractKart(); virtual ~AbstractKart();
virtual void reset(); virtual void reset();
virtual void init(RaceManager::KartType type, bool is_first_kart) = 0; virtual void init(RaceManager::KartType type) = 0;
// ======================================================================== // ========================================================================
// Functions related to controlling the kart // Functions related to controlling the kart
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -280,18 +279,6 @@ public:
/** Activates a slipstream effect, atm that is display some nitro. */ /** Activates a slipstream effect, atm that is display some nitro. */
virtual void setSlipstreamEffect(float f) = 0; virtual void setSlipstreamEffect(float f) = 0;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Sets the camera for this kart. Takes ownership of the camera and
* will delete it. */
virtual void setCamera(Camera *camera) = 0;
// ------------------------------------------------------------------------
/** Returns the camera of this kart (or NULL if no camera is attached
* to this kart). */
virtual Camera* getCamera() = 0;
// ------------------------------------------------------------------------
/** Returns the camera of this kart (or NULL if no camera is attached
* to this kart). */
virtual const Camera* getCamera() const = 0;
// ------------------------------------------------------------------------
/** Plays a beep sfx. */ /** Plays a beep sfx. */
virtual void beep() = 0; virtual void beep() = 0;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -88,6 +88,9 @@ protected:
void computePath(); void computePath();
virtual bool doSkid(float steer_fraction); virtual bool doSkid(float steer_fraction);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Nothing special to do when the race is finished. */
virtual void raceFinished() {};
// ------------------------------------------------------------------------
/** This can be called to detect if the kart is stuck (i.e. repeatedly /** This can be called to detect if the kart is stuck (i.e. repeatedly
* hitting part of the track). */ * hitting part of the track). */
bool isStuck() const { return m_stuck_trigger_rescue; } bool isStuck() const { return m_stuck_trigger_rescue; }

View File

@ -69,7 +69,6 @@ public:
virtual void crashed (const AbstractKart *k) = 0; virtual void crashed (const AbstractKart *k) = 0;
virtual void crashed (const Material *m) = 0; virtual void crashed (const Material *m) = 0;
virtual void setPosition (int p) = 0; virtual void setPosition (int p) = 0;
virtual void finishedRace (float time) = 0;
virtual bool isPlayerController () const = 0; virtual bool isPlayerController () const = 0;
virtual bool isNetworkController() const = 0; virtual bool isNetworkController() const = 0;
virtual bool disableSlipstreamBonus() const = 0; virtual bool disableSlipstreamBonus() const = 0;
@ -98,6 +97,10 @@ public:
virtual void newLap(int lap) = 0; virtual void newLap(int lap) = 0;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual void skidBonusTriggered() = 0; virtual void skidBonusTriggered() = 0;
// ------------------------------------------------------------------------
/** Called whan this controller's kart finishes the last lap. */
virtual void finishedRace(float time) = 0;
// ------------------------------------------------------------------------
}; // Controller }; // Controller
#endif #endif

View File

@ -54,6 +54,7 @@ EndController::EndController(AbstractKart *kart, StateManager::ActivePlayer *pla
Controller *prev_controller) Controller *prev_controller)
: AIBaseController(kart, player) : AIBaseController(kart, player)
{ {
m_previous_controller = prev_controller;
if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES) if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES)
{ {
// Overwrite the random selected default path from AIBaseController // Overwrite the random selected default path from AIBaseController
@ -150,9 +151,10 @@ void EndController::reset()
*/ */
void EndController::newLap(int lap) void EndController::newLap(int lap)
{ {
// This will implicitely trigger setting the first end camera to be active. // Forward the call to the original controller. This will implicitely
if(m_kart->getCamera()) // trigger setting the first end camera to be active if the controller
m_kart->getCamera()->setMode(Camera::CM_FINAL); // is a player controller.
m_previous_controller->newLap(lap);
} // newLap } // newLap
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -23,6 +23,7 @@
#include "karts/controller/ai_base_controller.hpp" #include "karts/controller/ai_base_controller.hpp"
class Camera;
class LinearWorld; class LinearWorld;
class QuadGraph; class QuadGraph;
class Track; class Track;
@ -62,6 +63,9 @@ private:
float m_time_since_stuck; float m_time_since_stuck;
/** Stores a pointer to the original controller. */
Controller *m_previous_controller;
/** For debugging purpose: a sphere indicating where the AI /** For debugging purpose: a sphere indicating where the AI
* is targeting at. */ * is targeting at. */
irr::scene::ISceneNode *m_debug_sphere; irr::scene::ISceneNode *m_debug_sphere;

View File

@ -56,9 +56,9 @@ PlayerController::PlayerController(AbstractKart *kart,
m_player = player; m_player = player;
m_player->setKart(kart); m_player->setKart(kart);
m_penalty_time = 0.0f; m_penalty_time = 0.0f;
kart->setCamera(new Camera(player_index, kart)); // Keep a pointer to the camera to remove the need to search for
kart->getCamera()->setMode(Camera::CM_NORMAL); // the right camera once per frame later.
m_camera = Camera::createCamera(kart);
m_bzzt_sound = sfx_manager->createSoundSource( "bzzt" ); m_bzzt_sound = sfx_manager->createSoundSource( "bzzt" );
m_wee_sound = sfx_manager->createSoundSource( "wee" ); m_wee_sound = sfx_manager->createSoundSource( "wee" );
m_ugh_sound = sfx_manager->createSoundSource( "ugh" ); m_ugh_sound = sfx_manager->createSoundSource( "ugh" );
@ -365,17 +365,17 @@ void PlayerController::update(float dt)
// look backward when the player requests or // look backward when the player requests or
// if automatic reverse camera is active // if automatic reverse camera is active
if (m_kart->getCamera()->getMode() != Camera::CM_FINAL) if (m_camera->getMode() != Camera::CM_FINAL)
{ {
if (m_controls->m_look_back || (UserConfigParams::m_reverse_look_threshold>0 && if (m_controls->m_look_back || (UserConfigParams::m_reverse_look_threshold>0 &&
m_kart->getSpeed()<-UserConfigParams::m_reverse_look_threshold)) m_kart->getSpeed()<-UserConfigParams::m_reverse_look_threshold))
{ {
m_kart->getCamera()->setMode(Camera::CM_REVERSE); m_camera->setMode(Camera::CM_REVERSE);
} }
else else
{ {
if (m_kart->getCamera()->getMode() == Camera::CM_REVERSE) if (m_camera->getMode() == Camera::CM_REVERSE)
m_kart->getCamera()->setMode(Camera::CM_NORMAL); m_camera->setMode(Camera::CM_NORMAL);
} }
} }
@ -422,9 +422,12 @@ void PlayerController::setPosition(int p)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Called when a kart finishes race. /** Called when a kart finishes race.
* /param time Finishing time for this kart. * /param time Finishing time for this kart.
*/ d*/
void PlayerController::finishedRace(float time) void PlayerController::finishedRace(float time)
{ {
// This will implicitely trigger setting the first end camera to be active
m_camera->setMode(Camera::CM_FINAL);
} // finishedRace } // finishedRace
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -43,6 +43,10 @@ private:
float m_penalty_time; float m_penalty_time;
/** The camera attached to the kart for this controller. The camera
* object is managed in the Camera class, so no need to free it. */
Camera *m_camera;
SFXBase *m_bzzt_sound; SFXBase *m_bzzt_sound;
SFXBase *m_wee_sound; SFXBase *m_wee_sound;
SFXBase *m_ugh_sound; SFXBase *m_ugh_sound;
@ -62,20 +66,21 @@ public:
float previous_energy=0); float previous_energy=0);
virtual void skidBonusTriggered(); virtual void skidBonusTriggered();
virtual void setPosition (int p); virtual void setPosition (int p);
virtual void finishedRace (float time);
virtual bool isPlayerController() const {return true;} virtual bool isPlayerController() const {return true;}
virtual bool isNetworkController() const { return false; } virtual bool isNetworkController() const { return false; }
virtual void reset (); virtual void reset ();
void resetInputState (); void resetInputState ();
virtual void finishedRace (float time);
virtual void crashed (const AbstractKart *k) {} virtual void crashed (const AbstractKart *k) {}
virtual void crashed (const Material *m) {} virtual void crashed (const Material *m) {}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Callback whenever a new lap is triggered. Used by the AI
* to trigger a recomputation of the way to use, not used for players. */
virtual void newLap(int lap) {}
// ------------------------------------------------------------------------
/** Player will always be able to get a slipstream bonus. */ /** Player will always be able to get a slipstream bonus. */
virtual bool disableSlipstreamBonus() const { return false; } virtual bool disableSlipstreamBonus() const { return false; }
// ------------------------------------------------------------------------
/** Callback whenever a new lap is triggered. Used by the AI }; // PlayerController
* to trigger a recomputation of the way to use. */
virtual void newLap(int lap) {}
};
#endif #endif

View File

@ -114,9 +114,12 @@ ExplosionAnimation::~ExplosionAnimation()
{ {
m_kart->getBody()->setLinearVelocity(btVector3(0,0,0)); m_kart->getBody()->setLinearVelocity(btVector3(0,0,0));
m_kart->getBody()->setAngularVelocity(btVector3(0,0,0)); m_kart->getBody()->setAngularVelocity(btVector3(0,0,0));
if(m_kart->getCamera() && for(unsigned int i=0; i<Camera::getNumCameras(); i++)
m_kart->getCamera()->getMode() != Camera::CM_FINAL) {
m_kart->getCamera()->setMode(Camera::CM_NORMAL); Camera *camera = Camera::getCamera(i);
if(camera->getMode() != Camera::CM_FINAL)
camera->setMode(Camera::CM_NORMAL);
}
} }
} // ~KartAnimation } // ~KartAnimation

View File

@ -36,7 +36,6 @@
#include "graphics/particle_emitter.hpp" #include "graphics/particle_emitter.hpp"
#include "graphics/particle_kind.hpp" #include "graphics/particle_kind.hpp"
#include "graphics/particle_kind_manager.hpp" #include "graphics/particle_kind_manager.hpp"
#include "graphics/rain.hpp"
#include "graphics/shadow.hpp" #include "graphics/shadow.hpp"
#include "graphics/skid_marks.hpp" #include "graphics/skid_marks.hpp"
#include "graphics/slip_stream.hpp" #include "graphics/slip_stream.hpp"
@ -83,7 +82,6 @@
* \param ident The identifier for the kart model to use. * \param ident The identifier for the kart model to use.
* \param position The position (or rank) for this kart (between 1 and * \param position The position (or rank) for this kart (between 1 and
* number of karts). This is used to determine the start position. * number of karts). This is used to determine the start position.
* \param is_first_kart Indicates whether this is the first *player* kart
* \param init_transform The initial position and rotation for this kart. * \param init_transform The initial position and rotation for this kart.
*/ */
Kart::Kart (const std::string& ident, unsigned int world_kart_id, Kart::Kart (const std::string& ident, unsigned int world_kart_id,
@ -113,11 +111,9 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
m_collision_particles = NULL; m_collision_particles = NULL;
m_slipstream = NULL; m_slipstream = NULL;
m_skidmarks = NULL; m_skidmarks = NULL;
m_camera = NULL;
m_controller = NULL; m_controller = NULL;
m_saved_controller = NULL; m_saved_controller = NULL;
m_flying = false; m_flying = false;
m_rain = NULL;
m_sky_particles_emitter= NULL; m_sky_particles_emitter= NULL;
m_stars_effect = NULL; m_stars_effect = NULL;
@ -161,8 +157,9 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
/** This is a second initialisation phase, necessary since in the constructor /** This is a second initialisation phase, necessary since in the constructor
* virtual functions are not called for any superclasses. * virtual functions are not called for any superclasses.
* \param type Type of the kart.
*/ */
void Kart::init(RaceManager::KartType type, bool is_first_kart) void Kart::init(RaceManager::KartType type)
{ {
// In multiplayer mode, sounds are NOT positional // In multiplayer mode, sounds are NOT positional
if (race_manager->getNumLocalPlayers() > 1) if (race_manager->getNumLocalPlayers() > 1)
@ -201,7 +198,7 @@ void Kart::init(RaceManager::KartType type, bool is_first_kart)
{ {
animations = false; animations = false;
} }
loadData(type, is_first_kart, animations); loadData(type, animations);
m_kart_gfx = new KartGFX(this); m_kart_gfx = new KartGFX(this);
m_skidding = new Skidding(this, m_skidding = new Skidding(this,
@ -242,7 +239,6 @@ Kart::~Kart()
if(m_previous_terrain_sound) sfx_manager->deleteSFX(m_previous_terrain_sound); if(m_previous_terrain_sound) sfx_manager->deleteSFX(m_previous_terrain_sound);
if(m_collision_particles) delete m_collision_particles; if(m_collision_particles) delete m_collision_particles;
if(m_slipstream) delete m_slipstream; if(m_slipstream) delete m_slipstream;
if(m_rain) delete m_rain;
if(m_sky_particles_emitter) delete m_sky_particles_emitter; if(m_sky_particles_emitter) delete m_sky_particles_emitter;
if(m_attachment) delete m_attachment; if(m_attachment) delete m_attachment;
if (m_stars_effect) delete m_stars_effect; if (m_stars_effect) delete m_stars_effect;
@ -273,7 +269,6 @@ Kart::~Kart()
delete m_controller; delete m_controller;
if(m_saved_controller) if(m_saved_controller)
delete m_saved_controller; delete m_saved_controller;
if (m_camera) delete m_camera;
} // ~Kart } // ~Kart
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -299,12 +294,6 @@ void Kart::reset()
m_max_speed->reset(); m_max_speed->reset();
m_powerup->reset(); m_powerup->reset();
if (m_camera)
{
m_camera->reset();
m_camera->setInitialTransform();
}
// Reset animations and wheels // Reset animations and wheels
m_kart_model->reset(); m_kart_model->reset();
@ -800,9 +789,6 @@ void Kart::finishedRace(float time)
else else
m_kart_model->setAnimation(KartModel::AF_LOSE_START); m_kart_model->setAnimation(KartModel::AF_LOSE_START);
// Not all karts have a camera
if (m_camera) m_camera->setMode(Camera::CM_FINAL);
RaceGUIBase* m = World::getWorld()->getRaceGUI(); RaceGUIBase* m = World::getWorld()->getRaceGUI();
if(m) if(m)
{ {
@ -820,9 +806,6 @@ void Kart::finishedRace(float time)
else if(m_race_position>=0.7f*race_manager->getNumberOfKarts()) else if(m_race_position>=0.7f*race_manager->getNumberOfKarts())
m_kart_model->setAnimation(KartModel::AF_LOSE_START); m_kart_model->setAnimation(KartModel::AF_LOSE_START);
// Not all karts have a camera
if (m_camera) m_camera->setMode(Camera::CM_REVERSE);
RaceGUIBase* m = World::getWorld()->getRaceGUI(); RaceGUIBase* m = World::getWorld()->getRaceGUI();
if(m) if(m)
{ {
@ -1015,8 +998,6 @@ void Kart::update(float dt)
if(!history->replayHistory()) if(!history->replayHistory())
m_controller->update(dt); m_controller->update(dt);
if(m_camera)
m_camera->update(dt);
// if its view is blocked by plunger, decrease remaining time // if its view is blocked by plunger, decrease remaining time
if(m_view_blocked_by_plunger > 0) m_view_blocked_by_plunger -= dt; if(m_view_blocked_by_plunger > 0) m_view_blocked_by_plunger -= dt;
@ -1082,16 +1063,6 @@ void Kart::update(float dt)
m_attachment->update(dt); m_attachment->update(dt);
//smoke drawing control point
if (UserConfigParams::m_graphical_effects)
{
if (m_rain)
{
m_rain->setPosition( getCamera()->getCameraSceneNode()->getPosition() );
m_rain->update(dt);
}
} // UserConfigParams::m_graphical_effects
m_kart_gfx->update(dt); m_kart_gfx->update(dt);
if (m_collision_particles) m_collision_particles->update(dt); if (m_collision_particles) m_collision_particles->update(dt);
@ -1377,17 +1348,22 @@ void Kart::handleMaterialGFX()
// has the 'below surface' flag set. Detect if there is a surface // has the 'below surface' flag set. Detect if there is a surface
// on top of the kart. // on top of the kart.
// -------------------------------------------------------------- // --------------------------------------------------------------
if (m_camera && m_camera->getMode() != Camera::CM_FINAL) if (m_controller->isPlayerController() && !hasFinishedRace())
{ {
for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{
Camera *camera = Camera::getCamera(i);
if (material && material->hasFallingEffect() && !m_flying) if (material && material->hasFallingEffect() && !m_flying)
{ {
m_camera->setMode(Camera::CM_FALLING); Camera::getCamera(i)->setMode(Camera::CM_FALLING);
} }
else if (m_camera->getMode() != Camera::CM_NORMAL && else if (camera->getMode() != Camera::CM_NORMAL &&
m_camera->getMode() != Camera::CM_REVERSE) camera->getMode() != Camera::CM_REVERSE)
{ {
m_camera->setMode(Camera::CM_NORMAL); camera->setMode(Camera::CM_NORMAL);
} }
} // for i in all cameras for this kart
} // camera != final camera } // camera != final camera
if (!UserConfigParams::m_graphical_effects) if (!UserConfigParams::m_graphical_effects)
@ -1444,30 +1420,6 @@ void Kart::handleMaterialGFX()
} // handleMaterialGFX } // handleMaterialGFX
//-----------------------------------------------------------------------------
/** Sets or reset the camera attached to a kart. In profile mode even AI karts
* can have a camera attached.
* \params camera The camera to attach to this kart (or NULL if no camera
* is to be used
*/
void Kart::setCamera(Camera *camera)
{
m_camera = camera;
if(!camera)
return;
#ifdef DEBUG
m_camera->getCameraSceneNode()
->setName((getIdent() + "'s camera").c_str());
#endif
// Handle camera-specific nodes for now if in multiplayer
if (m_rain && race_manager->getNumLocalPlayers() > 1)
{
m_rain->setCamera( camera->getCameraSceneNode() );
}
} // setCamera
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Sets zipper time, and apply one time additional speed boost. It can be /** Sets zipper time, and apply one time additional speed boost. It can be
* used with a specific material, in which case the zipper parmaters are * used with a specific material, in which case the zipper parmaters are
@ -2149,9 +2101,10 @@ void Kart::updateFlying()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Attaches the right model, creates the physics and loads all special /** Attaches the right model, creates the physics and loads all special
* effects (particle systems etc.) * effects (particle systems etc.)
* \param type Type of the kart.
* \param is_animated_model True if the model is animated.
*/ */
void Kart::loadData(RaceManager::KartType type, bool is_first_kart, void Kart::loadData(RaceManager::KartType type, bool is_animated_model)
bool is_animated_model)
{ {
m_node = m_kart_model->attachModel(is_animated_model); m_node = m_kart_model->attachModel(is_animated_model);
@ -2186,13 +2139,6 @@ void Kart::loadData(RaceManager::KartType type, bool is_first_kart,
m_sky_particles_emitter->addHeightMapAffector(track); m_sky_particles_emitter->addHeightMapAffector(track);
} }
if (UserConfigParams::m_weather_effects && track->getWeatherType() == WEATHER_RAIN &&
type == RaceManager::KT_PLAYER)
{
// camera not yet available at this point
m_rain = new Rain(NULL, NULL, is_first_kart);
}
Vec3 position(0, getKartHeight()*0.35f, -getKartLength()*0.35f); Vec3 position(0, getKartHeight()*0.35f, -getKartLength()*0.35f);
m_slipstream = new SlipStream(this); m_slipstream = new SlipStream(this);

View File

@ -38,7 +38,6 @@ class btKart;
class btUprightConstraint; class btUprightConstraint;
class Attachment; class Attachment;
class Camera;
class Controller; class Controller;
class Item; class Item;
class AbstractKartAnimation; class AbstractKartAnimation;
@ -46,7 +45,6 @@ class KartGFX;
class MaxSpeed; class MaxSpeed;
class ParticleEmitter; class ParticleEmitter;
class ParticleKind; class ParticleKind;
class Rain;
class SFXBase; class SFXBase;
class Shadow; class Shadow;
class Skidding; class Skidding;
@ -110,14 +108,6 @@ private:
/** For stars rotating around head effect */ /** For stars rotating around head effect */
Stars *m_stars_effect; Stars *m_stars_effect;
protected: // Used by the AI atm
/** The camera for each kart. Not all karts have cameras (e.g. AI karts
* usually don't), but there are exceptions: e.g. after the end of a
* race an AI kart is replacing the kart for a player.
*/
Camera *m_camera;
private: private:
/** True if the kart hasn't moved since 'ready-set-go' - used to /** True if the kart hasn't moved since 'ready-set-go' - used to
* determine startup boost. */ * determine startup boost. */
@ -174,8 +164,6 @@ private:
/** Handles all slipstreaming. */ /** Handles all slipstreaming. */
SlipStream *m_slipstream; SlipStream *m_slipstream;
Rain *m_rain;
/** Rotation compared to the start position, same for all wheels */ /** Rotation compared to the start position, same for all wheels */
float m_wheel_rotation; float m_wheel_rotation;
@ -221,14 +209,13 @@ private:
void updateNitro(float dt); void updateNitro(float dt);
float getActualWheelForce(); float getActualWheelForce();
void crashed(); void crashed();
void loadData(RaceManager::KartType type, bool is_first_kart, void loadData(RaceManager::KartType type, bool animatedModel);
bool animatedModel);
public: public:
Kart(const std::string& ident, unsigned int world_kart_id, Kart(const std::string& ident, unsigned int world_kart_id,
int position, const btTransform& init_transform); int position, const btTransform& init_transform);
virtual ~Kart(); virtual ~Kart();
virtual void init(RaceManager::KartType type, bool is_first_kart); virtual void init(RaceManager::KartType type);
virtual void updateGraphics(float dt, const Vec3& off_xyz, virtual void updateGraphics(float dt, const Vec3& off_xyz,
const btQuaternion& off_rotation); const btQuaternion& off_rotation);
virtual void createPhysics (); virtual void createPhysics ();
@ -290,18 +277,6 @@ public:
/** Returns a points to this kart's graphical effects. */ /** Returns a points to this kart's graphical effects. */
KartGFX* getKartGFX() { return m_kart_gfx; } KartGFX* getKartGFX() { return m_kart_gfx; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the camera of this kart (or NULL if no camera is attached
* to this kart). */
virtual Camera* getCamera () {return m_camera;}
// ------------------------------------------------------------------------
/** Returns the camera of this kart (or NULL if no camera is attached
* to this kart) - const version. */
virtual const Camera* getCamera () const {return m_camera;}
// ------------------------------------------------------------------------
/** Sets the camera for this kart. Takes ownership of the camera and
* will delete it. */
virtual void setCamera(Camera *camera);
// ------------------------------------------------------------------------
/** Returns the remaining collected energy. */ /** Returns the remaining collected energy. */
virtual float getEnergy () const { return m_collected_energy; } virtual float getEnergy () const { return m_collected_energy; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -77,9 +77,13 @@ RescueAnimation::~RescueAnimation()
m_kart->getBody()->setLinearVelocity(btVector3(0,0,0)); m_kart->getBody()->setLinearVelocity(btVector3(0,0,0));
m_kart->getBody()->setAngularVelocity(btVector3(0,0,0)); m_kart->getBody()->setAngularVelocity(btVector3(0,0,0));
World::getWorld()->getPhysics()->addKart(m_kart); World::getWorld()->getPhysics()->addKart(m_kart);
if (m_kart->getCamera() && for(unsigned int i=0; i<Camera::getNumCameras(); i++)
m_kart->getCamera()->getMode() != Camera::CM_FINAL) {
m_kart->getCamera()->setMode(Camera::CM_NORMAL); Camera *camera = Camera::getCamera(i);
if(camera && camera->getKart()==m_kart &&
camera->getMode() != Camera::CM_FINAL)
camera->setMode(Camera::CM_NORMAL);
}
} }
} // ~RescueAnimation } // ~RescueAnimation

View File

@ -125,7 +125,19 @@ void FollowTheLeaderRace::countdownReachedZero()
} }
// Time doesn't make any sense in FTL (and it is not displayed) // Time doesn't make any sense in FTL (and it is not displayed)
kart->finishedRace(-1.0f); kart->finishedRace(-1.0f);
// Move any camera for this kart to the leader, facing backwards,
// so that the eliminated player has something to watch.
for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{
Camera *camera = Camera::getCamera(i);
if(camera->getKart()==kart)
{
camera->setMode(Camera::CM_LEADER_MODE);
camera->setKart(getKart(0));
} }
} // for i<number of cameras
} // if kart to eliminate exists
// almost over, use fast music // almost over, use fast music
if(getCurrentNumKarts()==3) if(getCurrentNumKarts()==3)

View File

@ -110,7 +110,7 @@ AbstractKart *ProfileWorld::createKart(const std::string &kart_ident, int index,
/*world kart id*/ index, /*world kart id*/ index,
/*position*/ index+1, /*position*/ index+1,
init_pos); init_pos);
new_kart->init(RaceManager::KT_AI, /*is_first_kart*/false); new_kart->init(RaceManager::KT_AI);
Controller *controller = loadAIController(new_kart); Controller *controller = loadAIController(new_kart);
new_kart->setController(controller); new_kart->setController(controller);
@ -118,7 +118,8 @@ AbstractKart *ProfileWorld::createKart(const std::string &kart_ident, int index,
// karts can be seen. // karts can be seen.
if (index == (int)race_manager->getNumberOfKarts()-1) if (index == (int)race_manager->getNumberOfKarts()-1)
{ {
new_kart->setCamera(new Camera(index, new_kart)); // The camera keeps track of all cameras and will free them
Camera::createCamera(new_kart);
} }
return new_kart; return new_kart;
} // createKart } // createKart

View File

@ -151,6 +151,35 @@ void ThreeStrikesBattle::kartHit(const int kart_id)
if(wheels[2]) wheels[2]->setVisible(false); if(wheels[2]) wheels[2]->setVisible(false);
if(wheels[3]) wheels[3]->setVisible(false); if(wheels[3]) wheels[3]->setVisible(false);
eliminateKart(kart_id, /*notify_of_elimination*/ true); eliminateKart(kart_id, /*notify_of_elimination*/ true);
// Find a camera of the kart with the most lives ("leader"), and
// attach all cameras for this kart to the leader.
int max_lives = 0;
AbstractKart *leader = NULL;
for(unsigned int i=0; i<getNumKarts(); i++)
{
AbstractKart * const kart = getKart(i);
if(kart->isEliminated() || kart->hasFinishedRace() ||
kart->getWorldKartId()==kart_id) continue;
if(m_kart_info[i].m_lives > max_lives)
{
leader = kart;
max_lives = m_kart_info[i].m_lives;
}
}
// leader could be 0 if the last two karts hit each other in
// the same frame
if(leader)
{
for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{
Camera *camera = Camera::getCamera(i);
if(camera->getKart()->getWorldKartId()==kart_id)
{
camera->setMode(Camera::CM_NORMAL);
camera->setKart(leader);
}
} // for in < number of cameras
} // if leader
m_insert_tire = 4; m_insert_tire = 4;
} }

View File

@ -211,7 +211,7 @@ AbstractKart *World::createKart(const std::string &kart_ident, int index,
int position = index+1; int position = index+1;
btTransform init_pos = m_track->getStartTransform(index); btTransform init_pos = m_track->getStartTransform(index);
AbstractKart *new_kart = new Kart(kart_ident, index, position, init_pos); AbstractKart *new_kart = new Kart(kart_ident, index, position, init_pos);
new_kart->init(race_manager->getKartType(index), (local_player_id == 0)); new_kart->init(race_manager->getKartType(index));
Controller *controller = NULL; Controller *controller = NULL;
switch(kart_type) switch(kart_type)
{ {
@ -303,6 +303,8 @@ World::~World()
delete m_karts[i]; delete m_karts[i];
m_karts.clear(); m_karts.clear();
Camera::removeAllCameras();
projectile_manager->cleanup(); projectile_manager->cleanup();
// In case that the track is not found, m_physics is still undefined. // In case that the track is not found, m_physics is still undefined.
if(m_physics) if(m_physics)
@ -553,14 +555,16 @@ void World::resetAllKarts()
// Now store the current (i.e. in rest) suspension length for each // Now store the current (i.e. in rest) suspension length for each
// kart, so that the karts can visualise the suspension. // kart, so that the karts can visualise the suspension.
(*i)->setSuspensionLength(); (*i)->setSuspensionLength();
// Initialise the camera (if available), now that the correct
// kart position is set
if((*i)->getCamera())
(*i)->getCamera()->setInitialTransform();
// Update the kart transforms with the newly computed position // Update the kart transforms with the newly computed position
// after all karts are reset // after all karts are reset
(*i)->setTrans((*i)->getBody()->getWorldTransform()); (*i)->setTrans((*i)->getBody()->getWorldTransform());
} }
// Initialise the cameras, now that the correct kart positions are set
for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{
Camera::getCamera(i)->setInitialTransform();
}
} // resetAllKarts } // resetAllKarts
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -723,6 +727,11 @@ void World::update(float dt)
if(!m_karts[i]->isEliminated()) m_karts[i]->update(dt) ; if(!m_karts[i]->isEliminated()) m_karts[i]->update(dt) ;
} }
for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{
Camera::getCamera(i)->update(dt);
}
projectile_manager->update(dt); projectile_manager->update(dt);
PROFILER_POP_CPU_MARKER(); PROFILER_POP_CPU_MARKER();
@ -881,53 +890,43 @@ AbstractKart *World::getPlayerKart(unsigned int n) const
*/ */
AbstractKart *World::getLocalPlayerKart(unsigned int n) const AbstractKart *World::getLocalPlayerKart(unsigned int n) const
{ {
int count=-1; if(n>=Camera::getNumCameras()) return NULL;
const int kart_count = m_karts.size(); return Camera::getCamera(n)->getKart();
for(int i=0; i<kart_count; i++)
{
if(m_karts[i]->getCamera() &&
(m_karts[i]->getController()->isPlayerController() ||
ProfileWorld::isProfileMode() ) )
{
count++;
if(count == (int)n) return m_karts[i];
}
}
return NULL;
} // getLocalPlayerKart } // getLocalPlayerKart
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Remove (eliminate) a kart from the race */ /** Remove (eliminate) a kart from the race */
void World::eliminateKart(int kart_number, bool notify_of_elimination) void World::eliminateKart(int kart_id, bool notify_of_elimination)
{ {
AbstractKart *kart = m_karts[kart_number]; AbstractKart *kart = m_karts[kart_id];
// Display a message about the eliminated kart in the race gui // Display a message about the eliminated kart in the race guia
if (notify_of_elimination) if (notify_of_elimination)
{ {
for (KartList::iterator i = m_karts.begin(); i != m_karts.end(); i++ ) for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{ {
if(!(*i)->getCamera()) continue; Camera *camera = Camera::getCamera(i);
if(*i==kart) if(camera->getKart()==kart)
{ m_race_gui->addMessage(_("You have been eliminated!"), kart,
m_race_gui->addMessage(_("You have been eliminated!"), *i,
2.0f); 2.0f);
}
else else
{
m_race_gui->addMessage(_("'%s' has been eliminated.", m_race_gui->addMessage(_("'%s' has been eliminated.",
core::stringw(kart->getName())), *i, core::stringw(kart->getName())),
camera->getKart(),
2.0f); 2.0f);
} } // for i < number of cameras
} // for i in kart } // if notify_of_elimination
}
if(kart->getController()->isPlayerController()) if(kart->getController()->isPlayerController())
{
for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{ {
// Change the camera so that it will be attached to the leader // Change the camera so that it will be attached to the leader
// and facing backwards. // and facing backwards.
Camera* camera=kart->getCamera(); Camera *camera = Camera::getCamera(i);
if(camera->getKart()==kart)
camera->setMode(Camera::CM_LEADER_MODE); camera->setMode(Camera::CM_LEADER_MODE);
}
m_eliminated_players++; m_eliminated_players++;
} }
@ -981,6 +980,12 @@ void World::restartRace()
{ {
(*i)->reset(); (*i)->reset();
} }
for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{
Camera::getCamera(i)->reset();
}
if(ReplayPlay::get()) if(ReplayPlay::get())
ReplayPlay::get()->reset(); ReplayPlay::get()->reset();
resetAllKarts(); resetAllKarts();

View File

@ -182,8 +182,7 @@ void ReplayPlay::readKartData(FILE *fd, char *next_line)
exit(-2); exit(-2);
} }
m_ghost_karts.push_back(new GhostKart(std::string(s))); m_ghost_karts.push_back(new GhostKart(std::string(s)));
m_ghost_karts[m_ghost_karts.size()-1].init(RaceManager::KT_GHOST, m_ghost_karts[m_ghost_karts.size()-1].init(RaceManager::KT_GHOST);
/*is_first_kart*/false);
fgets(s, 1023, fd); fgets(s, 1023, fd);
unsigned int size; unsigned int size;

View File

@ -198,16 +198,19 @@ void MinimalRaceGUI::renderGlobal(float dt)
* collectibles, ... * collectibles, ...
* \param kart Pointer to the kart for which to render the view. * \param kart Pointer to the kart for which to render the view.
*/ */
void MinimalRaceGUI::renderPlayerView(const AbstractKart *kart, float dt) void MinimalRaceGUI::renderPlayerView(const Camera *camera, float dt)
{ {
if (!m_enabled) return; if (!m_enabled) return;
const core::recti &viewport = kart->getCamera()->getViewport(); const core::recti &viewport = camera->getViewport();
core::vector2df scaling = kart->getCamera()->getScaling(); core::vector2df scaling = camera->getScaling();
scaling *= viewport.getWidth()/800.0f; // scale race GUI along screen size scaling *= viewport.getWidth()/800.0f; // scale race GUI along screen size
drawPlungerInFace(kart, dt); const AbstractKart *kart = camera->getKart();
if(!kart) return;
drawPlungerInFace(camera, dt);
drawAllMessages (kart, viewport, scaling); drawAllMessages (kart, viewport, scaling);
if(!World::getWorld()->isRacePhase()) return; if(!World::getWorld()->isRacePhase()) return;
@ -215,7 +218,7 @@ void MinimalRaceGUI::renderPlayerView(const AbstractKart *kart, float dt)
drawEnergyMeter (kart, viewport, scaling); drawEnergyMeter (kart, viewport, scaling);
drawRankLap (kart, viewport); drawRankLap (kart, viewport);
RaceGUIBase::renderPlayerView(kart, dt); RaceGUIBase::renderPlayerView(camera, dt);
} // renderPlayerView } // renderPlayerView
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -118,7 +118,7 @@ public:
MinimalRaceGUI(); MinimalRaceGUI();
~MinimalRaceGUI(); ~MinimalRaceGUI();
virtual void renderGlobal(float dt); virtual void renderGlobal(float dt);
virtual void renderPlayerView(const AbstractKart *kart, float dt); virtual void renderPlayerView(const Camera *camera, float dt);
/** Returns the size of the texture on which to render the minimap to. */ /** Returns the size of the texture on which to render the minimap to. */
virtual const core::dimension2du getMiniMapSize() const virtual const core::dimension2du getMiniMapSize() const

View File

@ -184,15 +184,17 @@ void RaceGUI::renderGlobal(float dt)
* collectibles, ... * collectibles, ...
* \param kart Pointer to the kart for which to render the view. * \param kart Pointer to the kart for which to render the view.
*/ */
void RaceGUI::renderPlayerView(const AbstractKart *kart, float dt) void RaceGUI::renderPlayerView(const Camera *camera, float dt)
{ {
if (!m_enabled) return; if (!m_enabled) return;
const core::recti &viewport = kart->getCamera()->getViewport(); const core::recti &viewport = camera->getViewport();
core::vector2df scaling = kart->getCamera()->getScaling(); core::vector2df scaling = camera->getScaling();
const AbstractKart *kart = camera->getKart();
if(!kart) return;
drawPlungerInFace(kart, dt); drawPlungerInFace(camera, dt);
scaling *= viewport.getWidth()/800.0f; // scale race GUI along screen size scaling *= viewport.getWidth()/800.0f; // scale race GUI along screen size
drawAllMessages (kart, viewport, scaling); drawAllMessages (kart, viewport, scaling);
@ -205,7 +207,7 @@ void RaceGUI::renderPlayerView(const AbstractKart *kart, float dt)
if (!m_is_tutorial) if (!m_is_tutorial)
drawRankLap (kart, viewport); drawRankLap (kart, viewport);
RaceGUIBase::renderPlayerView(kart, dt); RaceGUIBase::renderPlayerView(camera, dt);
} // renderPlayerView } // renderPlayerView
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -111,7 +111,7 @@ public:
RaceGUI(); RaceGUI();
~RaceGUI(); ~RaceGUI();
virtual void renderGlobal(float dt); virtual void renderGlobal(float dt);
virtual void renderPlayerView(const AbstractKart *kart, float dt); virtual void renderPlayerView(const Camera *camera, float dt);
/** Returns the size of the texture on which to render the minimap to. */ /** Returns the size of the texture on which to render the minimap to. */
virtual const core::dimension2du getMiniMapSize() const virtual const core::dimension2du getMiniMapSize() const

View File

@ -474,21 +474,22 @@ void RaceGUIBase::update(float dt)
* is used here to display the referee during the ready-set-go phase. * is used here to display the referee during the ready-set-go phase.
* \param kart The kart whose view is rendered next. * \param kart The kart whose view is rendered next.
*/ */
void RaceGUIBase::preRenderCallback(const AbstractKart &kart) void RaceGUIBase::preRenderCallback(const Camera *camera)
{ {
if(m_referee) if(m_referee && camera->getKart())
{ {
Vec3 xyz = m_referee_pos[kart.getWorldKartId()]; unsigned int world_id = camera->getKart()->getWorldKartId();
Vec3 xyz = m_referee_pos[world_id];
xyz.setY(xyz.getY()+m_referee_height); xyz.setY(xyz.getY()+m_referee_height);
m_referee->setPosition(xyz); m_referee->setPosition(xyz);
m_referee->setRotation(m_referee_rotation[kart.getWorldKartId()]); m_referee->setRotation(m_referee_rotation[world_id]);
} }
} // preRenderCallback } // preRenderCallback
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void RaceGUIBase::renderPlayerView(const AbstractKart *kart, float dt) void RaceGUIBase::renderPlayerView(const Camera *camera, float dt)
{ {
const core::recti &viewport = kart->getCamera()->getViewport(); const core::recti &viewport = camera->getViewport();
if (m_lightning > 0.0f) if (m_lightning > 0.0f)
{ {
@ -1030,15 +1031,16 @@ void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin)
/** Draws the plunger-in-face if necessary. Does nothing if there is no /** Draws the plunger-in-face if necessary. Does nothing if there is no
* plunger in face atm. * plunger in face atm.
*/ */
void RaceGUIBase::drawPlungerInFace(const AbstractKart *kart, float dt) void RaceGUIBase::drawPlungerInFace(const Camera *camera, float dt)
{ {
const AbstractKart *kart = camera->getKart();
if (kart->getBlockedByPlungerTime()<=0) if (kart->getBlockedByPlungerTime()<=0)
{ {
m_plunger_state = PLUNGER_STATE_INIT; m_plunger_state = PLUNGER_STATE_INIT;
return; return;
} }
const core::recti &viewport = kart->getCamera()->getViewport(); const core::recti &viewport = camera->getViewport();
const int screen_width = viewport.LowerRightCorner.X const int screen_width = viewport.LowerRightCorner.X
- viewport.UpperLeftCorner.X; - viewport.UpperLeftCorner.X;

View File

@ -36,6 +36,7 @@ using namespace irr;
#include "utils/vec3.hpp" #include "utils/vec3.hpp"
class AbstractKart; class AbstractKart;
class Camera;
class Material; class Material;
class Referee; class Referee;
@ -194,7 +195,7 @@ protected:
const core::vector2df &scaling); const core::vector2df &scaling);
void drawGlobalMusicDescription(); void drawGlobalMusicDescription();
void drawGlobalReadySetGo (); void drawGlobalReadySetGo ();
void drawPlungerInFace(const AbstractKart *kart, float dt); void drawPlungerInFace(const Camera *camera, float dt);
/** Instructs the base gui to ignore unimportant messages (like /** Instructs the base gui to ignore unimportant messages (like
* item messages). * item messages).
*/ */
@ -220,7 +221,7 @@ public:
virtual void renderGlobal(float dt); virtual void renderGlobal(float dt);
virtual void init(); virtual void init();
virtual void restartRace(); virtual void restartRace();
virtual void renderPlayerView(const AbstractKart *kart, float dt); virtual void renderPlayerView(const Camera *camera, float dt);
virtual void addMessage(const irr::core::stringw &m, virtual void addMessage(const irr::core::stringw &m,
const AbstractKart *kart, float time, const AbstractKart *kart, float time,
const video::SColor &color= const video::SColor &color=
@ -228,7 +229,7 @@ public:
bool important=true, bool important=true,
bool big_font=false); bool big_font=false);
virtual void update(float dt); virtual void update(float dt);
virtual void preRenderCallback(const AbstractKart &kart); virtual void preRenderCallback(const Camera *camera);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the size of the texture on which to render the minimap to. */ /** Returns the size of the texture on which to render the minimap to. */
virtual const core::dimension2du virtual const core::dimension2du

View File

@ -178,13 +178,14 @@ void RaceGUIOverworld::renderGlobal(float dt)
* collectibles, ... * collectibles, ...
* \param kart Pointer to the kart for which to render the view. * \param kart Pointer to the kart for which to render the view.
*/ */
void RaceGUIOverworld::renderPlayerView(const AbstractKart *kart, float dt) void RaceGUIOverworld::renderPlayerView(const Camera *camera, float dt)
{ {
if (!m_enabled) return; if (!m_enabled) return;
const AbstractKart *kart = camera->getKart();
if(!kart) return;
const core::recti &viewport = kart->getCamera()->getViewport(); const core::recti &viewport = camera->getViewport();
core::vector2df scaling = camera->getScaling();
core::vector2df scaling = kart->getCamera()->getScaling();
//std::cout << "Applied ratio : " << viewport.getWidth()/800.0f << std::endl; //std::cout << "Applied ratio : " << viewport.getWidth()/800.0f << std::endl;
scaling *= viewport.getWidth()/800.0f; // scale race GUI along screen size scaling *= viewport.getWidth()/800.0f; // scale race GUI along screen size
@ -197,7 +198,7 @@ void RaceGUIOverworld::renderPlayerView(const AbstractKart *kart, float dt)
drawPowerupIcons (kart, viewport, scaling); drawPowerupIcons (kart, viewport, scaling);
RaceGUIBase::renderPlayerView(kart, dt); RaceGUIBase::renderPlayerView(camera, dt);
} // renderPlayerView } // renderPlayerView
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -120,7 +120,7 @@ public:
RaceGUIOverworld(); RaceGUIOverworld();
~RaceGUIOverworld(); ~RaceGUIOverworld();
virtual void renderGlobal(float dt); virtual void renderGlobal(float dt);
virtual void renderPlayerView(const AbstractKart *kart, float dt); virtual void renderPlayerView(const Camera *camera, float dt);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the currently selected challenge data (or NULL if no is /** Returns the currently selected challenge data (or NULL if no is

View File

@ -48,10 +48,11 @@ void AmbientLightSphere::update(float dt)
CheckStructure::update(dt); CheckStructure::update(dt);
World *world = World::getWorld(); World *world = World::getWorld();
for(unsigned int i=0; i<world->getNumKarts(); i++) for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{ {
AbstractKart *kart=world->getKart(i); Camera *camera = Camera::getCamera(i);
if(!kart->getCamera()) continue; const AbstractKart *kart=camera->getKart();
if(!kart) continue;
if(isInside(i)) if(isInside(i))
{ {
float d2=getDistance2ForKart(i); float d2=getDistance2ForKart(i);
@ -67,7 +68,7 @@ void AmbientLightSphere::update(float dt)
const video::SColor &def = track->getDefaultAmbientColor(); const video::SColor &def = track->getDefaultAmbientColor();
color = m_ambient_color.getInterpolated(def, f); color = m_ambient_color.getInterpolated(def, f);
} }
kart->getCamera()->setAmbientLight(color); camera->setAmbientLight(color);
} // if active } // if active
} // for i<num_karts } // for i<num_karts
} // update } // update
@ -83,6 +84,10 @@ void AmbientLightSphere::update(float dt)
bool AmbientLightSphere::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, bool AmbientLightSphere::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
int indx) int indx)
{ {
if(!World::getWorld()->getKart(indx)->getCamera()) return false; for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{
if(Camera::getCamera(i)->getKart()->getWorldKartId()==indx)
return CheckSphere::isTriggered(old_pos, new_pos, indx); return CheckSphere::isTriggered(old_pos, new_pos, indx);
}
return false;
} // isTriggered } // isTriggered

View File

@ -22,7 +22,6 @@
#include "utils/vec3.hpp" #include "utils/vec3.hpp"
class Track; class Track;
class Kart;
/** This object keeps track of which sector an object is on. A sector is /** This object keeps track of which sector an object is on. A sector is
* actually just the graph node (it's called sector to better distinguish * actually just the graph node (it's called sector to better distinguish