Merge branch 'master' of github.com:supertuxkart/stk-code

This commit is contained in:
hiker
2017-08-30 17:49:59 +10:00
34 changed files with 805 additions and 377 deletions

View File

@@ -44,7 +44,8 @@ and extract it to stk-code/lib. It contains sources of libraries that are used
in STK, but are not availiable in stk-code repository (curl, freetype, openal).
You need also Android SDK for android-19 platform (the API for Android 4.4) and
Android NDK r12b.
Android NDK. Note that NDK >= r15b is atm. not supported. Version r12b is
strongly recommended, because it's known that it works without issues.
You need to create proper "android-sdk" and "android-ndk" symlinks in the
directory with Android project, so that the compilation script will have access

File diff suppressed because it is too large Load Diff

View File

@@ -83,12 +83,12 @@ VAOManager::~VAOManager()
}
static void
resizeBufferIfNecessary(size_t &lastIndex, size_t newLastIndex, size_t bufferSize, size_t stride, GLenum type, GLuint &id, void *&Pointer)
resizeBufferIfNecessary(size_t &lastIndex, size_t newLastIndex, size_t& bufferSize, size_t stride, GLenum type, GLuint &id, void *&Pointer)
{
if (newLastIndex * stride >= bufferSize)
if (newLastIndex >= bufferSize)
{
while (newLastIndex >= bufferSize)
bufferSize = 2 * bufferSize + 1;
bufferSize = bufferSize == 0 ? 1 : bufferSize * 2;
GLuint newVBO;
glGenBuffers(1, &newVBO);
glBindBuffer(type, newVBO);

View File

@@ -43,14 +43,7 @@ MultitouchDevice::MultitouchDevice()
assert(m_android_device != NULL);
#endif
for (MultitouchEvent& event : m_events)
{
event.id = 0;
event.touched = false;
event.x = 0;
event.y = 0;
}
reset();
updateConfigParams();
} // MultitouchDevice
@@ -183,6 +176,28 @@ void MultitouchDevice::clearButtons()
m_buttons.clear();
} // clearButtons
// ----------------------------------------------------------------------------
/** Sets all buttons and events to default state
*/
void MultitouchDevice::reset()
{
for (MultitouchButton* button : m_buttons)
{
button->pressed = false;
button->event_id = 0;
button->axis_x = 0.0f;
button->axis_y = 0.0f;
}
for (MultitouchEvent& event : m_events)
{
event.id = 0;
event.touched = false;
event.x = 0;
event.y = 0;
}
} // reset
// ----------------------------------------------------------------------------
/** The function that is executed when touch event occurs. It updates the
* buttons state when it's needed.

View File

@@ -111,6 +111,7 @@ public:
void addButton(MultitouchButtonType type, int x, int y, int width,
int height);
void clearButtons();
void reset();
/** Returns the number of created buttons */
unsigned int getButtonsCount() {return m_buttons.size();}

View File

@@ -67,13 +67,14 @@ Flyable::Flyable(AbstractKart *kart, PowerupManager::PowerupType type,
m_type = type;
m_has_hit_something = false;
m_shape = NULL;
m_animation = NULL;
m_mass = mass;
m_adjust_up_velocity = true;
m_time_since_thrown = 0;
m_position_offset = Vec3(0,0,0);
m_owner_has_temporary_immunity = true;
m_do_terrain_info = true;
m_max_lifespan = -1;
m_max_lifespan = -1;
// Add the graphical model
#ifndef SERVER_ONLY
@@ -353,6 +354,24 @@ void Flyable::getLinearKartItemIntersection (const Vec3 &origin,
+ ( target_y_speed);
} // getLinearKartItemIntersection
//-----------------------------------------------------------------------------
void Flyable::setAnimation(AbstractKartAnimation *animation)
{
if (animation)
{
assert(m_animation == NULL);
Physics::getInstance()->removeBody(m_body);
}
else // animation = NULL
{
assert(m_animation != NULL);
m_body->setWorldTransform(getTrans());
Physics::getInstance()->addBody(m_body);
}
m_animation = animation;
} // addAnimation
//-----------------------------------------------------------------------------
/** Updates this flyable. It calls Moveable::update. If this function returns
* true, the flyable will be deleted by the projectile manager.
@@ -361,6 +380,13 @@ void Flyable::getLinearKartItemIntersection (const Vec3 &origin,
*/
bool Flyable::updateAndDelete(float dt)
{
if (hasAnimation())
{
m_animation->update(dt);
Moveable::update(dt);
return false;
} // if animation
m_time_since_thrown += dt;
if(m_max_lifespan > -1 && m_time_since_thrown > m_max_lifespan)
hit(NULL);

View File

@@ -34,6 +34,7 @@ using namespace irr;
#include "tracks/terrain_info.hpp"
class AbstractKart;
class AbstractKartAnimation;
class HitEffect;
class PhysicalObject;
class XMLNode;
@@ -64,6 +65,11 @@ private:
* terrain yourself (e.g. order of operations is important)
* set this to false with a call do setDoTerrainInfo(). */
bool m_do_terrain_info;
/** If the flyable is in a cannon, this is the pointer to the cannon
* animation. NULL otherwise. */
AbstractKartAnimation *m_animation;
protected:
/** Kart which shot this flyable. */
AbstractKart* m_owner;
@@ -162,11 +168,16 @@ public:
static void init (const XMLNode &node, scene::IMesh *model,
PowerupManager::PowerupType type);
virtual bool updateAndDelete(float);
virtual void setAnimation(AbstractKartAnimation *animation);
virtual HitEffect* getHitEffect() const;
bool isOwnerImmunity(const AbstractKart *kart_hit) const;
virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL);
void explode(AbstractKart* kart, PhysicalObject* obj=NULL,
bool secondary_hits=true);
unsigned int getOwnerId();
// ------------------------------------------------------------------------
/** Returns if this flyable has an animation playing (e.g. cannon). */
bool hasAnimation() const { return m_animation != NULL; }
// ------------------------------------------------------------------------
/** If true the up velocity of the flyable will be adjust so that the
* flyable stays at a height close to the average height.
@@ -194,15 +205,16 @@ public:
void reset () { Moveable::reset(); }
// ------------------------------------------------------------------------
/** Returns the type of flyable. */
PowerupManager::PowerupType
getType() const {return m_type;}
PowerupManager::PowerupType getType() const {return m_type;}
// ------------------------------------------------------------------------
/** Sets wether Flyable should update TerrainInfo as part of its update
* call, or if the inheriting object will update TerrainInfo itself
* (or perhaps not at all if it is not needed). */
void setDoTerrainInfo(bool d) { m_do_terrain_info = d; }
// ------------------------------------------------------------------------
unsigned int getOwnerId();
/** Returns the size (extend) of the mesh. */
const Vec3 &getExtend() const { return m_extend; }
// ------------------------------------------------------------------------
}; // Flyable
#endif

View File

@@ -29,6 +29,7 @@
#include "modes/linear_world.hpp"
#include "physics/btKart.hpp"
#include "physics/triangle_mesh.hpp"
#include "tracks/check_manager.hpp"
#include "tracks/drive_graph.hpp"
#include "tracks/drive_node.hpp"
#include "tracks/track.hpp"
@@ -103,7 +104,7 @@ RubberBall::RubberBall(AbstractKart *kart)
DriveGraph::get()->getNode(getCurrentGraphNode())->getNormal();
TerrainInfo::update(getXYZ(), -normal);
initializeControlPoints(m_owner->getXYZ());
CheckManager::get()->addFlyableToCannons(this);
} // RubberBall
// ----------------------------------------------------------------------------
@@ -114,6 +115,7 @@ RubberBall::~RubberBall()
if(m_ping_sfx->getStatus()==SFXBase::SFX_PLAYING)
m_ping_sfx->stop();
m_ping_sfx->deleteSFX();
CheckManager::get()->removeFlyableFromCannons(this);
} // ~RubberBall
// ----------------------------------------------------------------------------
@@ -145,6 +147,17 @@ void RubberBall::initializeControlPoints(const Vec3 &xyz)
m_t_increase = m_speed/m_length_cp_1_2;
} // initializeControlPoints
// ----------------------------------------------------------------------------
void RubberBall::setAnimation(AbstractKartAnimation *animation)
{
if (!animation)
{
initializeControlPoints(getXYZ());
m_height_timer = 0;
}
Flyable::setAnimation(animation);
} // setAnimation
// ----------------------------------------------------------------------------
/** Determines the first kart that is still in the race.
*/
@@ -310,6 +323,7 @@ bool RubberBall::updateAndDelete(float dt)
// FIXME: what does the rubber ball do in case of battle mode??
if(!world) return true;
if(m_delete_timer>0)
{
m_delete_timer -= dt;
@@ -323,6 +337,14 @@ bool RubberBall::updateAndDelete(float dt)
}
}
if (hasAnimation())
{
// Flyable will call update() of the animation to
// update the ball's position.
m_previous_xyz = getXYZ();
return Flyable::updateAndDelete(dt);
}
// Update the target in case that the first kart was overtaken (or has
// finished the race).
computeTarget();

View File

@@ -204,6 +204,7 @@ public:
static void init(const XMLNode &node, scene::IMesh *rubberball);
virtual bool updateAndDelete(float dt);
virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL);
virtual void setAnimation(AbstractKartAnimation *animation);
static float getTimeBetweenRubberBalls() {return m_time_between_balls;}
// ------------------------------------------------------------------------
/** This object does not create an explosion, all affects on

View File

@@ -24,6 +24,11 @@
#include "karts/skidding.hpp"
#include "physics/physics.hpp"
/** Constructor. Note that kart can be NULL in case that the animation is
* used for a basket ball in a cannon animation.
* \param kart Pointer to the kart that is animated, or NULL if the
* the animation is meant for a basket ball etc.
*/
AbstractKartAnimation::AbstractKartAnimation(AbstractKart *kart,
const std::string &name)
{
@@ -37,7 +42,7 @@ AbstractKartAnimation::AbstractKartAnimation(AbstractKart *kart,
// up animations) if this should happen. In debug mode this condition
// is caught by setKartAnimation(), and useful error messages are
// printed
if (kart->getKartAnimation())
if (kart && kart->getKartAnimation())
{
AbstractKartAnimation* ka = kart->getKartAnimation();
kart->setKartAnimation(NULL);
@@ -46,21 +51,23 @@ AbstractKartAnimation::AbstractKartAnimation(AbstractKart *kart,
#endif
// Register this animation with the kart (which will free it
// later).
kart->setKartAnimation(this);
Physics::getInstance()->removeKart(m_kart);
kart->getSkidding()->reset();
kart->getSlipstream()->reset();
if(kart->isSquashed())
if (kart)
{
// A time of 0 reset the squashing
kart->setSquash(0.0f, 0.0f);
kart->setKartAnimation(this);
Physics::getInstance()->removeKart(m_kart);
kart->getSkidding()->reset();
kart->getSlipstream()->reset();
if (kart->isSquashed())
{
// A time of 0 reset the squashing
kart->setSquash(0.0f, 0.0f);
}
// Reset the wheels (and any other animation played for that kart)
// This avoid the effect that some wheels might be way below the kart
// which is very obvious in the rescue animation.
m_kart->getKartModel()->resetVisualWheelPosition();
}
// Reset the wheels (and any other animation played for that kart)
// This avoid the effect that some wheels might be way below the kart
// which is very obvious in the rescue animation.
m_kart->getKartModel()->resetVisualWheelPosition();
} // AbstractKartAnimation
// ----------------------------------------------------------------------------
@@ -70,7 +77,7 @@ AbstractKartAnimation::~AbstractKartAnimation()
// is deleted (at the end of a race), which means that
// world is in the process of being deleted. In this case
// we can't call getPhysics() anymore.
if(m_timer < 0)
if(m_timer < 0 && m_kart)
{
m_kart->getBody()->setAngularVelocity(btVector3(0,0,0));
Physics::getInstance()->addKart(m_kart);
@@ -91,7 +98,7 @@ void AbstractKartAnimation::update(float dt)
m_timer -= dt;
if(m_timer<0)
{
m_kart->setKartAnimation(NULL);
if(m_kart) m_kart->setKartAnimation(NULL);
delete this;
}
} // update

View File

@@ -21,6 +21,7 @@
#include "animations/animation_base.hpp"
#include "animations/ipo.hpp"
#include "animations/three_d_animation.hpp"
#include "items/flyable.hpp"
#include "karts/abstract_kart.hpp"
#include "karts/kart_properties.hpp"
#include "modes/world.hpp"
@@ -28,7 +29,8 @@
#include "LinearMath/btTransform.h"
/** The constructor for the cannon animation.
* \param kart The kart to be animated.
* \param kart The kart to be animated. Can also be NULL if a basket ball
* etc is animated (e.g. cannon animation).
* \param ipo The IPO (blender interpolation curve) which the kart
* should follow.
* \param start_left, start_right: Left and right end points of the line
@@ -45,9 +47,41 @@ CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo,
float skid_rot)
: AbstractKartAnimation(kart, "CannonAnimation")
{
m_curve = new AnimationBase(ipo);
m_timer = ipo->getEndTime();
m_flyable = NULL;
init(ipo, start_left, start_right, end_left, end_right, skid_rot);
} // CannonAnimation
// ----------------------------------------------------------------------------
/** Constructor for a flyable. It sets the kart data to NULL.
*/
CannonAnimation::CannonAnimation(Flyable *flyable, Ipo *ipo,
const Vec3 &start_left, const Vec3 &start_right,
const Vec3 &end_left, const Vec3 &end_right )
: AbstractKartAnimation(NULL, "CannonAnimation")
{
m_flyable = flyable;
init(ipo, start_left, start_right, end_left, end_right, /*skid_rot*/0);
} // CannonAnimation(Flyable*...)
// ----------------------------------------------------------------------------
/** Common initialisation for kart-based and flyable-based animations.
* \param ipo The IPO (blender interpolation curve) which the kart
* should follow.
* \param start_left, start_right: Left and right end points of the line
* that the kart just crossed.
* \param end_left, end_right: Left and right end points of the line at
* which the kart finishes.
* \param skid_rot Visual rotation of the kart due to skidding (while this
* value can be queried, the AbstractkartAnimation constructor
* resets the value to 0, so it needs to be passed in.
*/
void CannonAnimation::init(Ipo *ipo, const Vec3 &start_left,
const Vec3 &start_right, const Vec3 &end_left,
const Vec3 &end_right, float skid_rot)
{
m_curve = new AnimationBase(ipo);
m_timer = ipo->getEndTime();
// First make sure that left and right points are indeed correct
// -------------------------------------------------------------
Vec3 my_start_left = start_left;
@@ -57,12 +91,17 @@ CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo,
// (the curve's origin must be in the middle of the line.
m_curve->getAt(0, &p0);
m_curve->getAt(0.1f, &p1);
Vec3 p2 = 0.5f*(p0 + p1) + m_kart->getNormal();
Vec3 p2;
if (m_kart)
p2 = 0.5f*(p0 + p1) + m_kart->getNormal();
else
p2 = 0.5f*(p0 + p1) + m_flyable->getNormal();
if (start_left.sideofPlane(p0, p1, p2) < 0)
{
// Left and right start line needs to be swapped
my_start_left = start_right;
my_start_right = start_left;
my_start_right = start_left;
}
// First adjust start and end points to take on each side half the kart
@@ -70,8 +109,9 @@ CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo,
Vec3 direction = my_start_right - my_start_left;
direction.normalize();
float kw = m_kart->getKartModel()->getWidth();
Vec3 adj_start_left = my_start_left + (0.5f*kw) * direction;
float kw = m_kart ? m_kart->getKartModel()->getWidth()
: m_flyable->getExtend().getX();
Vec3 adj_start_left = my_start_left + (0.5f*kw) * direction;
Vec3 adj_start_right = my_start_right - (0.5f*kw) * direction;
// Store the length of the start and end line, which is used
@@ -99,16 +139,17 @@ CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo,
// This delta is rotated with the kart and added to the interpolated curve
// position to get the actual kart position during the animation.
Vec3 curve_xyz;
Vec3 xyz = m_kart ? m_kart->getXYZ() : m_flyable->getXYZ();
m_curve->update(0, &curve_xyz);
m_delta = kart->getXYZ() - curve_xyz;
m_delta = xyz - curve_xyz;
// Compute on which fraction of the start line the kart is, to get the
// second component of the kart position: distance along start line
Vec3 v = adj_start_left - adj_start_right;
float l = v.length();
v /= l;
float f = v.dot(adj_start_left - kart->getXYZ());
float f = v.dot(adj_start_left - xyz);
if (f <= 0)
f = 0;
else if (f >= l)
@@ -138,28 +179,36 @@ CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo,
Vec3 tangent;
m_curve->getDerivativeAt(0, &tangent);
// Get the current kart orientation
Vec3 forward = m_kart->getTrans().getBasis().getColumn(2);
const btTransform &trans = m_kart ? m_kart->getTrans()
: m_flyable->getBody()->getWorldTransform();
Vec3 forward = trans.getBasis().getColumn(2);
Vec3 v1(tangent), v2(forward);
v1.setY(0); v2.setY(0);
m_delta_heading = shortestArcQuatNormalize2(v1, v2)
* btQuaternion(Vec3(0,1,0), skid_rot);
m_delta_heading = shortestArcQuatNormalize2(v1, v2)
* btQuaternion(Vec3(0, 1, 0), skid_rot);
// The previous call to m_curve->update will set the internal timer
// of the curve to dt. Reset it to 0 to make sure the timer is in
// synch with the timer of the CanonAnimation
m_curve->reset();
} // CannonAnimation
} // init
// ----------------------------------------------------------------------------
CannonAnimation::~CannonAnimation()
{
delete m_curve;
btTransform pos = m_kart->getTrans();
m_kart->getBody()->setCenterOfMassTransform(pos);
Vec3 v(0, 0, m_kart->getKartProperties()->getEngineMaxSpeed());
m_kart->setVelocity(pos.getBasis()*v);
if (m_kart)
{
btTransform pos = m_kart->getTrans();
m_kart->getBody()->setCenterOfMassTransform(pos);
Vec3 v(0, 0, m_kart->getKartProperties()->getEngineMaxSpeed());
m_kart->setVelocity(pos.getBasis()*v);
}
else
{
m_flyable->setAnimation(NULL);
}
} // ~CannonAnimation
// ----------------------------------------------------------------------------
@@ -184,7 +233,9 @@ void CannonAnimation::update(float dt)
m_curve->getDerivativeAt(m_curve->getAnimationDuration() - m_timer,
&tangent);
// Get the current kart orientation
Vec3 forward = m_kart->getTrans().getBasis().getColumn(2);
const btTransform &trans = m_kart ? m_kart->getTrans()
: m_flyable->getBody()->getWorldTransform();
Vec3 forward = trans.getBasis().getColumn(2);
// Heading
// -------
@@ -200,10 +251,14 @@ void CannonAnimation::update(float dt)
// ------------------
// While start and end line have to have the same 'up' vector, karts can
// sometimes be not parallel to them. So slowly adjust this over time
Vec3 up = m_kart->getTrans().getBasis().getColumn(1);
Vec3 up = trans.getBasis().getColumn(1);
up.normalize();
Vec3 gravity = -m_kart->getBody()->getGravity();
gravity.normalize();
Vec3 gravity = m_kart ? -m_kart->getBody()->getGravity()
: -m_flyable->getBody()->getGravity();
if (gravity.length2() > 0)
gravity.normalize();
else
gravity.setValue(0, 1, 0);
// Adjust only 5% towards the real up vector. This will smoothly
// adjust the kart while the kart is in the air
Vec3 target_up_vector = (gravity*0.05f + up*0.95f).normalize();
@@ -220,27 +275,33 @@ void CannonAnimation::update(float dt)
// The timer counts backwards, so the fraction goes from 1 to 0
float f = m_timer / m_curve->getAnimationDuration();
btQuaternion zero(gravity, 0);
btQuaternion current_delta_heading = zero.slerp(m_delta_heading, f);
btQuaternion all_heading = m_kart->getRotation()*current_delta_heading*heading;
m_kart->setRotation(q_up * all_heading);
// Then compute the new location of the kart
// -----------------------------------------
float f_current_width = m_start_line_length * f
+ m_end_line_length * (1.0f - f);
// Adjust the horizontal location based on steering
m_fraction_of_line += m_kart->getSteerPercent()*dt*2.0f;
btClamp(m_fraction_of_line, -1.0f, 1.0f);
// Then compute the new location of the kart
// -----------------------------------------
btQuaternion all_heading;
if (m_kart)
{
btQuaternion zero(gravity, 0);
btQuaternion current_delta_heading = zero.slerp(m_delta_heading, f);
all_heading = m_kart->getRotation()*current_delta_heading*heading;
m_kart->setRotation(q_up * all_heading);
// horiz_delta is in kart coordinates, the rotation by q will
// transform it to the global coordinate system
Vec3 horiz_delta = Vec3(0.5f*m_fraction_of_line * f_current_width, 0, 0);
// Adjust the horizontal location based on steering
m_fraction_of_line += m_kart->getSteerPercent()*dt*2.0f;
btClamp(m_fraction_of_line, -1.0f, 1.0f);
} // if m_kart
else
{
// If a rubber ball is in this cannon, reduce its height over
// time so that it starts closer to the ground when released
float height = m_delta.getY();
float radius = m_flyable->getExtend().getY();
height = (height - radius) * 0.95f + radius;
m_delta.setY(height);
all_heading.setValue(0, 0, 0, 1);
}
// Determine direction orthogonal to the curve for the sideway movement
// of the kart.
@@ -251,5 +312,8 @@ void CannonAnimation::update(float dt)
Vec3 curve_xyz;
m_curve->update(dt, &curve_xyz);
m_kart->setXYZ(curve_xyz+rotated_delta);
if (m_kart)
m_kart->setXYZ(curve_xyz + rotated_delta);
else
m_flyable->setXYZ(curve_xyz + rotated_delta);
} // update

View File

@@ -26,6 +26,7 @@
class AbstractKart;
class AnimationBase;
class Flyable;
class Ipo;
@@ -46,6 +47,10 @@ protected:
/** Stores the curve interpolation for the cannon. */
AnimationBase *m_curve;
/** If this animation is used for a flyable (e.g. basket ball) instead
* of a kart, m_flyable is defined and m_kart is NULL. */
Flyable *m_flyable;
/** Length of the (adjusted, i.e. taking kart width into account)
* start line. */
float m_start_line_length;
@@ -61,12 +66,19 @@ protected:
/** The initial heading of the kart when crossing the line. This is
* used to smoothly orient the kart towards the normal of the cuve. */
btQuaternion m_delta_heading;
void init(Ipo *ipo, const Vec3 &start_left, const Vec3 &start_right,
const Vec3 &end_left, const Vec3 &end_right, float skid_rot);
public:
CannonAnimation(AbstractKart *kart, Ipo *ipo,
const Vec3 &start_left, const Vec3 &start_right,
const Vec3 &end_left, const Vec3 &end_right,
float skid_rot);
virtual ~CannonAnimation();
CannonAnimation(Flyable *flyable, Ipo *ipo,
const Vec3 &start_left, const Vec3 &start_right,
const Vec3 &end_left, const Vec3 &end_right);
virtual ~CannonAnimation();
virtual void update(float dt);
}; // CannonAnimation

View File

@@ -1132,7 +1132,7 @@ int handleCmdLine()
if(CommandLine::has("--track", &s) || CommandLine::has("-t", &s))
{
race_manager->setTrack(s);
Log::verbose("main", "You choose to start in track '%s'.",
Log::verbose("main", "You chose to start in track '%s'.",
s.c_str());
Track* t = track_manager->getTrack(s);
@@ -1142,7 +1142,7 @@ int handleCmdLine()
}
else if (t->isArena())
{
//if it's arena, don't create ai karts
//if it's arena, don't create AI karts
const std::vector<std::string> l;
race_manager->setDefaultAIKartList(l);
// Add 1 for the player kart
@@ -1151,7 +1151,7 @@ int handleCmdLine()
}
else if (t->isSoccer())
{
//if it's soccer, don't create ai karts
//if it's soccer, don't create AI karts
const std::vector<std::string> l;
race_manager->setDefaultAIKartList(l);
// Add 1 for the player kart
@@ -1218,7 +1218,7 @@ int handleCmdLine()
}
else
{
Log::verbose("main", "You choose to have %d laps.", laps);
Log::verbose("main", "You chose to have %d laps.", laps);
race_manager->setNumLaps(laps);
}
} // --laps
@@ -1330,7 +1330,7 @@ int handleCmdLine()
if (request->isSuccess())
{
Log::info("Main", "Logged in from command line.");
Log::info("Main", "Logged in from command-line.");
}
}
@@ -1390,9 +1390,9 @@ void initRest()
font_manager->loadFonts();
GUIEngine::init(device, driver, StateManager::get());
// This only initialises the non-network part of the addons manager. The
// online section of the addons manager will be initialised from a
// separate thread running in network http.
// This only initialises the non-network part of the add-ons manager. The
// online section of the add-ons manager will be initialised from a
// separate thread running in network HTTP.
addons_manager = new AddonsManager();
Online::ProfileManager::create();
@@ -1477,7 +1477,7 @@ void askForInternetPermission()
// Typically internet is disabled here (just better safe
// than sorry). If internet should be allowed, the news
// manager needs to be started (which in turn activates
// the addons manager).
// the add-ons manager).
bool need_to_start_news_manager =
UserConfigParams::m_internet_status !=
Online::RequestManager::IPERM_ALLOWED;
@@ -1615,8 +1615,8 @@ int main(int argc, char *argv[] )
addons_manager->checkInstalledAddons();
// Load addons.xml to get info about addons even when not
// allowed to access the internet
// Load addons.xml to get info about add-ons even when not
// allowed to access the Internet
if (UserConfigParams::m_internet_status !=
Online::RequestManager::IPERM_ALLOWED)
{
@@ -1630,7 +1630,7 @@ int main(int argc, char *argv[] )
}
catch (std::runtime_error& e)
{
Log::warn("Addons", "Exception thrown when initializing addons manager : %s", e.what());
Log::warn("Addons", "Exception thrown when initializing add-ons manager : %s", e.what());
}
}
}
@@ -1652,7 +1652,7 @@ int main(int argc, char *argv[] )
{
MessageDialog *dialog =
new MessageDialog(_("Your screen resolution is too "
"small to run STK."),
"low to run STK."),
/*from queue*/ true);
GUIEngine::DialogQueue::get()->pushDialog(dialog);
}
@@ -1898,7 +1898,7 @@ static void cleanSuperTuxKart()
// But still give them some additional time to finish. It avoids a
// race condition where a thread might access the file manager after it
// was deleted (in cleanUserConfig below), but before STK finishes and
// the os takes all threads down.
// the OS takes all threads down.
if(!NewsManager::get()->waitForReadyToDeleted(2.0f))
{
@@ -1918,12 +1918,12 @@ static void cleanSuperTuxKart()
}
SFXManager::destroy();
// Music manager can not be deleted before the sfx thread is stopped
// (since sfx commands can contain music information, which are
// Music manager can not be deleted before the SFX thread is stopped
// (since SFX commands can contain music information, which are
// deleted by the music manager).
delete music_manager;
// The addons manager might still be called from a currenty running request
// The add-ons manager might still be called from a currenty running request
// in the request manager, so it can not be deleted earlier.
if(addons_manager) delete addons_manager;

View File

@@ -436,6 +436,8 @@ World::~World()
irr_driver->onUnloadWorld();
projectile_manager->cleanup();
// In case that a race is aborted (e.g. track not found) track is 0.
if(Track::getCurrentTrack())
Track::getCurrentTrack()->cleanup();
@@ -486,8 +488,6 @@ World::~World()
Camera::removeAllCameras();
projectile_manager->cleanup();
// In case that the track is not found, Physics was not instantiated,
// but kill handles this correctly.
Physics::kill();

View File

@@ -87,6 +87,13 @@ RaceGUI::RaceGUI()
const float map_size = 100.0f;
const float top_margin = 3.5f * m_font_height;
if (UserConfigParams::m_multitouch_enabled &&
UserConfigParams::m_multitouch_mode != 0 &&
race_manager->getNumLocalPlayers() == 1)
{
m_multitouch_gui = new RaceGUIMultitouch(this);
}
// Check if we have enough space for minimap when touch steering is enabled
if (m_multitouch_gui != NULL)
{
@@ -139,6 +146,7 @@ RaceGUI::RaceGUI()
//-----------------------------------------------------------------------------
RaceGUI::~RaceGUI()
{
delete m_multitouch_gui;
} // ~Racegui

View File

@@ -101,13 +101,6 @@ RaceGUIBase::RaceGUIBase()
m_referee = NULL;
m_multitouch_gui = NULL;
if (UserConfigParams::m_multitouch_enabled &&
UserConfigParams::m_multitouch_mode != 0 &&
race_manager->getNumLocalPlayers() == 1)
{
m_multitouch_gui = new RaceGUIMultitouch(this);
}
} // RaceGUIBase
// ----------------------------------------------------------------------------
@@ -161,6 +154,11 @@ void RaceGUIBase::reset()
m_plunger_speed = core::vector2df(0,0);
m_plunger_state = PLUNGER_STATE_INIT;
clearAllMessages();
if (m_multitouch_gui != NULL)
{
m_multitouch_gui->reset();
}
} // reset
//-----------------------------------------------------------------------------
@@ -173,7 +171,6 @@ RaceGUIBase::~RaceGUIBase()
// If the referee is currently being shown,
// remove it from the scene graph.
delete m_referee;
delete m_multitouch_gui;
} // ~RaceGUIBase
//-----------------------------------------------------------------------------

View File

@@ -76,6 +76,18 @@ RaceGUIMultitouch::~RaceGUIMultitouch()
} // ~RaceGUIMultitouch
//-----------------------------------------------------------------------------
/** Sets the multitouch race gui to its initial state
*/
void RaceGUIMultitouch::reset()
{
if (m_device != NULL)
{
m_device->reset();
}
} // reset
//-----------------------------------------------------------------------------
/** Clears all previously created buttons in the multitouch device
*/

View File

@@ -62,6 +62,7 @@ public:
unsigned int getMinimapBottom() {return m_minimap_bottom;}
void setGuiAction(bool enabled = true) {m_gui_action = enabled;}
void reset();
}; // RaceGUIMultitouch

View File

@@ -86,6 +86,13 @@ RaceGUIOverworld::RaceGUIOverworld()
float scaling = irr_driver->getFrameSize().Height / 420.0f;
const float map_size = 250.0f;
if (UserConfigParams::m_multitouch_enabled &&
UserConfigParams::m_multitouch_mode != 0 &&
race_manager->getNumLocalPlayers() == 1)
{
m_multitouch_gui = new RaceGUIMultitouch(this);
}
// Check if we have enough space for minimap when touch steering is enabled
if (m_multitouch_gui != NULL)
@@ -156,6 +163,7 @@ RaceGUIOverworld::RaceGUIOverworld()
//-----------------------------------------------------------------------------
RaceGUIOverworld::~RaceGUIOverworld()
{
delete m_multitouch_gui;
} // ~RaceGUIOverworld
//-----------------------------------------------------------------------------

View File

@@ -25,6 +25,7 @@
#include "graphics/show_curve.hpp"
#include "graphics/stk_tex_manager.hpp"
#include "io/xml_node.hpp"
#include "items/flyable.hpp"
#include "karts/abstract_kart.hpp"
#include "karts/cannon_animation.hpp"
#include "karts/skidding.hpp"
@@ -88,9 +89,12 @@ CheckCannon::CheckCannon(const XMLNode &node, unsigned int index)
: video::SColor(128, 128, 128, 128);
}
buffer->recalculateBoundingBox();
buffer->getMaterial().setTexture(0, STKTexManager::getInstance()->getUnicolorTexture(video::SColor(128, 255, 105, 180)));
buffer->getMaterial().setTexture(1, STKTexManager::getInstance()->getUnicolorTexture(video::SColor(0, 0, 0, 0)));
buffer->getMaterial().setTexture(2, STKTexManager::getInstance()->getUnicolorTexture(video::SColor(0, 0, 0, 0)));
buffer->getMaterial().setTexture(0, STKTexManager::getInstance()
->getUnicolorTexture(video::SColor(128, 255, 105, 180)));
buffer->getMaterial().setTexture(1, STKTexManager::getInstance()
->getUnicolorTexture(video::SColor(0, 0, 0, 0)));
buffer->getMaterial().setTexture(2, STKTexManager::getInstance()
->getUnicolorTexture(video::SColor(0, 0, 0, 0)));
buffer->getMaterial().BackfaceCulling = false;
//mesh->setBoundingBox(buffer->getBoundingBox());
m_debug_target_node = irr_driver->addMesh(mesh, "checkdebug");
@@ -114,6 +118,8 @@ CheckCannon::~CheckCannon()
} // ~CheckCannon
// ----------------------------------------------------------------------------
/** Changes the colour of a check cannon depending on state.
*/
void CheckCannon::changeDebugColor(bool is_active)
{
#if defined(DEBUG) && !defined(SERVER_ONLY)
@@ -133,6 +139,55 @@ void CheckCannon::changeDebugColor(bool is_active)
#endif
} // changeDebugColor
// ----------------------------------------------------------------------------
/** Adds a flyable to be tested for crossing a cannon checkline.
* \param flyable The flyable to be tested.
*/
void CheckCannon::addFlyable(Flyable *flyable)
{
m_all_flyables.push_back(flyable);
m_flyable_previous_position.push_back(flyable->getXYZ());
} // addFlyable
// ----------------------------------------------------------------------------
/** Removes a flyable from the tests if it crosses a checkline. Used when
* the flyable is removed (e.g. explodes).
*/
void CheckCannon::removeFlyable(Flyable *flyable)
{
std::vector<Flyable*>::iterator i = std::find(m_all_flyables.begin(),
m_all_flyables.end(),
flyable);
assert(i != m_all_flyables.end());
int index = i - m_all_flyables.begin(); // get the index
m_all_flyables.erase(i);
m_flyable_previous_position.erase(m_flyable_previous_position.begin() + index);
} // removeFlyable
// ----------------------------------------------------------------------------
/** Overriden to also check all flyables registered with the cannon.
*/
void CheckCannon::update(float dt)
{
CheckLine::update(dt);
for (unsigned int i = 0; i < m_all_flyables.size(); i++)
{
setIgnoreHeight(true);
bool triggered = isTriggered(m_flyable_previous_position[i],
m_all_flyables[i]->getXYZ(),
/*kart index - ignore*/ -1 );
setIgnoreHeight(false);
m_flyable_previous_position[i] = m_all_flyables[i]->getXYZ();
if(!triggered) continue;
// Cross the checkline - add the cannon animation
CannonAnimation *animation =
new CannonAnimation(m_all_flyables[i], m_curve->clone(),
getLeftPoint(), getRightPoint(),
m_target_left, m_target_right);
m_all_flyables[i]->setAnimation(animation);
} // for i in all flyables
} // update
// ----------------------------------------------------------------------------
/** Called when the check line is triggered. This function creates a cannon
* animation object and attaches it to the kart.

View File

@@ -21,8 +21,10 @@
#include "animations/animation_base.hpp"
#include "tracks/check_line.hpp"
#include "utils/cpp2011.hpp"
class CheckManager;
class Flyable;
class Ipo;
class ShowCurve;
class XMLNode;
@@ -51,12 +53,18 @@ private:
/** Used to display debug information about checklines. */
scene::IMeshSceneNode *m_debug_target_node;
#endif
std::vector<Flyable*> m_all_flyables;
std::vector<Vec3> m_flyable_previous_position;
public:
CheckCannon(const XMLNode &node, unsigned int index);
virtual ~CheckCannon();
virtual void trigger(unsigned int kart_index);
virtual void changeDebugColor(bool is_active);
virtual void trigger(unsigned int kart_index) OVERRIDE;
virtual void changeDebugColor(bool is_active) OVERRIDE;
virtual void update(float dt) OVERRIDE;
void addFlyable(Flyable *flyable);
void removeFlyable(Flyable *flyable);
}; // CheckLine
#endif

View File

@@ -46,16 +46,16 @@ CheckCylinder::CheckCylinder(const XMLNode &node, unsigned int index, TriggerIte
} // CheckCylinder
// ----------------------------------------------------------------------------
/** True if going from old_pos to new_pos enters or leaves this sphere. This
/** True if going from old_pos to new_pos enters or leaves this cylinder. This
* function is called from update (of the checkline structure). It also
* updates the flag about which karts are inside
* \param old_pos Position in previous frame.
* \param new_pos Position in current frame.
* \param kart_id Index of the kart, can be used to store kart specific
* \param kart_id Index of the kart, can be used to store kart specific
* additional data.
*/
bool CheckCylinder::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
unsigned int kart_id)
int kart_id)
{
// TODO: this is the code for a sphere, rewrite for cylinder
Vec3 old_pos_xz(old_pos.x(), 0.0f, old_pos.z());

View File

@@ -52,7 +52,7 @@ public:
TriggerItemListener* listener);
virtual ~CheckCylinder() {};
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
unsigned int kart_id);
int kart_id);
// ------------------------------------------------------------------------
/** Returns if kart indx is currently inside of the sphere. */
bool isInside(int index) const { return m_is_inside[index]; }

View File

@@ -55,7 +55,8 @@ void CheckGoal::update(float dt)
if (world)
{
if (isTriggered(m_previous_ball_position, world->getBallPosition(), -1))
if (isTriggered(m_previous_ball_position, world->getBallPosition(),
/*kart index - ignore*/-1) )
{
if (UserConfigParams::m_check_debug)
{
@@ -86,7 +87,7 @@ void CheckGoal::trigger(unsigned int i)
// ----------------------------------------------------------------------------
bool CheckGoal::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
unsigned int kartIndex)
int kart_index)
{
core::vector2df cross_point;

View File

@@ -65,7 +65,7 @@ public:
virtual void update(float dt) OVERRIDE;
virtual void trigger(unsigned int kart_index) OVERRIDE;
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
unsigned int indx) OVERRIDE;
int indx) OVERRIDE;
virtual void reset(const Track &track) OVERRIDE;
// ------------------------------------------------------------------------

View File

@@ -53,13 +53,13 @@ void CheckLap::reset(const Track &track)
// ----------------------------------------------------------------------------
/** True if going from old_pos to new_pos crosses this checkline. This function
* is called from update (of the checkline structure).
* \param old_pos Position in previous frame.
* \param new_pos Position in current frame.
* \param old_pos Position in previous frame.
* \param new_pos Position in current frame.
* \param kart_index Index of the kart, can be used to store kart specific
* additional data.
* additional data.
*/
bool CheckLap::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
unsigned int kart_index)
int kart_index)
{
World* w = World::getWorld();
LinearWorld* lin_world = dynamic_cast<LinearWorld*>(w);

View File

@@ -40,7 +40,7 @@ public:
CheckLap(const XMLNode &node, unsigned int index);
virtual ~CheckLap() {};
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
unsigned int indx);
int indx);
virtual void reset(const Track &track);
}; // CheckLine

View File

@@ -40,6 +40,7 @@
CheckLine::CheckLine(const XMLNode &node, unsigned int index)
: CheckStructure(node, index)
{
m_ignore_height = false;
// Note that when this is called the karts have not been allocated
// in world, so we can't call world->getNumKarts()
m_previous_sign.resize(race_manager->getNumberOfKarts());
@@ -169,13 +170,14 @@ void CheckLine::changeDebugColor(bool is_active)
// ----------------------------------------------------------------------------
/** True if going from old_pos to new_pos crosses this checkline. This function
* is called from update (of the checkline structure).
* \param old_pos Position in previous frame.
* \param new_pos Position in current frame.
* \param indx Index of the kart, can be used to store kart specific
* additional data.
* \param old_pos Position in previous frame.
* \param new_pos Position in current frame.
* \param kart_indx Index of the kart, can be used to store kart specific
* additional data. If set to a negative number it will
* be ignored (used for e.g. soccer ball, and basket ball).
*/
bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
unsigned int kart_index)
int kart_index)
{
World* w = World::getWorld();
core::vector2df p=new_pos.toIrrVector2d();
@@ -184,7 +186,7 @@ bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
bool previous_sign;
if (kart_index == UINT_MAX)
if (kart_index < 0)
{
core::vector2df p = old_pos.toIrrVector2d();
previous_sign = (m_line.getPointOrientation(p) >= 0);
@@ -196,18 +198,20 @@ bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
// If the sign has changed, i.e. the infinite line was crossed somewhere,
// check if the finite line was actually crossed:
core::vector2df cross_point;
if (sign != previous_sign &&
m_line.intersectWith(core::line2df(old_pos.toIrrVector2d(),
new_pos.toIrrVector2d()),
m_cross_point) )
cross_point) )
{
// Now check the minimum height: the kart position must be within a
// reasonable distance in the Z axis - 'reasonable' for now to be
// between -1 and 4 units (negative numbers are unlikely, but help
// in case that the kart is 'somewhat' inside of the track, or the
// checklines are a bit off in Z direction.
result = new_pos.getY()-m_min_height<m_over_min_height &&
new_pos.getY()-m_min_height>-m_under_min_height;
result = m_ignore_height ||
(new_pos.getY()-m_min_height<m_over_min_height &&
new_pos.getY()-m_min_height>-m_under_min_height );
if(UserConfigParams::m_check_debug && !result)
{
if(World::getWorld()->getNumKarts()>0)
@@ -219,20 +223,20 @@ bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
Log::info("CheckLine", "Kart %d crosses line, but wrong height "
"(%f vs %f).",
kart_index, new_pos.getY(), m_min_height);
}
}
else
result = false;
if (kart_index != UINT_MAX)
m_previous_sign[kart_index] = sign;
if (result && kart_index != UINT_MAX)
if (kart_index >= 0)
{
LinearWorld* lw = dynamic_cast<LinearWorld*>(w);
if (lw != NULL)
lw->setLastTriggeredCheckline(kart_index, m_index);
m_previous_sign[kart_index] = sign;
if (result)
{
LinearWorld* lw = dynamic_cast<LinearWorld*>(w);
if (lw != NULL)
lw->setLastTriggeredCheckline(kart_index, m_index);
}
}
return result;
} // isTriggered

View File

@@ -46,7 +46,10 @@ private:
/** The line that is tested for being crossed. */
core::line2df m_line;
core::vector2df m_cross_point;
/** True if this line should ignore the height test. This is required
* e.g. for basketball cannons, since the ball can be too height to
* otherwise trigger the cannon. */
bool m_ignore_height;
/** The minimum height of the checkline. */
float m_min_height;
@@ -79,17 +82,18 @@ public:
CheckLine(const XMLNode &node, unsigned int index);
virtual ~CheckLine();
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
unsigned int indx);
int indx);
virtual void reset(const Track &track);
virtual void resetAfterKartMove(unsigned int kart_index);
virtual void changeDebugColor(bool is_active);
// ------------------------------------------------------------------------
/** Returns the actual line data for this checkpoint. */
const core::line2df &getLine2D() const {return m_line;}
// ------------------------------------------------------------------------
/** Returns the 2d point at which the line was crossed. Note that this
* value is ONLY valid after isTriggered is called and inside of
* trigger(). */
const core::vector2df &getCrossPoint() const { return m_cross_point; }
/** Sets if this check line should not do a height test for testing
* if a line is crossed. Used for basket calls in cannon (the ball can
* be too heigh to otherwise trigger he cannon). */
void setIgnoreHeight(bool b) { m_ignore_height = b; }
}; // CheckLine
#endif

View File

@@ -131,6 +131,37 @@ void CheckManager::resetAfterKartMove(AbstractKart *kart)
(*i)->resetAfterKartMove(kart->getWorldKartId());
} // resetAfterKartMove
// ----------------------------------------------------------------------------
/** Adds a flyable object to be tested against cannons. This will allow
* bowling- and rubber-balls to fly in a cannon.
* \param flyable Pointer to the flyable to be added.
*/
void CheckManager::addFlyableToCannons(Flyable *flyable)
{
for (unsigned int i = 0; i < m_all_checks.size(); i++)
{
CheckCannon *cc = dynamic_cast<CheckCannon*>(m_all_checks[i]);
if (cc)
cc->addFlyable(flyable);
}
} // addFlyable
// ----------------------------------------------------------------------------
/** Removes a flyable from all cannons. Used when this flyable is removed
* (e.g. explodes).
* \param flyable Pointer to the flyable to be removed.
*/
void CheckManager::removeFlyableFromCannons(Flyable *flyable)
{
for (unsigned int i = 0; i < m_all_checks.size(); i++)
{
CheckCannon *cc = dynamic_cast<CheckCannon*>(m_all_checks[i]);
if (cc)
cc->removeFlyable(flyable);
}
} // addFlyable
// ----------------------------------------------------------------------------
/** Updates all animations. Called one per time step.
* \param dt Time since last call.

View File

@@ -27,6 +27,7 @@
class AbstractKart;
class CheckStructure;
class Flyable;
class Track;
class XMLNode;
class Vec3;
@@ -46,6 +47,8 @@ private:
~CheckManager();
public:
void add(CheckStructure* strct) { m_all_checks.push_back(strct); }
void addFlyableToCannons(Flyable *flyable);
void removeFlyableFromCannons(Flyable *flyable);
void load(const XMLNode &node);
void update(float dt);
void reset(const Track &track);

View File

@@ -53,11 +53,11 @@ CheckSphere::CheckSphere(const XMLNode &node, unsigned int index)
* updates the flag about which karts are inside
* \param old_pos Position in previous frame.
* \param new_pos Position in current frame.
* \param kart_id Index of the kart, can be used to store kart specific
* \param kart_id Index of the kart, can be used to store kart specific
* additional data.
*/
bool CheckSphere::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
unsigned int kart_id)
int kart_id)
{
float old_dist2 = (old_pos-m_center_point).length2();
float new_dist2 = (new_pos-m_center_point).length2();

View File

@@ -48,7 +48,7 @@ public:
CheckSphere(const XMLNode &node, unsigned int index);
virtual ~CheckSphere() {};
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
unsigned int kart_id);
int kart_id);
// ------------------------------------------------------------------------
/** Returns if kart indx is currently inside of the sphere. */
bool isInside(int index) const { return m_is_inside[index]; }

View File

@@ -115,7 +115,7 @@ public:
* additional data.
*/
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
unsigned int indx)=0;
int indx)=0;
virtual void trigger(unsigned int kart_index);
virtual void reset(const Track &track);