Items animation (#4713)
This commit is contained in:
parent
3ccdfaf70d
commit
96c0d167bf
@ -19,6 +19,7 @@
|
||||
|
||||
#include "items/item.hpp"
|
||||
|
||||
#include "SColor.h"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/lod_node.hpp"
|
||||
#include "graphics/sp/sp_mesh.hpp"
|
||||
@ -38,6 +39,10 @@
|
||||
#include <IMeshSceneNode.h>
|
||||
#include <ISceneManager.h>
|
||||
|
||||
const float ICON_SIZE = 0.7f;
|
||||
const int SPARK_AMOUNT = 10;
|
||||
const float SPARK_SIZE = 0.4f;
|
||||
const float SPARK_SPEED_H = 1.0f;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Constructor.
|
||||
@ -52,8 +57,8 @@ ItemState::ItemState(ItemType type, const AbstractKart *owner, int id)
|
||||
m_item_id = id;
|
||||
m_previous_owner = owner;
|
||||
m_used_up_counter = -1;
|
||||
if (owner)
|
||||
setDeactivatedTicks(stk_config->time2Ticks(1.5f));
|
||||
if (owner)
|
||||
setDeactivatedTicks(stk_config->time2Ticks(1.5f));
|
||||
else
|
||||
setDeactivatedTicks(0);
|
||||
} // ItemState(ItemType)
|
||||
@ -212,9 +217,10 @@ void ItemState::saveCompleteState(BareNetworkString* buffer) const
|
||||
*/
|
||||
Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
|
||||
scene::IMesh* mesh, scene::IMesh* lowres_mesh,
|
||||
const AbstractKart *owner)
|
||||
const std::string& icon, const AbstractKart *owner)
|
||||
: ItemState(type, owner)
|
||||
{
|
||||
m_icon_node = NULL;
|
||||
m_was_available_previously = true;
|
||||
m_distance_2 = 1.2f;
|
||||
initItem(type, xyz, normal);
|
||||
@ -259,6 +265,31 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
|
||||
hpr.setHPR(getOriginalRotation());
|
||||
m_node->setRotation(hpr.toIrrHPR());
|
||||
m_node->grab();
|
||||
|
||||
for (int n = 0; n < SPARK_AMOUNT; n++)
|
||||
{
|
||||
scene::ISceneNode* billboard =
|
||||
irr_driver->addBillboard(core::dimension2df(SPARK_SIZE, SPARK_SIZE),
|
||||
"item_spark.png", m_node);
|
||||
#ifdef DEBUG
|
||||
billboard->setName("spark");
|
||||
#endif
|
||||
|
||||
billboard->setVisible(true);
|
||||
|
||||
m_spark_nodes.push_back(billboard);
|
||||
}
|
||||
|
||||
if (!icon.empty())
|
||||
{
|
||||
m_icon_node = irr_driver->addBillboard(core::dimension2df(1.0f, 1.0f),
|
||||
icon, m_node);
|
||||
|
||||
m_icon_node->setPosition(core::vector3df(0.0f, 0.5f, 0.0f));
|
||||
m_icon_node->setVisible(false);
|
||||
((scene::IBillboardSceneNode*)m_icon_node)
|
||||
->setColor(ItemManager::getGlowColor(type).toSColor());
|
||||
}
|
||||
} // Item(type, xyz, normal, mesh, lowres_mesh)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -337,6 +368,11 @@ Item::~Item()
|
||||
{
|
||||
if (m_node != NULL)
|
||||
{
|
||||
for (auto* node : m_spark_nodes)
|
||||
m_node->removeChild(node);
|
||||
if (m_icon_node)
|
||||
m_node->removeChild(m_icon_node);
|
||||
|
||||
irr_driver->removeNode(m_node);
|
||||
m_node->drop();
|
||||
}
|
||||
@ -352,6 +388,7 @@ Item::~Item()
|
||||
void Item::reset()
|
||||
{
|
||||
m_was_available_previously = true;
|
||||
m_animation_start_ticks = 0;
|
||||
ItemState::reset();
|
||||
|
||||
if (m_node != NULL)
|
||||
@ -379,6 +416,21 @@ void Item::handleNewMesh(ItemType type)
|
||||
Vec3 hpr;
|
||||
hpr.setHPR(getOriginalRotation());
|
||||
m_node->setRotation(hpr.toIrrHPR());
|
||||
|
||||
if (m_icon_node)
|
||||
m_node->removeChild(m_icon_node);
|
||||
auto icon = ItemManager::getIcon(type);
|
||||
|
||||
if (!icon.empty())
|
||||
{
|
||||
m_icon_node = irr_driver->addBillboard(core::dimension2df(1.0f, 1.0f),
|
||||
icon, m_node);
|
||||
|
||||
m_icon_node->setPosition(core::vector3df(0.0f, 0.5f, 0.0f));
|
||||
m_icon_node->setVisible(false);
|
||||
((scene::IBillboardSceneNode*)m_icon_node)
|
||||
->setColor(ItemManager::getGlowColor(type).toSColor());
|
||||
}
|
||||
#endif
|
||||
} // handleNewMesh
|
||||
|
||||
@ -408,29 +460,37 @@ void Item::updateGraphics(float dt)
|
||||
|
||||
if (!m_was_available_previously && isAvailable())
|
||||
{
|
||||
// This item is now available again - make sure it is not
|
||||
// scaled anymore.
|
||||
m_node->setScale(core::vector3df(1, 1, 1));
|
||||
// Play animation when item respawns
|
||||
m_node->setScale(core::vector3df(0, 0, 0));
|
||||
m_animation_start_ticks = World::getWorld()->getTicksSinceStart();
|
||||
}
|
||||
|
||||
float time_since_return = stk_config->ticks2Time(
|
||||
World::getWorld()->getTicksSinceStart() - m_animation_start_ticks);
|
||||
|
||||
if (isAvailable() && time_since_return <= 1.0f)
|
||||
{
|
||||
float p = time_since_return, f = (1.0f - time_since_return);
|
||||
float factor_v = sin(-13.0f * M_PI_2 * (p + 1.0f))
|
||||
* pow(2.0f, -10.0f * p) + 1.0f;
|
||||
float factor_h = 1.0f - (f * f * f * f * f - f * f * f * sin(f * M_PI));
|
||||
|
||||
m_node->setScale(core::vector3df(factor_h, factor_v, factor_h));
|
||||
}
|
||||
|
||||
if (isAvailable() && time_since_return > 1.0f)
|
||||
{
|
||||
// Ensure the model has the wanted scale
|
||||
m_node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
|
||||
if (!isAvailable() && time_till_return <= 1.0f)
|
||||
{
|
||||
// Make it visible by scaling it from 0 to 1:
|
||||
if (rotating())
|
||||
{
|
||||
float angle =
|
||||
fmodf((float)(World::getWorld()->getTicksSinceStart() +
|
||||
getTicksTillReturn()) / 40.0f, M_PI * 2);
|
||||
btMatrix3x3 m;
|
||||
m.setRotation(getOriginalRotation());
|
||||
btQuaternion r = btQuaternion(m.getColumn(1), angle) *
|
||||
getOriginalRotation();
|
||||
Vec3 hpr;
|
||||
hpr.setHPR(r);
|
||||
m_node->setRotation(hpr.toIrrHPR());
|
||||
}
|
||||
m_node->setVisible(true);
|
||||
m_node->setScale(core::vector3df(1, 1, 1)*(1 - time_till_return));
|
||||
|
||||
// Make it de facto invisible, but the model needs to be visible for
|
||||
// particles to show
|
||||
m_node->setScale(core::vector3df(0.0f, 1.0f, 0.0f));
|
||||
}
|
||||
if (isAvailable())
|
||||
{
|
||||
@ -452,5 +512,63 @@ void Item::updateGraphics(float dt)
|
||||
hpr.setHPR(getOriginalRotation());
|
||||
m_node->setRotation(hpr.toIrrHPR());
|
||||
} // if item is available
|
||||
|
||||
for (size_t i = 0; i < SPARK_AMOUNT; i++)
|
||||
{
|
||||
if (time_since_return >= 1.0f)
|
||||
{
|
||||
m_spark_nodes[i]->setVisible(false);
|
||||
continue;
|
||||
}
|
||||
|
||||
float t = time_since_return + 0.5f;
|
||||
float t2 = time_since_return + 1.0f;
|
||||
|
||||
float node_angle = !rotating() ? 0.0f :
|
||||
fmodf((float)World::getWorld()->getTicksSinceStart() / 40.0f,
|
||||
M_PI * 2);
|
||||
|
||||
float x = sin(float(i) / float(SPARK_AMOUNT) * 2.0f * M_PI - node_angle)
|
||||
* t * SPARK_SPEED_H;
|
||||
float y = 2.0f * t2 - t2 * t2 - 0.5f;
|
||||
float z = cos(float(i) / float(SPARK_AMOUNT) * 2.0f * M_PI - node_angle)
|
||||
* t * SPARK_SPEED_H;
|
||||
|
||||
m_spark_nodes[i]->setPosition(core::vector3df(x, y, z));
|
||||
|
||||
float factor = std::max(0.0f, 1.0f - t / 2.0f);
|
||||
|
||||
if (factor < 0.001f)
|
||||
{
|
||||
m_spark_nodes[i]->setVisible(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spark_nodes[i]->setVisible(true);
|
||||
|
||||
((scene::IBillboardSceneNode*)m_spark_nodes[i])
|
||||
->setSize(core::dimension2df(factor * SPARK_SIZE,
|
||||
factor * SPARK_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_icon_node)
|
||||
{
|
||||
if (!isAvailable() && time_till_return <= 1.0f)
|
||||
{
|
||||
m_icon_node->setVisible(true);
|
||||
float size = 1.0f / (pow(6.0f, -time_till_return - 0.2f) *
|
||||
(-time_till_return - 0.2f)) + 7.0f;
|
||||
|
||||
((scene::IBillboardSceneNode*)m_icon_node)
|
||||
->setSize(core::dimension2df(size * ICON_SIZE,
|
||||
size * ICON_SIZE));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_icon_node->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
m_was_available_previously = isAvailable();
|
||||
} // updateGraphics
|
||||
|
@ -330,6 +330,12 @@ private:
|
||||
/** Graphical type of the mesh. */
|
||||
ItemType m_graphical_type;
|
||||
|
||||
/** Vector containing the sparks */
|
||||
std::vector<scene::ISceneNode*> m_spark_nodes;
|
||||
|
||||
/** Billboard that shows when the item is about to respawn */
|
||||
scene::ISceneNode* m_icon_node;
|
||||
|
||||
/** Stores if the item was available in the previously rendered frame. */
|
||||
bool m_was_available_previously;
|
||||
|
||||
@ -344,6 +350,9 @@ private:
|
||||
* is not on any quad. */
|
||||
float m_distance_from_center;
|
||||
|
||||
/** Time ticks since the item last respawned */
|
||||
int m_animation_start_ticks;
|
||||
|
||||
/** The closest point to the left and right of this item at which it
|
||||
* would not be collected. Used by the AI to avoid items. */
|
||||
Vec3 *m_avoidance_points[2];
|
||||
@ -355,7 +364,7 @@ private:
|
||||
public:
|
||||
Item(ItemType type, const Vec3& xyz, const Vec3& normal,
|
||||
scene::IMesh* mesh, scene::IMesh* lowres_mesh,
|
||||
const AbstractKart *owner);
|
||||
const std::string& icon, const AbstractKart *owner);
|
||||
virtual ~Item ();
|
||||
virtual void updateGraphics(float dt) OVERRIDE;
|
||||
virtual void reset() OVERRIDE;
|
||||
|
@ -47,6 +47,7 @@
|
||||
std::vector<scene::IMesh *> ItemManager::m_item_mesh;
|
||||
std::vector<scene::IMesh *> ItemManager::m_item_lowres_mesh;
|
||||
std::vector<video::SColorf> ItemManager::m_glow_color;
|
||||
std::vector<std::string> ItemManager::m_icon;
|
||||
bool ItemManager::m_disable_item_collection = false;
|
||||
std::mt19937 ItemManager::m_random_engine;
|
||||
uint32_t ItemManager::m_random_seed = 0;
|
||||
@ -59,9 +60,11 @@ void ItemManager::loadDefaultItemMeshes()
|
||||
m_item_mesh.clear();
|
||||
m_item_lowres_mesh.clear();
|
||||
m_glow_color.clear();
|
||||
m_icon.clear();
|
||||
m_item_mesh.resize(ItemState::ITEM_LAST-ItemState::ITEM_FIRST+1, NULL);
|
||||
m_glow_color.resize(ItemState::ITEM_LAST-ItemState::ITEM_FIRST+1,
|
||||
video::SColorf(255.0f, 255.0f, 255.0f) );
|
||||
m_icon.resize(ItemState::ITEM_LAST-ItemState::ITEM_FIRST+1, "");
|
||||
|
||||
m_item_lowres_mesh.resize(ItemState::ITEM_LAST-ItemState::ITEM_FIRST+1, NULL);
|
||||
|
||||
@ -113,6 +116,7 @@ void ItemManager::loadDefaultItemMeshes()
|
||||
#endif
|
||||
m_item_lowres_mesh[i]->grab();
|
||||
}
|
||||
m_icon[i] = "icon-" + item_names[(ItemState::ItemType)i] + ".png";
|
||||
} // for i
|
||||
delete root;
|
||||
} // loadDefaultItemMeshes
|
||||
@ -297,7 +301,8 @@ Item* ItemManager::dropNewItem(ItemState::ItemType type,
|
||||
}
|
||||
|
||||
Item* item = new Item(type, pos, normal, m_item_mesh[mesh_type],
|
||||
m_item_lowres_mesh[mesh_type], /*prev_owner*/kart);
|
||||
m_item_lowres_mesh[mesh_type], m_icon[mesh_type],
|
||||
/*prev_owner*/kart);
|
||||
|
||||
// restoreState in NetworkItemManager will handle the insert item
|
||||
if (!server_xyz)
|
||||
@ -329,7 +334,8 @@ Item* ItemManager::placeItem(ItemState::ItemType type, const Vec3& xyz,
|
||||
ItemState::ItemType mesh_type = type;
|
||||
|
||||
Item* item = new Item(type, xyz, normal, m_item_mesh[mesh_type],
|
||||
m_item_lowres_mesh[mesh_type], /*prev_owner*/NULL);
|
||||
m_item_lowres_mesh[mesh_type], m_icon[mesh_type],
|
||||
/*prev_owner*/NULL);
|
||||
|
||||
insertItem(item);
|
||||
if (m_switch_ticks >= 0)
|
||||
|
@ -88,6 +88,10 @@ public:
|
||||
static scene::IMesh* getItemLowResolutionModel(ItemState::ItemType type)
|
||||
{ return m_item_lowres_mesh[type]; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the mesh for a certain item. */
|
||||
static std::string getIcon(ItemState::ItemType type)
|
||||
{ return m_icon[type]; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the glow color for an item. */
|
||||
static video::SColorf& getGlowColor(ItemState::ItemType type)
|
||||
{ return m_glow_color[type]; }
|
||||
@ -113,6 +117,9 @@ private:
|
||||
/** Stores all low-resolution item models. */
|
||||
static std::vector<scene::IMesh *> m_item_lowres_mesh;
|
||||
|
||||
/** Stores all item models. */
|
||||
static std::vector<std::string> m_icon;
|
||||
|
||||
protected:
|
||||
/** Remaining time that items should remain switched. If the
|
||||
* value is <0, it indicates that the items are not switched atm. */
|
||||
|
@ -2904,7 +2904,7 @@ void Track::copyFromMainProcess()
|
||||
{
|
||||
ItemState* it = m_item_manager->getItem(i);
|
||||
nim->insertItem(new Item(it->getType(), it->getXYZ(), it->getNormal(),
|
||||
NULL/*mesh*/, NULL/*lowres_mesh*/, NULL/*owner*/));
|
||||
NULL/*mesh*/, NULL/*lowres_mesh*/, "", NULL/*owner*/));
|
||||
}
|
||||
m_item_manager = nim;
|
||||
} // copyFromMainProcess
|
||||
|
@ -42,6 +42,9 @@
|
||||
#ifndef M_PI
|
||||
# define M_PI 3.14159265358979323846f /* As in Linux's math.h */
|
||||
#endif
|
||||
#ifndef M_PI_2
|
||||
# define M_PI_2 1.57079632679489661923
|
||||
#endif
|
||||
|
||||
#define NINETY_DEGREE_RAD (M_PI/2.0f)
|
||||
#define DEGREE_TO_RAD (M_PI/180.0f)
|
||||
|
Loading…
Reference in New Issue
Block a user