Added first test version of 'rubber ball' (which might replace
the anchor). Known bugs: atm it does not yet bounce (it follows just the drivelines and might be partly in the track); the first kart can't avoid it (long term breaking might allow you to avoid it); it might hit another kart first and explode. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@9302 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
cc20387a95
commit
afb3728995
BIN
data/models/rubber_ball-icon.png
Normal file
BIN
data/models/rubber_ball-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
data/models/rubber_ball.b3d
Normal file
BIN
data/models/rubber_ball.b3d
Normal file
Binary file not shown.
BIN
data/models/rubber_ball.png
Normal file
BIN
data/models/rubber_ball.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
@ -15,6 +15,9 @@
|
||||
model="anchor.b3d" />
|
||||
<item name="switch" icon="swap-icon.png" />
|
||||
<item name="swatter" icon="swatter-icon.png" />
|
||||
<item name="rubber-ball" icon="rubber_ball-icon.png"
|
||||
model="rubber_ball.b3d" speed="10.0"
|
||||
min-height="0.2" max-height="1.0" />
|
||||
<item name="parachute" icon="parachute-icon.png"
|
||||
model="parachute.b3d" />
|
||||
<item name="plunger" icon="plunger-icon.png"
|
||||
@ -37,19 +40,19 @@
|
||||
be quite rare, since otherwise the item might be used
|
||||
too often (compared with many items which will only
|
||||
affect a karts or two). -->
|
||||
<!-- bubble cake bowl zipper plunger switch glove para anvil -->
|
||||
<first w="25 5 15 5 10 10 10 0 0"
|
||||
w-multi=" 0 0 5 0 0 0 5 0 0" />
|
||||
<top33 w="30 30 30 30 30 10 30 10 0"
|
||||
w-multi=" 0 10 10 0 10 0 10 0 0" />
|
||||
<mid33 w="30 30 30 30 30 10 30 20 5"
|
||||
w-multi=" 0 20 20 20 20 0 0 5 0" />
|
||||
<end33 w=" 0 30 30 30 30 10 30 30 30"
|
||||
w-multi=" 0 30 30 30 30 0 30 20 0" />
|
||||
<last w=" 0 30 30 60 60 0 0 60 60"
|
||||
w-multi=" 0 30 30 60 60 0 0 0 0" />
|
||||
<battle w=" 0 30 60 0 0 10 40 0 0"
|
||||
w-multi=" 0 0 5 0 0 0 0 0 0" />
|
||||
<!-- bubble cake bowl zipper plunger switch glove rubber para anvil -->
|
||||
<first w="25 5 15 5 10 10 10 0 0 0"
|
||||
w-multi=" 0 0 5 0 0 0 5 0 0 0" />
|
||||
<top33 w="30 30 30 30 30 10 30 10 10 0"
|
||||
w-multi=" 0 10 10 0 10 0 10 0 0 0" />
|
||||
<mid33 w="30 30 30 30 30 10 30 20 20 5"
|
||||
w-multi=" 0 20 20 20 20 0 0 5 5 0" />
|
||||
<end33 w=" 0 30 30 30 30 10 30 30 30 30"
|
||||
w-multi=" 0 30 30 30 30 0 30 20 20 0" />
|
||||
<last w=" 0 30 30 60 60 0 0 60 60 60"
|
||||
w-multi=" 0 30 30 60 60 0 0 0 0 0" />
|
||||
<battle w=" 0 30 60 0 0 10 40 0 0 0"
|
||||
w-multi=" 0 0 5 0 0 0 0 0 0 0" />
|
||||
|
||||
</powerup>
|
||||
|
||||
|
@ -185,6 +185,8 @@ supertuxkart_SOURCES = \
|
||||
items/powerup_manager.hpp \
|
||||
items/projectile_manager.cpp \
|
||||
items/projectile_manager.hpp \
|
||||
items/rubber_ball.cpp \
|
||||
items/rubber_ball.hpp \
|
||||
items/rubber_band.cpp \
|
||||
items/rubber_band.hpp \
|
||||
items/swatter.cpp \
|
||||
|
@ -574,6 +574,10 @@
|
||||
RelativePath="..\..\items\projectile_manager.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\items\rubber_ball.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\items\rubber_band.cpp"
|
||||
>
|
||||
|
@ -196,7 +196,11 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
if (UserConfigParams::m_artist_debug_mode && world)
|
||||
{
|
||||
Kart* kart = world->getLocalPlayerKart(0);
|
||||
kart->setPowerup(PowerupManager::POWERUP_SWATTER, 10000);
|
||||
if(control_is_pressed)
|
||||
kart->setPowerup(PowerupManager::POWERUP_RUBBERBALL,
|
||||
10000);
|
||||
else
|
||||
kart->setPowerup(PowerupManager::POWERUP_SWATTER, 10000);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -202,7 +202,8 @@ void Flyable::createPhysics(float forw_offset, const Vec3 &velocity,
|
||||
m_body->setLinearVelocity(v);
|
||||
if(!rotates) m_body->setAngularFactor(0.0f); // prevent rotations
|
||||
}
|
||||
m_body->setCollisionFlags(btCollisionObject::CF_NO_CONTACT_RESPONSE);
|
||||
m_body->setCollisionFlags(m_body->getCollisionFlags() |
|
||||
btCollisionObject::CF_NO_CONTACT_RESPONSE);
|
||||
|
||||
} // createPhysics
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -466,6 +467,8 @@ void Flyable::hit(Kart *kart_hit, PhysicalObject* object)
|
||||
case PowerupManager::POWERUP_PLUNGER:
|
||||
// Handled by plunger.cpp Plunger::hit
|
||||
break;
|
||||
case PowerupManager::POWERUP_RUBBERBALL:
|
||||
break;
|
||||
case PowerupManager::POWERUP_BOWLING:
|
||||
{
|
||||
if (kart_hit == m_owner)
|
||||
|
@ -228,6 +228,7 @@ void Powerup::use()
|
||||
break;
|
||||
}
|
||||
case PowerupManager::POWERUP_CAKE:
|
||||
case PowerupManager::POWERUP_RUBBERBALL:
|
||||
case PowerupManager::POWERUP_BOWLING:
|
||||
case PowerupManager::POWERUP_PLUNGER:
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "items/bowling.hpp"
|
||||
#include "items/cake.hpp"
|
||||
#include "items/plunger.hpp"
|
||||
#include "items/rubber_ball.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
@ -93,7 +94,7 @@ PowerupManager::PowerupType
|
||||
static std::string powerup_names[] = {
|
||||
"", /* Nothing */
|
||||
"bubblegum", "cake", "bowling", "zipper", "plunger", "switch",
|
||||
"swatter", "parachute", "anchor"
|
||||
"swatter", "rubber-ball", "parachute", "anchor"
|
||||
};
|
||||
|
||||
for(unsigned int i=POWERUP_FIRST; i<=POWERUP_LAST; i++)
|
||||
@ -188,11 +189,13 @@ void PowerupManager::LoadPowerup(PowerupType type, const XMLNode &node)
|
||||
// Load special attributes for certain powerups
|
||||
switch (type) {
|
||||
case POWERUP_BOWLING:
|
||||
Bowling::init(node, m_all_meshes[type]); break;
|
||||
Bowling::init(node, m_all_meshes[type]); break;
|
||||
case POWERUP_PLUNGER:
|
||||
Plunger::init(node, m_all_meshes[type]); break;
|
||||
Plunger::init(node, m_all_meshes[type]); break;
|
||||
case POWERUP_CAKE:
|
||||
Cake::init(node, m_all_meshes[type]); break;
|
||||
Cake::init(node, m_all_meshes[type]); break;
|
||||
case POWERUP_RUBBERBALL:
|
||||
RubberBall::init(node, m_all_meshes[type]); break;
|
||||
default:;
|
||||
} // switch
|
||||
} // LoadNode
|
||||
|
@ -79,7 +79,7 @@ public:
|
||||
POWERUP_BUBBLEGUM = POWERUP_FIRST,
|
||||
POWERUP_CAKE,
|
||||
POWERUP_BOWLING, POWERUP_ZIPPER, POWERUP_PLUNGER,
|
||||
POWERUP_SWITCH, POWERUP_SWATTER,
|
||||
POWERUP_SWITCH, POWERUP_SWATTER, POWERUP_RUBBERBALL,
|
||||
POWERUP_PARACHUTE,
|
||||
POWERUP_ANVIL, //powerup.cpp assumes these two come last
|
||||
POWERUP_LAST=POWERUP_ANVIL,
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "items/plunger.hpp"
|
||||
#include "items/powerup_manager.hpp"
|
||||
#include "items/powerup.hpp"
|
||||
#include "items/rubber_ball.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/race_state.hpp"
|
||||
|
||||
@ -174,9 +175,10 @@ Flyable *ProjectileManager::newProjectile(Kart *kart,
|
||||
Flyable *f;
|
||||
switch(type)
|
||||
{
|
||||
case PowerupManager::POWERUP_BOWLING: f = new Bowling(kart); break;
|
||||
case PowerupManager::POWERUP_PLUNGER: f = new Plunger(kart); break;
|
||||
case PowerupManager::POWERUP_CAKE: f = new Cake(kart); break;
|
||||
case PowerupManager::POWERUP_BOWLING: f = new Bowling(kart); break;
|
||||
case PowerupManager::POWERUP_PLUNGER: f = new Plunger(kart); break;
|
||||
case PowerupManager::POWERUP_CAKE: f = new Cake(kart); break;
|
||||
case PowerupManager::POWERUP_RUBBERBALL: f = new RubberBall(kart);break;
|
||||
default: return NULL;
|
||||
}
|
||||
m_active_projectiles.push_back(f);
|
||||
|
264
src/items/rubber_ball.cpp
Normal file
264
src/items/rubber_ball.cpp
Normal file
@ -0,0 +1,264 @@
|
||||
// $Id$
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2011 Joerg Henrichs
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "items/rubber_ball.hpp"
|
||||
|
||||
#include "karts/kart.hpp"
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
|
||||
RubberBall::RubberBall(Kart *kart) : Flyable(kart, PowerupManager::POWERUP_RUBBERBALL,
|
||||
0.0f /* mass */)
|
||||
{
|
||||
float forw_offset = 0.5f*kart->getKartLength() + m_extend.getZ()*0.5f+5.0f;
|
||||
|
||||
float min_speed = m_speed*4.0f;
|
||||
m_speed = kart->getSpeed() + m_speed;
|
||||
|
||||
if(m_speed < min_speed) m_speed = min_speed;
|
||||
|
||||
createPhysics(forw_offset, btVector3(0.0f, 0.0f, m_speed*2),
|
||||
new btSphereShape(0.5f*m_extend.getY()),
|
||||
-70.0f /*gravity*/,
|
||||
true /*rotates*/);
|
||||
|
||||
// Do not adjust the up velocity
|
||||
setAdjustUpVelocity(false);
|
||||
|
||||
// should not live forever, auto-destruct after 30 seconds
|
||||
m_max_lifespan = 30;
|
||||
|
||||
m_target = NULL;
|
||||
computeTarget();
|
||||
|
||||
const LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
|
||||
m_quad_graph = &(world->getTrack()->getQuadGraph());
|
||||
m_current_graph_node = world->getSectorForKart(kart->getWorldKartId());
|
||||
|
||||
// Determine distance along track
|
||||
Vec3 ball_distance_vec;
|
||||
m_quad_graph->spatialToTrack(&ball_distance_vec, getXYZ(),
|
||||
m_current_graph_node);
|
||||
m_distance_along_track = ball_distance_vec[2];
|
||||
|
||||
std::vector<unsigned int> succ;
|
||||
m_quad_graph->getSuccessors(m_current_graph_node, succ, /* ai */ true);
|
||||
|
||||
// We have to start aiming at the next sector (since it might be possible
|
||||
// that the kart is ahead of the center of the current sector).
|
||||
m_current_graph_node = succ[0];
|
||||
|
||||
// At the start the ball aims at quads till it gets close enough to the
|
||||
// target:
|
||||
m_aiming_at_target = false;
|
||||
m_wrapped_around = false;
|
||||
|
||||
} // RubberBall
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Determines the first kart. If a target has already been identified in an
|
||||
* earlier call, it is tested first, avoiding a loop over all karts.
|
||||
*/
|
||||
void RubberBall::computeTarget()
|
||||
{
|
||||
LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
|
||||
// FIXME: what does the rubber ball do in case of battle mode??
|
||||
if(!world) return;
|
||||
|
||||
for(unsigned int p = race_manager->getFinishedKarts()+1;
|
||||
p < world->getNumKarts()+1; p++)
|
||||
{
|
||||
m_target = world->getKartAtPosition(p);
|
||||
if(!m_target->isEliminated() && !m_target->hasFinishedRace())
|
||||
{
|
||||
// Don't aim at yourself
|
||||
if(m_target == m_owner) m_target = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} // computeTarget
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Initialises this object with data from the power.xml file (this is a static
|
||||
* function).
|
||||
* \param node XML Node
|
||||
* \param bowling The bowling ball mesh
|
||||
*/
|
||||
void RubberBall::init(const XMLNode &node, scene::IMesh *bowling)
|
||||
{
|
||||
Flyable::init(node, bowling, PowerupManager::POWERUP_RUBBERBALL);
|
||||
} // init
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Updates the rubber ball.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
void RubberBall::update(float dt)
|
||||
{
|
||||
Flyable::update(dt);
|
||||
|
||||
// Update the target in case that the first kart was overtaken (or has
|
||||
// finished the race).
|
||||
computeTarget();
|
||||
|
||||
if(!m_target)
|
||||
{
|
||||
// Remove this item from the game
|
||||
hit(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
Vec3 aim_xyz;
|
||||
determineTargetCoordinates(dt, &aim_xyz);
|
||||
|
||||
Vec3 delta = aim_xyz - getXYZ();
|
||||
// Determine the next point for the ball.
|
||||
// FIXME: use interpolation here for smooth curves
|
||||
Vec3 next_xyz = getXYZ() + delta * (m_speed * dt / delta.length());
|
||||
|
||||
|
||||
// Determine new distance along track
|
||||
Vec3 ball_distance_vec;
|
||||
m_quad_graph->spatialToTrack(&ball_distance_vec, getXYZ(),
|
||||
m_current_graph_node);
|
||||
float old_distance = m_distance_along_track;
|
||||
m_distance_along_track = ball_distance_vec[2];
|
||||
|
||||
float track_length = World::getWorld()->getTrack()->getTrackLength();
|
||||
|
||||
// Detect if the ball crossed the start line
|
||||
m_wrapped_around = old_distance > 0.9f * track_length &&
|
||||
m_distance_along_track < 10.0f;
|
||||
|
||||
// FIXME: do we want to test if we have overtaken the target kart?
|
||||
|
||||
#if 0
|
||||
float height = 3*fabsf(sinf(10.0f*logf(target_distance
|
||||
- m_distance_along_track)));
|
||||
|
||||
next_xyz.setY(next_xyz.getY()*0.9f+(getHoT() + height)*0.1f);
|
||||
#endif
|
||||
|
||||
setXYZ(next_xyz);
|
||||
} // update
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Determines which coordinates the ball should aim at next. If the ball is
|
||||
* still 'far' away from the target (>20), then it will aim at the next
|
||||
* graph node. If it's closer, the ball will aim directly at the kart and
|
||||
* keep on aiming at the kart, it will not follow the drivelines anymore.
|
||||
* \param aim_xyz On return contains the xyz coordinates to aim at.
|
||||
*/
|
||||
void RubberBall::determineTargetCoordinates(float dt, Vec3 *aim_xyz)
|
||||
{
|
||||
// If aiming at target phase, keep on aiming at target.
|
||||
// ----------------------------------------------------
|
||||
if(m_aiming_at_target)
|
||||
{
|
||||
*aim_xyz = m_target->getXYZ();
|
||||
return;
|
||||
}
|
||||
|
||||
// Aiming at a graph node
|
||||
// ----------------------
|
||||
const Vec3 &ball_xyz = getXYZ();
|
||||
|
||||
GraphNode *gn = &(m_quad_graph->getNode(m_current_graph_node));
|
||||
|
||||
// At this stage m_distance_along track is already the new distance (set
|
||||
// in the previous time step when aiming). It has to be detected if the
|
||||
// ball is now ahead of the graph node, and if so, the graph node has to
|
||||
// be updated till it is again ahead of the ball. Three distinct cases
|
||||
// have to be considered:
|
||||
// 1) The ball just crossed the start line (-> distance close to 0),
|
||||
// but the graph node is still before the start line, in which case
|
||||
// a new graph node has to be determined.
|
||||
// 2) The ball hasn't crossed the start line, but the graph node has
|
||||
// (i.e. graph node is 0), in which case the graph node is correct.
|
||||
// This happens after the first iteration, i.e. graph node initially
|
||||
// is the last one (distance close to track length), but if the ball
|
||||
// is ahead (distance of a graph node is measured to the beginning of
|
||||
// the quad, so if the ball is in the middle of the last quad it will
|
||||
// be ahead of the graph node!) the graph node will be set to the
|
||||
// first graph node (distance close to 0). In this case the graph node
|
||||
// should not be changed anymore.
|
||||
// 3) All other cases that do not involve the start line at all
|
||||
// (including e.g. ball and graph node crossed start line, neither
|
||||
// ball nor graph node crossed start line), which means that a new
|
||||
// graph node need to be determined only if the distance along track
|
||||
// of the ball is greater than the distance for
|
||||
float gn_distance = gn->getDistanceFromStart();
|
||||
float track_length = World::getWorld()->getTrack()->getTrackLength();
|
||||
|
||||
// Test 1: ball wrapped around, and graph node is close to end of track
|
||||
bool ball_ahead = m_wrapped_around && gn_distance >0.9f*track_length;
|
||||
|
||||
// Test 3: distance of ball greater than distance of graph node
|
||||
if(!ball_ahead && gn_distance < m_distance_along_track)
|
||||
// The distance test only applies if the graph node hasn't wrapped
|
||||
// around
|
||||
ball_ahead = true;
|
||||
|
||||
while(ball_ahead)
|
||||
{
|
||||
// FIXME: aim better if necessary!
|
||||
m_current_graph_node = gn->getSuccessor(0);
|
||||
gn = &(m_quad_graph->getNode(m_current_graph_node));
|
||||
|
||||
// Detect a wrap around of the graph node. We could just test if
|
||||
// the index of the new graph node is 0, but since it's possible
|
||||
// that we might have tracks with a more complicated structure, e.g
|
||||
// with two different start lines, we use this more general test:
|
||||
// If the previous distance was close to the end of the track, and
|
||||
// the new distance is close to 0, the graph node wrapped around.
|
||||
// This test prevents an infinite loop if the ball is on the last
|
||||
// quad, in which case no grpah node would fulfill the distance test.
|
||||
if(gn_distance > 0.9f*track_length &&
|
||||
gn->getDistanceFromStart()<10.0f)
|
||||
break;
|
||||
gn_distance = gn->getDistanceFromStart();
|
||||
ball_ahead = m_wrapped_around && gn_distance >0.9f*track_length;
|
||||
ball_ahead = !ball_ahead &&
|
||||
gn->getDistanceFromStart() < m_distance_along_track;
|
||||
}
|
||||
|
||||
const LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
|
||||
if(!world) return; // FIXME battle mode
|
||||
|
||||
float target_distance =
|
||||
world->getDistanceDownTrackForKart(m_target->getWorldKartId());
|
||||
|
||||
// Handle wrap around of distance if target crosses finishing line
|
||||
if(m_distance_along_track > target_distance)
|
||||
target_distance += world->getTrack()->getTrackLength();
|
||||
|
||||
// If the ball is close enough, start aiming directly at the target kart
|
||||
// ---------------------------------------------------------------------
|
||||
if(target_distance-m_distance_along_track < 20)
|
||||
{
|
||||
m_aiming_at_target = true;
|
||||
*aim_xyz = m_target->getXYZ();
|
||||
return;
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
*aim_xyz = gn->getQuad().getCenter();
|
||||
|
||||
} // determineTargetCoordinates
|
68
src/items/rubber_ball.hpp
Normal file
68
src/items/rubber_ball.hpp
Normal file
@ -0,0 +1,68 @@
|
||||
// $Id$
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2011 Joerg Henrichs
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_RUBBER_BALL_HPP
|
||||
#define HEADER_RUBBER_BALL_HPP
|
||||
|
||||
#include "items/flyable.hpp"
|
||||
|
||||
class Kart;
|
||||
class QuadGraph;
|
||||
|
||||
/**
|
||||
* \ingroup items
|
||||
*/
|
||||
class RubberBall: public Flyable
|
||||
{
|
||||
private:
|
||||
/** A pointer to the target kart. */
|
||||
const Kart *m_target;
|
||||
|
||||
/** The current quad this ball is aiming at. */
|
||||
int m_current_graph_node;
|
||||
|
||||
/** The previous distance to the graph node we are aiming
|
||||
* at atm. If the distance increases, we have passed the
|
||||
* point we aimed at and have to aim at the next point. */
|
||||
float m_distance_along_track;
|
||||
|
||||
/** True if the ball just crossed the start line, i.e. its
|
||||
* distance changed from close to length of track in the
|
||||
* previous time step to a bit over zero now. */
|
||||
bool m_wrapped_around;
|
||||
|
||||
/** Once the ball is close enough, it will aim for the kart. If the
|
||||
* kart should be able to then increase the distance to the ball,
|
||||
* the ball will be removed and the kart escapes. This boolean is
|
||||
* used to keep track of the state of this ball. */
|
||||
bool m_aiming_at_target;
|
||||
|
||||
/** For convenience keep a pointer to the quad graph. */
|
||||
QuadGraph *m_quad_graph;
|
||||
|
||||
void computeTarget();
|
||||
void determineTargetCoordinates(float dt, Vec3 *aim_xyz);
|
||||
public:
|
||||
RubberBall (Kart* kart);
|
||||
static void init(const XMLNode &node, scene::IMesh *bowling);
|
||||
|
||||
virtual void update (float dt);
|
||||
}; // RubberBall
|
||||
|
||||
#endif
|
@ -32,7 +32,7 @@
|
||||
#include "modes/world.hpp"
|
||||
#include "karts/kart.hpp"
|
||||
|
||||
#define SWAT_POS_OFFSET core::vector3df(0.0, 0.2, -0.4)
|
||||
#define SWAT_POS_OFFSET core::vector3df(0.0, 0.2f, -0.4f)
|
||||
#define SWAT_ANGLE_MIN 45
|
||||
#define SWAT_ANGLE_MAX 135
|
||||
#define SWAT_ANGLE_OFFSET (90.0f + 15.0f)
|
||||
|
@ -577,6 +577,12 @@ void DefaultAIController::handleItems(const float dt)
|
||||
m_controls->m_fire = true;
|
||||
break;
|
||||
}
|
||||
case PowerupManager::POWERUP_RUBBERBALL:
|
||||
// Perhaps some more sophisticated algorithm might be useful.
|
||||
// For now: fire if there is a kart ahead (which means that
|
||||
// this kart is certainly not the first kart)
|
||||
m_controls->m_fire = m_kart_ahead != NULL;
|
||||
break;
|
||||
default:
|
||||
printf("Invalid or unhandled powerup '%d' in default AI.\n",
|
||||
m_kart->getPowerup()->getType());
|
||||
@ -610,7 +616,7 @@ void DefaultAIController::computeNearestKarts()
|
||||
for(unsigned int i=0; i<m_world->getNumKarts(); i++)
|
||||
{
|
||||
Kart *k = m_world->getKart(i);
|
||||
if(k->isEliminated() || k==m_kart) continue;
|
||||
if(k->isEliminated() || k->hasFinishedRace() || k==m_kart) continue;
|
||||
if(k->getPosition()==my_position+1)
|
||||
{
|
||||
m_kart_behind = k;
|
||||
|
@ -117,7 +117,8 @@ void Moveable::stopFlying()
|
||||
*/
|
||||
void Moveable::update(float dt)
|
||||
{
|
||||
m_motion_state->getWorldTransform(m_transform);
|
||||
if(m_body->getInvMass()!=0)
|
||||
m_motion_state->getWorldTransform(m_transform);
|
||||
m_velocityLC = getVelocity()*m_transform.getBasis();
|
||||
Vec3 forw_vec = m_transform.getBasis().getColumn(0);
|
||||
m_heading = -atan2f(forw_vec.getZ(), forw_vec.getX());
|
||||
@ -145,12 +146,21 @@ void Moveable::createBody(float mass, btTransform& trans,
|
||||
m_transform = trans;
|
||||
m_motion_state = new KartMotionState(trans);
|
||||
|
||||
btRigidBody::btRigidBodyConstructionInfo info(mass, m_motion_state, shape, inertia);
|
||||
btRigidBody::btRigidBodyConstructionInfo info(mass, m_motion_state,
|
||||
shape, inertia);
|
||||
info.m_restitution=0.5f;
|
||||
|
||||
// Then create a rigid body
|
||||
// ------------------------
|
||||
m_body = new btRigidBody(info);
|
||||
if(mass==0)
|
||||
{
|
||||
// Create a kinematic object
|
||||
m_body->setCollisionFlags(m_body->getCollisionFlags() |
|
||||
btCollisionObject::CF_KINEMATIC_OBJECT );
|
||||
m_body->setActivationState(DISABLE_DEACTIVATION);
|
||||
}
|
||||
|
||||
// The value of user_pointer must be set from the actual class, otherwise this
|
||||
// is only a pointer to moveable, not to (say) kart, and virtual
|
||||
// functions are not called correctly. So only init the pointer to zero.
|
||||
|
Loading…
x
Reference in New Issue
Block a user