From 10ea91e758045500af1ec7d6785568cb629e7957 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Tue, 27 Apr 2010 22:43:44 +0000 Subject: [PATCH] Made bubble gum disappear (after a certain number of hits, set in stk_config.xml). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@5294 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- data/stk_config.xml | 3 +++ src/config/stk_config.cpp | 7 ++++++ src/config/stk_config.hpp | 2 ++ src/items/item.cpp | 33 +++++++++++++++---------- src/items/item.hpp | 21 +++++++++++++++- src/items/item_manager.cpp | 50 +++++++++++++++++++++++++++++--------- src/items/item_manager.hpp | 2 +- src/items/powerup.cpp | 36 ++++++++++++++++++++++++--- src/karts/kart.cpp | 4 +-- 9 files changed, 125 insertions(+), 33 deletions(-) diff --git a/data/stk_config.xml b/data/stk_config.xml index fb3ae264d..2629dc4e1 100644 --- a/data/stk_config.xml +++ b/data/stk_config.xml @@ -68,6 +68,9 @@ Order: item, banana, big-nitro, small-nitro, bubble-bum --> + + + diff --git a/src/config/stk_config.cpp b/src/config/stk_config.cpp index d3d41ac80..7681a0d7f 100644 --- a/src/config/stk_config.cpp +++ b/src/config/stk_config.cpp @@ -103,6 +103,7 @@ void STKConfig::load(const std::string &filename) CHECK_NEG(m_zipper_speed_gain, "zipper-speed-gain" ); CHECK_NEG(m_zipper_max_speed_fraction, "zipper-max-speed-fraction" ); CHECK_NEG(m_item_switch_time, "item-switch-time" ); + CHECK_NEG(m_bubble_gum_counter, "bubblegum disappear counter"); CHECK_NEG(m_explosion_impulse, "explosion-impulse" ); CHECK_NEG(m_explosion_impulse_objects, "explosion-impulse-objects" ); CHECK_NEG(m_max_history, "max-history" ); @@ -137,6 +138,7 @@ void STKConfig::init_defaults() m_explosion_impulse = m_explosion_impulse_objects = m_delay_finish_time = m_skid_fadeout_time = m_near_ground = m_item_switch_time = UNDEFINED; + m_bubble_gum_counter = -100; m_max_karts = -100; m_gp_order = -100; m_max_history = -100; @@ -248,6 +250,11 @@ void STKConfig::getAllData(const XMLNode * root) switch_node->get("time", &m_item_switch_time); } + if(const XMLNode *bubble_gum_node= root->getNode("bubble-gum")) + { + bubble_gum_node->get("disappear-counter", &m_bubble_gum_counter); + } + if(const XMLNode *explosion_node= root->getNode("explosion")) { explosion_node->get("impulse", &m_explosion_impulse ); diff --git a/src/config/stk_config.hpp b/src/config/stk_config.hpp index fadb6a2c8..c10fe7152 100644 --- a/src/config/stk_config.hpp +++ b/src/config/stk_config.hpp @@ -63,6 +63,8 @@ public: float m_zipper_max_speed_fraction;/**m_bubble_gum_counter + : -1 ; m_original_mesh = mesh; m_node = irr_driver->addMesh(mesh); m_node->setPosition(xyz.toIrrVector()); @@ -62,7 +65,7 @@ void Item::setType(ItemType type) */ void Item::switchTo(ItemType type, scene::IMesh *mesh) { - m_original_type = m_type; + m_original_type = m_type; setType(type); m_node->setMesh(mesh); } // switchTo @@ -97,9 +100,12 @@ Item::~Item() */ void Item::reset() { - m_collected = false; - m_time_till_return = 0.0f; - m_deactive_time = 0.0f; + m_collected = false; + m_time_till_return = 0.0f; + m_deactive_time = 0.0f; + m_disappear_counter = m_type==ITEM_BUBBLEGUM + ? stk_config->m_bubble_gum_counter + : -1 ; if(m_original_type!=ITEM_NONE) { setType(m_original_type); @@ -168,8 +174,9 @@ void Item::collected(const Kart *kart, float t) { m_collected = true; m_event_handler = kart; - if(m_type==ITEM_BUBBLEGUM) + if(m_type==ITEM_BUBBLEGUM && m_disappear_counter>0) { + m_disappear_counter --; // Deactivates the item for a certain amount of time. It is used to // prevent bubble gum from hitting a kart over and over again (in each // frame) by giving it time to drive away. diff --git a/src/items/item.hpp b/src/items/item.hpp index 6ea3e656e..7d10e36f4 100644 --- a/src/items/item.hpp +++ b/src/items/item.hpp @@ -92,7 +92,13 @@ private: /** Optionally if item was placed by a kart, a timer can be used to * temporarly deactivate collision so a kart is not hit by its own item */ float m_deactive_time; - + + /** Counts how often an item is used before it disappears. Used for + * bubble gum to make them disappear after a while. A value >0 + * indicates that the item still exists, =0 that the item can be + * deleted, and <0 that the item will never be deleted. */ + int m_disappear_counter; + void setType(ItemType type); public: Item (ItemType type, const Vec3& xyz, const Vec3& normal, @@ -113,9 +119,22 @@ public: } // hitKart // ------------------------------------------------------------------------ + /** Returns the index of this item in the item manager list. */ unsigned int getItemId() const { return m_item_id; } + // ------------------------------------------------------------------------ + /** Returns the type of this item. */ ItemType getType() const { return m_type; } + // ------------------------------------------------------------------------ + /** Returns true if this item is currently collected. */ bool wasCollected() const { return m_collected;} + // ------------------------------------------------------------------------ + /** Returns true if this item is used up and can be removed. */ + bool isUsedUp() const {return m_disappear_counter==0; } + // ------------------------------------------------------------------------ + /** Returns true if this item can be used up, and therefore needs to + * be removed when the game is reset. */ + bool canBeUsedUp() const {return m_disappear_counter>-1; } + // ------------------------------------------------------------------------ void setParent(Kart* parent); void reset(); void switchTo(ItemType type, scene::IMesh *mesh); diff --git a/src/items/item_manager.cpp b/src/items/item_manager.cpp index 61b3693be..96228f7fb 100644 --- a/src/items/item_manager.cpp +++ b/src/items/item_manager.cpp @@ -138,15 +138,25 @@ void ItemManager::loadDefaultItems() Item* ItemManager::newItem(Item::ItemType type, const Vec3& xyz, const Vec3 &normal, Kart *parent) { + // Find where the item can be stored in the index list: either in a + // previously deleted entry, otherwise at the end. + int index = -1; + for(index=m_all_items.size()-1; index>=0 && m_all_items[index]; index--) {} + + if(index==-1) index = m_all_items.size(); Item* item; - item = new Item(type, xyz, normal, m_item_mesh[type], m_all_items.size()); + item = new Item(type, xyz, normal, m_item_mesh[type], index); if(parent != NULL) item->setParent(parent); if(m_switch_time>=0) { Item::ItemType new_type = m_switch_to[item->getType()]; item->switchTo(new_type, m_item_mesh[(int)new_type]); } - m_all_items.push_back(item); + if(index<(int)m_all_items.size()) + m_all_items[index] = item; + else + m_all_items.push_back(item); + return item; } // newItem @@ -157,12 +167,17 @@ Item* ItemManager::newItem(Item::ItemType type, const Vec3& xyz, void ItemManager::collectedItem(int item_id, Kart *kart, int add_info) { Item *item=m_all_items[item_id]; + assert(item); item->collected(kart); kart->collectedItem(*item, add_info); } // collectedItem //----------------------------------------------------------------------------- -void ItemManager::hitItem(Kart* kart) +/** Checks if any item was collected by the given kart. This function calls + * collectedItem if an item was collected. + * \param kart Pointer to the kart. + */ +void ItemManager::checkItemHit(Kart* kart) { // Only do this on the server if(network_manager->getMode()==NetworkManager::NW_CLIENT) return; @@ -170,13 +185,13 @@ void ItemManager::hitItem(Kart* kart) for(AllItemTypes::iterator i =m_all_items.begin(); i!=m_all_items.end(); i++) { - if((*i)->wasCollected()) continue; + if((!*i) || (*i)->wasCollected()) continue; if((*i)->hitKart(kart)) { collectedItem(i-m_all_items.begin(), kart); } // if hit } // for m_all_items -} // hitItem +} // checkItemHit //----------------------------------------------------------------------------- /** Remove all item instances, and the track specific models. This is used @@ -187,7 +202,8 @@ void ItemManager::cleanup() for(AllItemTypes::iterator i =m_all_items.begin(); i!=m_all_items.end(); i++) { - delete *i; + if(*i) + delete *i; } m_all_items.clear(); } // cleanup @@ -203,14 +219,17 @@ void ItemManager::reset() { for(AllItemTypes::iterator i =m_all_items.begin(); i!=m_all_items.end(); i++) - (*i)->switchBack(); + { + if(*i) (*i)->switchBack(); + } m_switch_time = -1.0f; } AllItemTypes::iterator i=m_all_items.begin(); while(i!=m_all_items.end()) { - if((*i)->getType()==Item::ITEM_BUBBLEGUM) + if(!*i) continue; + if((*i)->canBeUsedUp() || (*i)->getType()==Item::ITEM_BUBBLEGUM) { Item *b=*i; AllItemTypes::iterator i_next = m_all_items.erase(i); @@ -239,7 +258,7 @@ void ItemManager::update(float dt) for(AllItemTypes::iterator i =m_all_items.begin(); i!=m_all_items.end(); i++) { - (*i)->switchBack(); + if(*i) (*i)->switchBack(); } // for m_all_items } // m_switch_time < 0 } // m_switch_time>=0 @@ -247,7 +266,15 @@ void ItemManager::update(float dt) for(AllItemTypes::iterator i =m_all_items.begin(); i!=m_all_items.end(); i++) { - (*i)->update(dt); + if(*i) + { + (*i)->update(dt); + if( (*i)->isUsedUp()) + { + delete *i; + m_all_items[i-m_all_items.begin()] = NULL; + } // if usedUp + } // if *i } // for m_all_items } // update @@ -260,12 +287,11 @@ void ItemManager::switchItems() for(AllItemTypes::iterator i =m_all_items.begin(); i!=m_all_items.end(); i++) { + if(!*i) continue; Item::ItemType new_type = m_switch_to[(*i)->getType()]; if(m_switch_time<0) (*i)->switchTo(new_type, m_item_mesh[(int)new_type]); - // FIXME: if switch is used while items are switched: - // switch back - but that doesn't work properly yet else (*i)->switchBack(); } // for m_all_items diff --git a/src/items/item_manager.hpp b/src/items/item_manager.hpp index 3aa4c949b..00e15ea3f 100644 --- a/src/items/item_manager.hpp +++ b/src/items/item_manager.hpp @@ -60,7 +60,7 @@ public: Item* newItem (Item::ItemType type, const Vec3& xyz, const Vec3 &normal, Kart* parent=NULL); void update (float delta); - void hitItem (Kart* kart); + void checkItemHit (Kart* kart); void cleanup (); void reset (); void removeTextures (); diff --git a/src/items/powerup.cpp b/src/items/powerup.cpp index 4d05a7e63..ace27f1b8 100644 --- a/src/items/powerup.cpp +++ b/src/items/powerup.cpp @@ -34,9 +34,12 @@ //----------------------------------------------------------------------------- -Powerup::Powerup(Kart* kart_) +/** Constructor, stores the kart to which this powerup belongs. + * \param kart The kart to which this powerup belongs. + */ +Powerup::Powerup(Kart* kart) { - m_owner = kart_; + m_owner = kart; m_sound_use = NULL; reset(); } // Powerup @@ -50,6 +53,8 @@ Powerup::~Powerup() } // ~Powerup //----------------------------------------------------------------------------- +/** Resets the powerup, called at begin of a race. + */ void Powerup::reset() { m_type = POWERUP_NOTHING; @@ -61,6 +66,12 @@ void Powerup::reset() } // reset //----------------------------------------------------------------------------- +/** Sets the collected items. The number of items is increased if the same + * item is currently collected, otherwise replaces the existing item. It also + * sets item specific sounds. + * \param type Thew new type. + * \param n Number of items of the given type. + */ void Powerup::set(PowerupType type, int n) { if (m_type==type) @@ -113,6 +124,9 @@ void Powerup::set(PowerupType type, int n) } // set //----------------------------------------------------------------------------- +/** Returns the icon for the currently collected powerup. Used in the + * race_gui to display the collected item. + */ Material *Powerup::getIcon() const { // Check if it's one of the types which have a separate @@ -121,6 +135,8 @@ Material *Powerup::getIcon() const } //----------------------------------------------------------------------------- +/** Use (fire) this powerup. + */ void Powerup::use() { // Play custom kart sound when collectible is used @@ -136,7 +152,7 @@ void Powerup::use() m_number--; World *world = World::getWorld(); - RaceGUI* gui = World::getWorld()->getRaceGUI(); + RaceGUI* gui = world->getRaceGUI(); switch (m_type) { case POWERUP_ZIPPER: m_owner->handleZipper(); @@ -214,7 +230,7 @@ void Powerup::use() case POWERUP_PARACHUTE: { Kart* player_kart = NULL; - //Attach a parachutte(that last as twice as the + //Attach a parachutte(that last twice as long as the //one from the bananas) to all the karts that //are in front of this one. for(unsigned int i = 0 ; i < world->getNumKarts(); ++i) @@ -257,6 +273,18 @@ void Powerup::use() } // use //----------------------------------------------------------------------------- +/** This function is called when a bnous box is it. This function can be + * called on a server (in which case item and add_info are not used), + * or on a client, in which case the item and additional info is used + * to make sure server and clients are synched correctly. + * \param n + * \param item The item (bonux box) that was hit. This is necessary + * for servers so that the clients can be informed which item + * was collected. + * \param add_info Additional information. This is used for network games + * so that the server can overwrite which item is collectted + * (otherwise a random choice is done). + */ void Powerup::hitBonusBox(int n, const Item &item, int add_info) { World *world = World::getWorld(); diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index a17cf7653..472d76a78 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -537,7 +537,7 @@ void Kart::collectedItem(const Item &item, int add_info) // In wheelie style, karts get more items depending on energy, // in nitro mode it's only one item. int n = 1; - m_powerup.hitBonusBox(n, item,add_info); + m_powerup.hitBonusBox(n, item, add_info); break; } case Item::ITEM_BUBBLEGUM: @@ -769,7 +769,7 @@ void Kart::update(float dt) } // if there is material // Check if any item was hit. - item_manager->hitItem(this); + item_manager->checkItemHit(this); if(m_kart_properties->hasSkidmarks()) m_skidmarks->update(dt);