#include "pch.h" ////////////////////////////////////////////////////////////////////////////// // // ExplosionGeo // ////////////////////////////////////////////////////////////////////////////// class ExplosionGeoImpl : public ExplosionGeo { private: ////////////////////////////////////////////////////////////////////////////// // // Types // ////////////////////////////////////////////////////////////////////////////// class ExplosionData : IObject { public: TRef m_pimage; Vector m_position; Vector m_dposition; float m_angle; float m_timeStart; float m_scale; }; class ShockwaveData : IObject { public: TRef m_pimageShockwave; Vector m_position; Vector m_dposition; Vector m_forward; Vector m_right; Color m_color; float m_timeStart; float m_scale; }; typedef TList ExplosionDataList; ////////////////////////////////////////////////////////////////////////////// // // Members // ////////////////////////////////////////////////////////////////////////////// TList m_listShockwave; TVector m_vlistExplosion; ////////////////////////////////////////////////////////////////////////////// // // Value Members // ////////////////////////////////////////////////////////////////////////////// Number* GetTime() { return Number::Cast(GetChild(0)); } public: ExplosionGeoImpl(Number* ptime) : ExplosionGeo(ptime), m_vlistExplosion(24) { } ////////////////////////////////////////////////////////////////////////////// // // Methods // ////////////////////////////////////////////////////////////////////////////// void AddExplosion( const Vector& position, const Vector& forward, const Vector& right, const Vector& dposition, float radiusExplosion, float radiusShockWave, const Color& color, int countDecals, TVector > vpimage, Image* pimageShockwave ) { // // Add the shockwave // if (pimageShockwave != NULL) { m_listShockwave.PushFront(); ShockwaveData& sdata = m_listShockwave.GetFront(); sdata.m_timeStart = GetTime()->GetValue(); sdata.m_pimageShockwave = pimageShockwave; sdata.m_color = color; sdata.m_position = position; sdata.m_dposition = dposition; sdata.m_scale = radiusShockWave; sdata.m_forward = forward; sdata.m_right = right; } // // Add the little explosions // int countImage = vpimage.GetCount(); int indexImage = 0; for (int index = 0; index < countDecals; index++) { ExplosionDataList& list = m_vlistExplosion.Get(index); list.PushFront(); ExplosionData& edata = list.GetFront(); edata.m_timeStart = GetTime()->GetValue() + index * 0.25f; edata.m_pimage = vpimage[indexImage]; edata.m_position = position + Vector::RandomPosition(radiusExplosion * 0.5f); edata.m_dposition = dposition; edata.m_angle = random(0, 2 * pi); edata.m_scale = radiusExplosion; indexImage++; if (indexImage >= countImage) { indexImage = 0; } } } ////////////////////////////////////////////////////////////////////////////// // // Value Methods // ////////////////////////////////////////////////////////////////////////////// ZString GetFunctionName() { return "ExplosionGeo"; } ////////////////////////////////////////////////////////////////////////////// // // Geometry Methods // ////////////////////////////////////////////////////////////////////////////// float RenderShockwaves(Context* pcontext) { float fill = 0; TList::Iterator iter(m_listShockwave); while (!iter.End()) { ShockwaveData& sdata = iter.Value(); float time = GetTime()->GetValue() - sdata.m_timeStart; float bright = 1.0f - time * time; if (bright <= 0) { iter.Remove(); } else { float scale = time * sdata.m_scale; fill += pcontext->DrawDecal( sdata.m_pimageShockwave->GetSurface(), bright * sdata.m_color, sdata.m_position + time * sdata.m_dposition, scale * sdata.m_forward, scale * sdata.m_right, 0, 0 ); iter.Next(); } }; return fill; } float RenderExplosions( Context* pcontext, ExplosionDataList& list ) { float fill = 0; ExplosionDataList::Iterator iter(list); while (!iter.End()) { ExplosionData& edata = iter.Value(); float time = GetTime()->GetValue() - edata.m_timeStart; if (time >= 0) { int frame = (int)(time * 20.0f); if (frame >= edata.m_pimage->GetCount()) { iter.Remove(); continue; } else { fill += pcontext->DrawDecal( edata.m_pimage->GetSurface(frame), Color::White(), edata.m_position + time * edata.m_dposition, Vector::GetZero(), Vector::GetZero(), edata.m_scale, edata.m_angle ); } } iter.Next(); } return fill; } void Render(Context* pcontext) { float fill = 0; fill += RenderShockwaves(pcontext); int count = m_vlistExplosion.GetCount(); for (int index = 0; index < count; index++) { fill += RenderExplosions(pcontext, m_vlistExplosion.Get(index)); // // If we have passed the fill limit throw away the rest of the explosions // if (fill > 2.0f) { for (int index2 = index + 1; index2 < count; index2++) { m_vlistExplosion.Get(index2).SetEmpty(); } return; } } } }; ////////////////////////////////////////////////////////////////////////////// // // ExplosionGeo Factory // ////////////////////////////////////////////////////////////////////////////// TRef CreateExplosionGeo(Number* ptime) { return new ExplosionGeoImpl(ptime); }