A player can now remove himself by pressing rescue at the kart selection screen

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3733 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria 2009-07-11 19:24:42 +00:00
parent 0e890dc5cc
commit ab4cdcae00
10 changed files with 147 additions and 17 deletions

View File

@ -73,6 +73,10 @@ public:
m_player = player;
m_device = NULL;
}
~ActivePlayer()
{
setDevice(NULL);
}
Player* getPlayer()
{
@ -86,6 +90,8 @@ public:
InputDevice* getDevice() const { return m_device; }
void setDevice(InputDevice* device)
{
if (m_device != NULL) m_device->setPlayer(NULL);
m_device = device;
if(device != NULL)

View File

@ -45,11 +45,14 @@ namespace StateManager
class PlayerKartWidget;
// ref only since we're adding them to a Screen, and the Screen will take ownership of these widgets
// FIXME : delete these objects when leaving the screen (especially when suing escape)
ptr_vector<PlayerKartWidget, REF> g_player_karts;
class PlayerKartWidget : public Widget
{
ActivePlayer* m_associatedPlayer;
float x_speed, y_speed, w_speed, h_speed;
public:
LabelWidget* playerIDLabel;
SpinnerWidget* playerName;
@ -69,7 +72,11 @@ namespace StateManager
PlayerKartWidget(ActivePlayer* associatedPlayer, Widget* area, const int playerID) : Widget()
{
m_associatedPlayer = associatedPlayer;
x_speed = 1.0f;
y_speed = 1.0f;
w_speed = 1.0f;
h_speed = 1.0f;
this->playerID = playerID;
// FIXME : if a player removes itself, all IDs need to be updated
@ -140,6 +147,32 @@ namespace StateManager
//kartName->setParent(this);
m_children.push_back(kartName);
}
~PlayerKartWidget()
{
if (playerIDLabel->getIrrlichtElement() != NULL)
playerIDLabel->getIrrlichtElement()->remove();
if (playerName->getIrrlichtElement() != NULL)
playerName->getIrrlichtElement()->remove();
if (modelView->getIrrlichtElement() != NULL)
modelView->getIrrlichtElement()->remove();
if (kartName->getIrrlichtElement() != NULL)
kartName->getIrrlichtElement()->remove();
}
void setPlayerID(const int newPlayerID)
{
if (StateManager::getActivePlayers().get(newPlayerID) != m_associatedPlayer)
{
std::cerr << "Internal inconsistency, PlayerKartWidget has IDs and pointers that do not correspond to one player\n";
assert(false);
}
playerID = newPlayerID;
}
virtual void add()
{
playerIDLabel->add();
@ -157,12 +190,18 @@ namespace StateManager
}
}
void move(const int x, const int y, const int w, const int h)
{
target_x = x;
target_y = y;
target_w = w;
target_h = h;
x_speed = abs( this->x - x ) / 300.0f;
y_speed = abs( this->y - y ) / 300.0f;
w_speed = abs( this->w - w ) / 300.0f;
h_speed = abs( this->h - h ) / 300.0f;
}
void onUpdate(float delta)
@ -174,47 +213,47 @@ namespace StateManager
// move x towards target
if (x < target_x)
{
x += move_step;
x += move_step*x_speed;
if (x > target_x) x = target_x; // don't move to the other side of the target
}
else if (x > target_x)
{
x -= move_step;
x -= move_step*x_speed;
if (x < target_x) x = target_x; // don't move to the other side of the target
}
// move y towards target
if (y < target_y)
{
y += move_step;
y += move_step*y_speed;
if (y > target_y) y = target_y; // don't move to the other side of the target
}
else if (y > target_y)
{
y -= move_step;
y -= move_step*y_speed;
if (y < target_y) y = target_y; // don't move to the other side of the target
}
// move w towards target
if (w < target_w)
{
w += move_step;
w += move_step*w_speed;
if (w > target_w) w = target_w; // don't move to the other side of the target
}
else if (w > target_w)
{
w -= move_step;
w -= move_step*w_speed;
if (w < target_w) w = target_w; // don't move to the other side of the target
}
// move h towards target
if (h < target_h)
{
h += move_step;
h += move_step*h_speed;
if (h > target_h) h = target_h; // don't move to the other side of the target
}
else if (h > target_h)
{
h -= move_step;
h -= move_step*h_speed;
if (h < target_h) h = target_h; // don't move to the other side of the target
}
@ -298,6 +337,15 @@ namespace StateManager
kart_name_y = y + h - 25;;
kart_name_w = w;
kart_name_h = 25;
// for shrinking effect
if (h < 150)
{
const float factor = h / 150.0f;
kart_name_h *= factor;
player_name_h *= factor;
player_id_h *= factor;
}
}
};
@ -364,6 +412,7 @@ void firePressedOnNewDevice(InputDevice* device)
newPlayer->add();
StateManager::addActivePlayer(aplayer);
aplayer->setDevice(device);
const int amount = g_player_karts.size();
@ -408,6 +457,30 @@ void setPlayer0Device(InputDevice* device)
// input_manager->getDeviceList()->setNoAssignMode(true);
}
PlayerKartWidget* removedWidget = NULL;
void playerPressedRescue(int playerID)
{
std::cout << "Player " << playerID << " no more wishes to play!\n";
removedWidget = g_player_karts.remove(playerID);
StateManager::removeActivePlayer(playerID);
const int amount = g_player_karts.size();
Widget* fullarea = getCurrentScreen()->getWidget("playerskarts");
const int splitWidth = fullarea->w / amount;
assert( amount == StateManager::activePlayerCount() );
for (int n=0; n<amount; n++)
{
g_player_karts[n].setPlayerID(n);
g_player_karts[n].move( fullarea->x + splitWidth*n, fullarea->y, splitWidth, fullarea->h );
}
removedWidget->move( removedWidget->x + removedWidget->w/2, fullarea->y + fullarea->h,
0, 0);
}
void kartSelectionUpdate(float delta)
{
@ -416,6 +489,19 @@ void kartSelectionUpdate(float delta)
{
g_player_karts[n].onUpdate(delta);
}
if (removedWidget != NULL)
{
removedWidget->onUpdate(delta);
if (removedWidget->w == 0 || removedWidget->h == 0)
{
// destruct when too small (for "disappear" effects)
GUIEngine::getCurrentScreen()->manualRemoveWidget(removedWidget);
delete removedWidget;
removedWidget = NULL;
}
}
}
/**

View File

@ -29,6 +29,8 @@ namespace StateManager
{
void setPlayer0Device(InputDevice* device);
void firePressedOnNewDevice(InputDevice* device);
void playerPressedRescue(int playerID);
void kartSelectionUpdate(float delta);
void menuEventKarts(GUIEngine::Widget* widget, std::string& name);

View File

@ -308,6 +308,11 @@ void Screen::manualAddWidget(Widget* w)
m_widgets.push_back(w);
}
void Screen::manualRemoveWidget(Widget* w)
{
m_widgets.remove(w);
}
#if 0
#pragma mark -
#pragma mark Getting widgets

View File

@ -84,7 +84,8 @@ namespace GUIEngine
void calculateLayout();
void manualAddWidget(Widget* w);
void manualRemoveWidget(Widget* w);
const std::string& getName() const { return m_filename; }
void elementsWereDeleted(ptr_vector<Widget>* within_vector = NULL);

View File

@ -64,6 +64,14 @@ namespace StateManager
{
g_active_players.push_back(p);
}
void removeActivePlayer(int id)
{
g_active_players.erase(id);
}
int activePlayerCount()
{
return g_active_players.size();
}
void resetActivePlayers()
{

View File

@ -44,7 +44,9 @@ namespace StateManager
* so no need to delete it yourself.
*/
void addActivePlayer(ActivePlayer* p);
void removeActivePlayer(int id);
int activePlayerCount();
void resetActivePlayers();
void escapePressed();

View File

@ -131,7 +131,7 @@ bool DeviceManager::mapInputToPlayerAndAction( Input::InputType type, int device
if( m_keyboards[n].hasBinding(btnID, action) )
{
// We found which device was triggered.
if(m_assign_mode == NO_ASSIGN)
{
// In no-assign mode, simply keep track of which device is used
@ -143,7 +143,7 @@ bool DeviceManager::mapInputToPlayerAndAction( Input::InputType type, int device
{
// In assign mode, find to which active player this binding belongs
// FIXME : in order to speed this use, a Player* pointer could be
// stored inside the device so we don't need to iterate through devices
// stored inside the device so we don't need to iterate through players
const ptr_vector<ActivePlayer, HOLD>& players = StateManager::getActivePlayers();
const int playerAmount = players.size();
for(int n=0; n<playerAmount; n++)
@ -152,6 +152,14 @@ bool DeviceManager::mapInputToPlayerAndAction( Input::InputType type, int device
{
// we found which active player has this binding
*player = n;
if (m_assign_mode == DETECT_NEW && *action == PA_RESCUE)
{
if (value > Input::MAX_VALUE/2) StateManager::playerPressedRescue( *player );
*action = PA_FIRST; // FIXME : returning PA_FIRST is quite a hackish way to tell input was handled internally
return true;
}
return true;
}
}
@ -163,9 +171,13 @@ bool DeviceManager::mapInputToPlayerAndAction( Input::InputType type, int device
for(unsigned int n=0; n<m_keyboard_amount; n++)
{
PlayerAction localaction = PA_FIRST; // none
if (m_keyboards[n].hasBinding(btnID, &localaction) && localaction == PA_FIRE)
if (m_keyboards[n].hasBinding(btnID, &localaction))
{
if (value > Input::MAX_VALUE/2) StateManager::firePressedOnNewDevice( m_keyboards.get(n) );
if(localaction == PA_FIRE)
{
if (value > Input::MAX_VALUE/2) StateManager::firePressedOnNewDevice( m_keyboards.get(n) );
}
*action = PA_FIRST; // FIXME : returning PA_FIRST is quite a hackish way to tell input was handled internally
return true;
}
@ -237,6 +249,12 @@ bool DeviceManager::mapInputToPlayerAndAction( Input::InputType type, int device
if(gamepad->hasBinding(type, btnID /* axis or button */, value, *player, action /* out */) )
{
if (m_assign_mode == DETECT_NEW && *action == PA_RESCUE)
{
if (value > Input::MAX_VALUE/2) StateManager::playerPressedRescue( *player );
*action = PA_FIRST; // FIXME : returning PA_FIRST is quite a hackish way to tell input was handled internally
}
return true;
}
}

View File

@ -37,7 +37,7 @@ void InputDevice::setPlayer(ActivePlayer* owner)
return;
}
}
std::cerr << "\n\nError, trying to assign that doesn't exist to a device!!!\n\n";
std::cerr << "\n\nError, trying to assign a player that doesn't exist to a device!!!\n\n";
}
// -----------------------------------------------------------------------------
void InputDevice::serialize(std::ofstream& stream)

View File

@ -105,12 +105,14 @@ void erase(const int ID)
contentsVector.erase(contentsVector.begin()+ID);
}
void remove(const int ID)
TYPE* remove(const int ID)
{
assert(ID > -1);
assert((unsigned int)ID < contentsVector.size());
TYPE* out = contentsVector[ID];
contentsVector.erase(contentsVector.begin()+ID);
return out;
}
bool contains( TYPE* instance ) const