Added first version of switch collectable.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@4635 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2010-02-04 22:53:24 +00:00
parent 192fc34572
commit 8be9c3397a
16 changed files with 237 additions and 37 deletions

View File

@ -70,6 +70,9 @@ anvil-time is the time an anvil is active
zipper-time is the time a zipper is active
zipper-force is the additional zipper force
zipper-speed-gain is the one time additional speed
item-switch-time How long a switch is being effective.
switch-items for each item list the index of the item it is switched with.
Order: item, banana, big-nitro, small-nitro
-->
<attachment-parameters
@ -87,6 +90,8 @@ zipper-speed-gain is the one time additional speed
zipper-force="250.0"
zipper-speed-gain="4.5"
zipper-max-speed-fraction="2.0"
item-switch-time="5"
switch-items="1 0 1 1 4"
/>
<!-- GENERAL KART DEFAULTS

9
data/switch.collectable Normal file
View File

@ -0,0 +1,9 @@
;; -*- mode: lisp -*-
(tuxkart-collectable
(name "swap")
(mesh "zipper.b3d")
(icon "swap-icon.png")
)
;; EOF ;;

View File

@ -24,8 +24,9 @@
#include <sstream>
#include "io/file_manager.hpp"
//#include "lisp/parser.hpp"
#include "io/xml_node.hpp"
#include "items/item.hpp"
#include "items/item_manager.hpp"
#include "audio/music_information.hpp"
STKConfig* stk_config=0;
@ -80,6 +81,11 @@ void STKConfig::load(const std::string &filename)
fprintf(stderr,"No follow leader interval(s) defined in stk_config");
exit(-1);
}
if(m_switch_items.size()!=Item::ITEM_LAST-Item::ITEM_FIRST+1)
{
fprintf(stderr,"No item switches defined in stk_config");
exit(-1);
}
if(m_menu_background.size()==0)
{
fprintf(stderr,"No menu background defined in stk_config");
@ -104,6 +110,7 @@ void STKConfig::load(const std::string &filename)
CHECK_NEG(m_zipper_force, "zipper-force" );
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_final_camera_time, "final-camera-time" );
CHECK_NEG(m_explosion_impulse, "explosion-impulse" );
CHECK_NEG(m_explosion_impulse_objects, "explosion-impulse-objects" );
@ -119,6 +126,7 @@ void STKConfig::load(const std::string &filename)
CHECK_NEG(m_music_credit_time, "music-credit-time" );
m_kart_properties.checkAllSet(filename);
item_manager->setSwitchItems(m_switch_items);
} // load
// -----------------------------------------------------------------------------
@ -137,7 +145,8 @@ void STKConfig::init_defaults()
m_zipper_max_speed_fraction = m_music_credit_time =
m_explosion_impulse = m_explosion_impulse_objects =
m_delay_finish_time = m_skid_fadeout_time =
m_final_camera_time = m_near_ground = UNDEFINED;
m_final_camera_time = m_near_ground =
m_item_switch_time = UNDEFINED;
m_max_karts = -100;
m_grid_order = -100;
m_max_history = -100;
@ -150,6 +159,7 @@ void STKConfig::init_defaults()
m_enable_networking = true;
m_scores.clear();
m_leader_intervals.clear();
m_switch_items.clear();
} // init_defaults
//-----------------------------------------------------------------------------
@ -227,11 +237,13 @@ void STKConfig::getAllData(const XMLNode * root)
node->get("bomb-time", &m_bomb_time);
node->get("bomb-time-increase", &m_bomb_time_increase);
node->get("leader-intervals", &m_leader_intervals);
node->get("switch-items", &m_switch_items);
node->get("anvil-time", &m_anvil_time);
node->get("zipper-time", &m_zipper_time);
node->get("zipper-force", &m_zipper_force);
node->get("zipper-speed-gain", &m_zipper_speed_gain);
node->get("zipper-max-speed-fraction", &m_zipper_max_speed_fraction);
node->get("item-switch-time", &m_item_switch_time);
node = root -> getNode("misc-defaults");

View File

@ -56,6 +56,7 @@ public:
float m_zipper_speed_gain; /**<Initial one time speed gain. */
float m_zipper_max_speed_fraction;/**<Fraction of max speed allowed past
regular max speed */
float m_item_switch_time; /**< Time items will be switched. */
float m_final_camera_time; /**<Time for the movement of the final
* camera. */
float m_explosion_impulse; /**<Impulse affecting each non-hit kart.*/
@ -85,6 +86,7 @@ public:
std::vector<float>
m_leader_intervals; /**<Interval in follow the leader till
last kart is reomved. */
std::vector<int> m_switch_items; /**< How to switch items. */
std::vector<int>
m_scores; /**<Scores depending on position. */

View File

@ -460,7 +460,7 @@ scene::IParticleSystemSceneNode *IrrDriver::addParticleNode(bool default_emitter
* since the node is not optimised.
* \param mesh The mesh to add.
*/
scene::ISceneNode *IrrDriver::addMesh(scene::IMesh *mesh)
scene::IMeshSceneNode *IrrDriver::addMesh(scene::IMesh *mesh)
{
return m_scene_manager->addMeshSceneNode(mesh);
} // addMesh

View File

@ -99,7 +99,7 @@ public:
scene::ISceneNode *addWaterNode(scene::IMesh *mesh, float wave_height,
float wave_speed, float wave_length);
scene::ISceneNode *addOctTree(scene::IMesh *mesh);
scene::ISceneNode *addMesh(scene::IMesh *mesh);
scene::IMeshSceneNode*addMesh(scene::IMesh *mesh);
scene::ISceneNode *addBillboard(const core::dimension2d< f32 > size, video::ITexture *texture, scene::ISceneNode* parent=NULL);
scene::IParticleSystemSceneNode

View File

@ -35,6 +35,7 @@
#include "guiengine/screen.hpp"
#include "input/device_manager.hpp"
#include "input/input.hpp"
#include "items/item_manager.hpp"
#include "items/projectile_manager.hpp"
#include "karts/kart.hpp"
#include "karts/player_kart.hpp"
@ -120,6 +121,13 @@ void InputManager::handleStaticAction(int key, int value)
kart->setPowerup(POWERUP_CAKE, 10000);
}
break;
case KEY_F4:
if (race_manager->getNumPlayers() ==1 )
{
Kart* kart = RaceManager::getPlayerKart(0);
kart->setPowerup(POWERUP_SWITCH, 10000);
}
break;
case KEY_F11:
// FIXME: at this stage you can only switch back from debug view to normal
// view, if switching again you noly get a grey screen - some opengl settings

View File

@ -31,13 +31,16 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
m_rotate = rotate;
m_event_handler = NULL;
m_deactive_time = 0;
m_normal = normal;
// Sets heading to 0, and sets pitch and roll depending on the normal. */
Vec3 hpr = Vec3(0, normal);
m_coord = Coord(xyz, hpr);
m_item_id = item_id;
m_type = type;
m_original_type = ITEM_NONE;
m_collected = false;
m_time_till_return = 0.0f; // not strictly necessary, see isCollected()
m_original_mesh = mesh;
m_node = irr_driver->addMesh(mesh);
// If lighting would be enabled certain items (esp. bananas)
// don't look smooth, so for now generally disable lighting
@ -48,6 +51,31 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
} // Item
//-----------------------------------------------------------------------------
/** Changes this item to be a new type for a certain amount of time.
* \param type New type of this item.
* \param mesh Mesh to use to display this item.
*/
void Item::switchTo(ItemType type, scene::IMesh *mesh)
{
m_original_type = m_type;
m_type = type;
m_node->setMesh(mesh);
} // switchTo
//-----------------------------------------------------------------------------
/** Switch backs to the original item.
*/
void Item::switchBack()
{
assert(m_original_type!=ITEM_NONE);
m_type = m_original_type;
m_original_type = ITEM_NONE;
m_node->setMesh(m_original_mesh);
} // switchBack
//-----------------------------------------------------------------------------
/** Removes an item.
*/
Item::~Item()
{
irr_driver->removeNode(m_node);
@ -55,13 +83,25 @@ Item::~Item()
} // ~Item
//-----------------------------------------------------------------------------
/** Resets before a race (esp. if a race is restarted).
*/
void Item::reset()
{
m_collected = false;
m_time_till_return = 0.0f;
m_deactive_time = 0.0f;
if(m_original_type!=ITEM_NONE)
{
m_type = m_original_type;
m_original_type = ITEM_NONE;
}
} // reset
//-----------------------------------------------------------------------------
/** Sets which karts dropped an item. This is used to avoid that a kart is
* affected by its own items.
* \param parent Kart that dropped the item.
*/
void Item::setParent(Kart* parent)
{
m_event_handler = parent;
@ -69,13 +109,17 @@ void Item::setParent(Kart* parent)
}
//-----------------------------------------------------------------------------
void Item::update(float delta)
/** Updated the item - rotates it, takes care of items coming back into
* the game after it has been collected.
* \param dt Time step size.
*/
void Item::update(float dt)
{
if(m_event_handler != NULL && m_deactive_time > 0) m_deactive_time -= delta;
if(m_event_handler != NULL && m_deactive_time > 0) m_deactive_time -= dt;
if(m_collected)
{
m_time_till_return -= delta;
m_time_till_return -= dt;
if ( m_time_till_return > 0 )
{
Vec3 hell(m_coord.getXYZ());
@ -95,10 +139,22 @@ void Item::update(float delta)
if(!m_rotate) return;
// have it rotate
Vec3 rotation(delta*M_PI, 0, 0);
Vec3 rotation(dt*M_PI, 0, 0);
m_coord.setHPR(m_coord.getHPR()+rotation);
m_node->setRotation(m_coord.getHPR().toIrrHPR());
m_node->setPosition(m_coord.getXYZ().toIrrVector());
return;
static float t=0;
t += dt;
btQuaternion q(Vec3(0,0,1), t*0.1f);
btQuaternion q_orig(m_normal, 0);
btQuaternion result=q+q_orig;
btMatrix3x3 m(result);
float y, p, r;
m.getEuler(y, p, r);
m_node->setRotation(Vec3(y, p, r).toIrrHPR());
}
} // update

View File

@ -30,28 +30,52 @@ using namespace irr;
class Item
{
public:
// The list of all items. Important for the switch item function:
// bubblegum must be the last item (since bubble gum can't be
// switched with any other item, since it's a different objecct).
enum ItemType
{
ITEM_FIRST,
ITEM_BONUS_BOX = ITEM_FIRST,
ITEM_BANANA,
ITEM_GOLD_COIN,
ITEM_SILVER_COIN,
ITEM_NITRO_BIG,
ITEM_NITRO_SMALL,
ITEM_BUBBLEGUM,
ITEM_LAST = ITEM_BUBBLEGUM
ITEM_LAST = ITEM_BUBBLEGUM,
ITEM_COUNT,
ITEM_NONE
};
private:
ItemType m_type; // Item type
bool m_collected; // true if item was collected & is not displayed
float m_time_till_return; // time till a collected item reappears
Coord m_coord; // Original coordinates, used mainly when
// collected items reappear.
/** Scene node of this item. */
scene::ISceneNode *m_node;
unsigned int m_item_id; // index in item_manager field
/** Item type. */
ItemType m_type;
bool m_rotate; // set to false if item should not rotate
/** If the item is switched, this contains the original type.
* It is ITEM_NONE if the item is not switched. */
ItemType m_original_type;
/** True if item was collected & is not displayed. */
bool m_collected;
/** Time till a collected item reappears. */
float m_time_till_return;
/** Original coordinates, used mainly when collected items reappear. */
Coord m_coord;
/** Scene node of this item. */
scene::IMeshSceneNode *m_node;
/** Stores the original mesh in order to reset it. */
scene::IMesh *m_original_mesh;
Vec3 m_normal;
/** Index in item_manager field. */
unsigned int m_item_id;
/** Set to false if item should not rotate. */
bool m_rotate;
/** optionally, set this if this item was laid by a particular kart. in this case,
the 'm_deactive_time' will also be set - see below. */
@ -92,6 +116,8 @@ public:
bool wasCollected() const { return m_collected;}
void setParent(Kart* parent);
void reset();
void switchTo(ItemType type, scene::IMesh *mesh);
void switchBack();
}; // class Item
#endif

View File

@ -23,6 +23,7 @@
#include <string>
#include <sstream>
#include "config/stk_config.hpp"
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
@ -43,8 +44,26 @@ ItemManager::ItemManager()
{
m_all_meshes.clear();
// The actual loading is done in loadDefaultItems
// Prepare the switch to array, which stores which item should be
// switched to what other item. Initialise it with a mapping that
// each item is switched to itself, so basically a no-op.
m_switch_to.reserve(Item::ITEM_COUNT);
for(unsigned int i=Item::ITEM_FIRST; i<Item::ITEM_COUNT; i++)
m_switch_to.push_back((Item::ItemType)i);
} // ItemManager
//-----------------------------------------------------------------------------
/** Sets which objects is getting switched to what.
* \param switch A mapping of items types to item types for the mapping.
* must contain one entry for each item.
*/
void ItemManager::setSwitchItems(const std::vector<int> &switch_items)
{
for(unsigned int i=Item::ITEM_FIRST; i<Item::ITEM_COUNT; i++)
m_switch_to[i]=(Item::ItemType)stk_config->m_switch_items[i];
} // setSwitchItems
//-----------------------------------------------------------------------------
void ItemManager::removeTextures()
{
@ -107,8 +126,8 @@ void ItemManager::setDefaultItemStyle()
std::string DEFAULT_NAMES[Item::ITEM_LAST - Item::ITEM_FIRST +1];
DEFAULT_NAMES[Item::ITEM_BONUS_BOX] = "gift-box";
DEFAULT_NAMES[Item::ITEM_BANANA] = "banana";
DEFAULT_NAMES[Item::ITEM_GOLD_COIN] = "nitrotank-big";
DEFAULT_NAMES[Item::ITEM_SILVER_COIN] = "nitrotank-small";
DEFAULT_NAMES[Item::ITEM_NITRO_BIG] = "nitrotank-big";
DEFAULT_NAMES[Item::ITEM_NITRO_SMALL] = "nitrotank-small";
DEFAULT_NAMES[Item::ITEM_BUBBLEGUM] = "bubblegum";
bool bError=0;
@ -143,6 +162,13 @@ void ItemManager::setDefaultItemStyle()
} // setDefaultItemStyle
//-----------------------------------------------------------------------------
/** Creates a new item.
* \param type Type of the item.
* \param xyz Position of the item.
* \param normal The normal of the terrain to set roll and pitch.
* \param parent In case of a dropped item used to avoid that a kart
* is affected by its own items.
*/
Item* ItemManager::newItem(Item::ItemType type, const Vec3& xyz,
const Vec3 &normal, Kart *parent)
{
@ -258,6 +284,8 @@ void ItemManager::reset()
i++;
}
} // for i
m_switch_time = -1;
} // reset
//-----------------------------------------------------------------------------
@ -299,14 +327,51 @@ void ItemManager::setStyle()
} // setStyle
//-----------------------------------------------------------------------------
void ItemManager::update(float delta)
void ItemManager::update(float dt)
{
// If switch time is over, switch all items back
if(m_switch_time>=0)
{
m_switch_time -= dt;
if(m_switch_time<0)
{
for(AllItemTypes::iterator i =m_all_items.begin();
i!=m_all_items.end(); i++)
{
(*i)->switchBack();
} // for m_all_items
} // m_switch_time < 0
} // m_switch_time>=0
for(AllItemTypes::iterator i =m_all_items.begin();
i!=m_all_items.end(); i++)
{
(*i)->update(dt);
} // for m_all_items
} // update
//-----------------------------------------------------------------------------
/** Switches all items: boxes become bananas and vice versa for a certain
* amount of time (as defined in stk_config.xml.
*/
void ItemManager::switchItems()
{
for(AllItemTypes::iterator i =m_all_items.begin();
i!=m_all_items.end(); i++)
{
(*i)->update(delta);
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
} // delta
m_switch_time = stk_config->m_item_switch_time;
} // switchItems
//-----------------------------------------------------------------------------
void ItemManager::loadItemStyle(const std::string filename)
@ -328,8 +393,8 @@ void ItemManager::loadItemStyle(const std::string filename)
}
setItem(item_node, "red", Item::ITEM_BONUS_BOX );
setItem(item_node, "green", Item::ITEM_BANANA );
setItem(item_node, "gold" ,Item::ITEM_GOLD_COIN );
setItem(item_node, "silver",Item::ITEM_SILVER_COIN);
setItem(item_node, "gold" ,Item::ITEM_NITRO_BIG );
setItem(item_node, "silver",Item::ITEM_NITRO_SMALL);
delete root;
} // loadItemStyle

View File

@ -43,6 +43,13 @@ private:
std::map<std::string,scene::IMesh*> m_all_meshes;
std::string m_user_filename;
/** Remaining time that items should remain switched. */
float m_switch_time;
/** What item is item is switched to. */
std::vector<Item::ItemType> m_switch_to;
void setDefaultItemStyle();
void setItem(const lisp::Lisp *item_node, const char *colour,
Item::ItemType type);
@ -62,6 +69,8 @@ public:
void setUserFilename (char *s) {m_user_filename=s;}
void collectedItem (int item_id, Kart *kart,
int add_info=-1);
void switchItems ();
void setSwitchItems(const std::vector<int> &switch_items);
void setStyle ();
scene::IMesh* getItemModel (Item::ItemType type)
{return m_item_mesh[type];}

View File

@ -129,6 +129,9 @@ void Powerup::use()
{
case POWERUP_ZIPPER: m_owner->handleZipper();
break ;
case POWERUP_SWITCH:
item_manager->switchItems();
break;
case POWERUP_CAKE:
case POWERUP_BOWLING:
case POWERUP_PLUNGER:

View File

@ -46,6 +46,7 @@ initPowerupType ict[]=
{POWERUP_BUBBLEGUM, "bubblegum.xml" },
{POWERUP_CAKE, "cake.projectile" },
{POWERUP_ANVIL, "anvil.collectable" },
{POWERUP_SWITCH, "switch.collectable" },
{POWERUP_PARACHUTE, "parachute.collectable" },
{POWERUP_PLUNGER, "plunger.projectile" },
{POWERUP_MAX, "" },
@ -69,6 +70,8 @@ void PowerupManager::removeTextures()
} // removeTextures
//-----------------------------------------------------------------------------
/** Loads all projectiles from the powerup.xml file.
*/
void PowerupManager::loadPowerups()
{
for(int i=0; ict[i].powerup != POWERUP_MAX; i++)

View File

@ -33,6 +33,7 @@ class Material;
enum PowerupType {POWERUP_NOTHING,
POWERUP_BUBBLEGUM, POWERUP_CAKE,
POWERUP_BOWLING, POWERUP_ZIPPER, POWERUP_PLUNGER,
POWERUP_SWITCH,
POWERUP_PARACHUTE, POWERUP_ANVIL, //powerup.cpp assumes these two come last
POWERUP_MAX};

View File

@ -426,8 +426,8 @@ void Kart::collectedItem(const Item &item, int add_info)
m_attachment.hitBanana(item, add_info);
break;
case Item::ITEM_SILVER_COIN: m_collected_energy++ ; break;
case Item::ITEM_GOLD_COIN : m_collected_energy += 3 ; break;
case Item::ITEM_NITRO_SMALL: m_collected_energy++; break;
case Item::ITEM_NITRO_BIG: m_collected_energy += 3; break;
case Item::ITEM_BONUS_BOX :
{
// In wheelie style, karts get more items depending on energy,
@ -451,7 +451,7 @@ void Kart::collectedItem(const Item &item, int add_info)
// functions (hit{Red,Green}Item), so only coins need to be
// stored here.
if(network_manager->getMode()==NetworkManager::NW_SERVER &&
(type==Item::ITEM_SILVER_COIN || type==Item::ITEM_GOLD_COIN) )
(type==Item::ITEM_NITRO_BIG || type==Item::ITEM_NITRO_SMALL) )
{
race_state->itemCollected(getWorldKartId(), item.getItemId());
}

View File

@ -700,8 +700,8 @@ void Track::loadTrackModel(unsigned int mode_id)
Item::ItemType type;
if (name=="banana" ) type = Item::ITEM_BANANA;
else if(name=="item" ) type = Item::ITEM_BONUS_BOX;
else if(name=="small-nitro") type = Item::ITEM_SILVER_COIN;
else type = Item::ITEM_GOLD_COIN;
else if(name=="small-nitro") type = Item::ITEM_NITRO_SMALL;
else type = Item::ITEM_NITRO_BIG;
Vec3 xyz;
// Set some kind of default in case Z is not defined in the file
// (with the new track exporter it always is defined anyway).
@ -905,7 +905,8 @@ void Track::itemCommand(const Vec3 &xyz, Item::ItemType type,
// Don't tilt the items, since otherwise the rotation will look odd,
// i.e. the items will not rotate around the normal, but 'wobble'
// around.
Vec3 normal(0, 0, 0.0f);
//Vec3 normal(0.7, 0, 0.7);
Vec3 normal(0, 0, 1);
item_manager->newItem(type, loc, normal);
} // itemCommand