~ubuntu-branches/ubuntu/precise/supertuxkart/precise

« back to all changes in this revision

Viewing changes to src/items/rubber_band.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Egger
  • Date: 2011-02-24 22:36:25 UTC
  • mfrom: (1.1.9 upstream) (6.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20110224223625-ygrjfpg92obovuch
Tags: 0.7+dfsg1-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
//  along with this program; if not, write to the Free Software
18
18
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
19
 
20
 
#include "rubber_band.hpp"
 
20
#include "items/rubber_band.hpp"
21
21
 
22
 
#include "material_manager.hpp"
23
 
#include "race_manager.hpp"
24
 
#include "graphics/scene.hpp"
 
22
#include "graphics/irr_driver.hpp"
 
23
#include "graphics/material_manager.hpp"
25
24
#include "items/plunger.hpp"
26
25
#include "items/projectile_manager.hpp"
27
26
#include "karts/kart.hpp"
28
27
#include "modes/world.hpp"
29
28
#include "physics/physics.hpp"
 
29
#include "race/race_manager.hpp"
 
30
#include "utils/string_utils.hpp"
 
31
 
 
32
 
 
33
const wchar_t* getPlungerString()
 
34
{
 
35
    const int PLUNGER_STRINGS_AMOUNT = 3;
 
36
 
 
37
    RandomGenerator r;
 
38
    const int id = r.get(PLUNGER_STRINGS_AMOUNT);
 
39
 
 
40
    switch (id)
 
41
    {
 
42
        //I18N: shown when hit by plunger. %0 is the victim, %1 is the attacker
 
43
        case 0: return _("%0 bites %1's bait");
 
44
        //I18N: shown when hit by plunger. %0 is the victim, %1 is the attacker
 
45
        case 1: return _("%1 latches onto %0 for a free ride");
 
46
        //I18N: shown when hit by plunger. %0 is the victim, %1 is the attacker
 
47
        case 2: return _("%1 tests a tractor beam on %0");
 
48
        default: assert(false); return L"";  // avoid warning about no return value
 
49
    }
 
50
}
 
51
 
30
52
 
31
53
/** RubberBand constructor. It creates a simple quad and attaches it to the
32
54
 *  root(!) of the graph. It's easier this way to get the right coordinates
36
58
 *                 can trigger an explosion)
37
59
 *  \param kart    Reference to the kart.
38
60
 */
39
 
RubberBand::RubberBand(Plunger *plunger, const Kart &kart)
40
 
          : ssgVtxTable(GL_QUADS, new ssgVertexArray,
41
 
                        new ssgNormalArray,
42
 
                        new ssgTexCoordArray,
43
 
                        new ssgColourArray ), 
 
61
RubberBand::RubberBand(Plunger *plunger, Kart *kart) :
44
62
            m_plunger(plunger), m_owner(kart)
45
63
{
 
64
    video::SColor color(77, 179, 0, 0);
 
65
    video::SMaterial m;
 
66
    m.AmbientColor    = color;
 
67
    m.DiffuseColor    = color;
 
68
    m.EmissiveColor   = color;
 
69
    m.BackfaceCulling = false;
 
70
    m_mesh           = irr_driver->createQuadMesh(&m, /*create_one_quad*/ true);
 
71
    m_buffer         = m_mesh->getMeshBuffer(0);
 
72
    m_attached_state = RB_TO_PLUNGER;
 
73
    assert(m_buffer->getVertexType()==video::EVT_STANDARD);
 
74
 
 
75
    updatePosition();
 
76
    m_node = irr_driver->addMesh(m_mesh);
46
77
#ifdef DEBUG
47
 
    setName("rubber_band");
 
78
    std::string debug_name = m_owner->getIdent()+" (rubber-band)";
 
79
    m_node->setName(debug_name.c_str());
48
80
#endif
49
81
 
50
 
    // The call to update defines the actual coordinates, only the entries are added for now.
51
 
    vertices->add(0, 0, 0); vertices->add(0, 0, 0);
52
 
    vertices->add(0, 0, 0); vertices->add(0, 0, 0);
53
 
    m_attached_state = RB_TO_PLUNGER;
54
 
    updatePosition();
55
 
 
56
 
    sgVec3 norm;
57
 
    sgSetVec3(norm, 1/sqrt(2.0f), 0, 1/sqrt(2.0f));
58
 
    normals->add(norm);normals->add(norm);
59
 
    normals->add(norm);normals->add(norm);
60
 
 
61
 
    sgVec4 colour;
62
 
    sgSetVec4(colour, 0.7f, 0.0f, 0.0f, 0.3f);
63
 
    colours->add(colour);colours->add(colour);
64
 
    colours->add(colour);colours->add(colour);
65
 
    m_state = new ssgSimpleState();
66
 
    m_state->disable(GL_CULL_FACE);
67
 
    setState(m_state);
68
 
    //setState(material_manager->getMaterial("chrome.rgb")->getState());
69
 
 
70
 
    scene->add(this);
71
 
}   // RubberBand
72
 
 
73
 
// ----------------------------------------------------------------------------
74
 
/** Removes the rubber band from the scene. Is called when the plunger 
75
 
 *  explodes.
 
82
}   // RubberBand
 
83
 
 
84
// ----------------------------------------------------------------------------
 
85
RubberBand::~RubberBand()
 
86
{
 
87
    irr_driver->removeNode(m_node);
 
88
 
 
89
    // This mesh is self made and so not stored in the
 
90
    // mesh cache. So no reason to call
 
91
    // irr_driver->removeMesh(m_mesh);
 
92
    // But it was implicitly 'grabbed' during creation, so we have
 
93
    // to drop it here.
 
94
    m_mesh->drop();
 
95
}   // RubberBand
 
96
 
 
97
// ----------------------------------------------------------------------------
 
98
/** Updates the position of the rubber band. It especially sets the
 
99
 *  end position of the rubber band, i.e. the side attached to the plunger,
 
100
 *  track, or kart hit.
76
101
 */
77
 
void RubberBand::removeFromScene()
78
 
{
79
 
    scene->remove(this);
80
 
}   // removeFromScene
81
 
 
82
 
// ----------------------------------------------------------------------------
83
 
/** Updates the position of the rubber band. It especially sets the
84
 
 *  end position of the rubber band, i.e. the side attached to the plunger,
85
 
 *  track, or kart hit.
86
 
 */
87
102
void RubberBand::updatePosition()
88
103
{
89
 
    const Vec3 &k = m_owner.getXYZ();
90
 
 
91
 
    // Get the position to which the band is attached
92
 
    // ----------------------------------------------
93
 
    switch(m_attached_state)
94
 
    {
95
 
    case RB_TO_KART:    m_end_position = m_hit_kart->getXYZ(); break;
96
 
    case RB_TO_TRACK:   m_end_position = m_hit_position;       break;
97
 
    case RB_TO_PLUNGER: m_end_position = m_plunger->getXYZ();
98
 
                        checkForHit(k, m_end_position);        break;
99
 
    }   // switch(m_attached_state);
100
 
 
101
 
    // Update the rubber band positions
102
 
    // --------------------------------
103
 
    // Todo: make height dependent on length (i.e. rubber band gets
104
 
    // thinner). And call explosion if the band is too long.
105
 
    const float hh=.1f;  // half height of the band
106
 
    const Vec3 &p=m_end_position;  // for shorter typing
107
 
    float *f = vertices->get(0);
108
 
    f[0] = p.getX()-hh; f[1] = p.getY(); f[2] = p.getZ()-hh;
109
 
    f = vertices->get(1);
110
 
    f[0] = p.getX()+hh; f[1] = p.getY(); f[2] = p.getZ()+hh;
111
 
    f = vertices->get(2);
112
 
    f[0] = k.getX()+hh; f[1] = k.getY(); f[2] = k.getZ()+hh;
113
 
    f = vertices->get(3);
114
 
    f[0] = k.getX()-hh; f[1] = k.getY(); f[2] = k.getZ()-hh;
115
 
    dirtyBSphere();
116
 
}   // updatePosition
117
 
 
 
104
    const Vec3 &k = m_owner->getXYZ();
 
105
 
 
106
    // Get the position to which the band is attached
 
107
    // ----------------------------------------------
 
108
    switch(m_attached_state)
 
109
    {
 
110
    case RB_TO_KART:    m_end_position = m_hit_kart->getXYZ(); break;
 
111
    case RB_TO_TRACK:   m_end_position = m_hit_position;       break;
 
112
    case RB_TO_PLUNGER: m_end_position = m_plunger->getXYZ();
 
113
                        checkForHit(k, m_end_position);        break;
 
114
    }   // switch(m_attached_state);
 
115
 
 
116
    // Update the rubber band positions
 
117
    // --------------------------------
 
118
    // Todo: make height dependent on length (i.e. rubber band gets
 
119
    // thinner). And call explosion if the band is too long.
 
120
    const float hh=.1f;  // half height of the band
 
121
    const Vec3 &p=m_end_position;  // for shorter typing
 
122
    irr::video::S3DVertex* v=(video::S3DVertex*)m_buffer->getVertices();
 
123
    v[0].Pos.X = p.getX()-hh; v[0].Pos.Y=p.getY(); v[0].Pos.Z = p.getZ()-hh;
 
124
    v[1].Pos.X = p.getX()+hh; v[1].Pos.Y=p.getY(); v[1].Pos.Z = p.getZ()+hh;
 
125
    v[2].Pos.X = k.getX()+hh; v[2].Pos.Y=k.getY(); v[2].Pos.Z = k.getZ()+hh;
 
126
    v[3].Pos.X = k.getX()-hh; v[3].Pos.Y=k.getY(); v[3].Pos.Z = k.getZ()-hh;
 
127
    m_buffer->recalculateBoundingBox();
 
128
    m_mesh->setBoundingBox(m_buffer->getBoundingBox());
 
129
}   // updatePosition
 
130
 
118
131
// ----------------------------------------------------------------------------
119
132
/** Updates the rubber band. It takes the new position of the kart and the
120
133
 *  plunger, and sets the quad representing the rubber band appropriately.
124
137
 */
125
138
void RubberBand::update(float dt)
126
139
{
127
 
    if(m_owner.isEliminated())
 
140
    if(m_owner->isEliminated())
128
141
    {
129
142
        // Rubber band snaps
130
143
        m_plunger->hit(NULL);
134
147
    }
135
148
 
136
149
    updatePosition();
137
 
    const Vec3 &k = m_owner.getXYZ();
138
 
    
 
150
    const Vec3 &k = m_owner->getXYZ();
 
151
 
139
152
    // Check for rubber band snapping
140
153
    // ------------------------------
141
154
    float l = (m_end_position-k).length2();
142
 
    float max_len = m_owner.getKartProperties()->getRubberBandMaxLength();
 
155
    float max_len = m_owner->getKartProperties()->getRubberBandMaxLength();
143
156
    if(l>max_len*max_len)
144
157
    {
145
158
        // Rubber band snaps
152
165
    // ----------------------------
153
166
    if(m_attached_state!=RB_TO_PLUNGER)
154
167
    {
155
 
        float force = m_owner.getKartProperties()->getRubberBandForce();
 
168
        float force = m_owner->getKartProperties()->getRubberBandForce();
156
169
        Vec3 diff   = m_end_position-k;
157
170
        
158
171
        // detach rubber band if kart gets very close to hit point
166
179
        }
167
180
        
168
181
        diff.normalize();   // diff can't be zero here
169
 
        m_owner.getBody()->applyCentralForce(diff*force);
 
182
        m_owner->getBody()->applyCentralForce(diff*force);
 
183
        m_owner->increaseMaxSpeed(MaxSpeed::MS_INCREASE_RUBBER,
 
184
            m_owner->getKartProperties()->getRubberBandSpeedIncrease(),
 
185
            /*duration*/0.1f, 
 
186
            m_owner->getKartProperties()->getRubberBandFadeOutTime());
170
187
        if(m_attached_state==RB_TO_KART)
171
188
            m_hit_kart->getBody()->applyCentralForce(diff*(-force));
172
189
    }
185
202
    short int old_kart_group=0;
186
203
 
187
204
    // If the owner is being rescued, the broadphase handle does not exist!
188
 
    if(m_owner.getBody()->getBroadphaseHandle())
189
 
        old_kart_group = m_owner.getBody()->getBroadphaseHandle()->m_collisionFilterGroup;
 
205
    if(m_owner->getBody()->getBroadphaseHandle())
 
206
        old_kart_group = m_owner->getBody()->getBroadphaseHandle()->m_collisionFilterGroup;
190
207
    m_plunger->getBody()->getBroadphaseHandle()->m_collisionFilterGroup = 0;
191
 
    if(m_owner.getBody()->getBroadphaseHandle())
192
 
        m_owner.getBody()->getBroadphaseHandle()->m_collisionFilterGroup = 0;
 
208
    if(m_owner->getBody()->getBroadphaseHandle())
 
209
        m_owner->getBody()->getBroadphaseHandle()->m_collisionFilterGroup = 0;
193
210
 
194
211
    // Do the raycast
195
 
    RaceManager::getWorld()->getPhysics()->getPhysicsWorld()->rayTest(k, p, 
196
 
                                                                      ray_callback);
 
212
    World::getWorld()->getPhysics()->getPhysicsWorld()->rayTest(k, p, 
 
213
                                                                ray_callback);
197
214
    // Reset collision groups
198
215
    m_plunger->getBody()->getBroadphaseHandle()->m_collisionFilterGroup = old_plunger_group;
199
 
    if(m_owner.getBody()->getBroadphaseHandle())
200
 
        m_owner.getBody()->getBroadphaseHandle()->m_collisionFilterGroup = old_kart_group;
 
216
    if(m_owner->getBody()->getBroadphaseHandle())
 
217
        m_owner->getBody()->getBroadphaseHandle()->m_collisionFilterGroup = old_kart_group;
201
218
    if(ray_callback.HasHit())
202
219
    {
203
220
        Vec3 pos(ray_callback.m_hitPointWorld);
228
245
    {
229
246
        m_hit_kart       = kart_hit;
230
247
        m_attached_state = RB_TO_KART;
 
248
 
 
249
        RaceGUIBase* gui = World::getWorld()->getRaceGUI();
 
250
        irr::core::stringw hit_message;
 
251
        hit_message += StringUtils::insertValues(getPlungerString(),
 
252
                                                 kart_hit->getName().c_str(),
 
253
                                                 m_owner->getName().c_str()
 
254
                                                ).c_str();
 
255
        gui->addMessage(hit_message, NULL, 3.0f, 40, video::SColor(255, 255, 255, 255), false);
231
256
        return;
232
257
    }
233
258