⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 explosion.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 3 页
字号:
}

void Explosion::onRemove()
{
   for( int i=0; i<ExplosionData::EC_NUM_EMITTERS; i++ )
   {
      if( mEmitterList[i] )
      {
         mEmitterList[i]->deleteWhenEmpty();
         mEmitterList[i] = NULL;
      }
   }

   if (mSceneManager != NULL)
      mSceneManager->removeObjectFromScene(this);
   if (getContainer() != NULL)
      getContainer()->removeObject(this);

   Parent::onRemove();
}


bool Explosion::onNewDataBlock(GameBaseData* dptr)
{
   mDataBlock = dynamic_cast<ExplosionData*>(dptr);
   if (!mDataBlock || !Parent::onNewDataBlock(dptr))
      return false;

   scriptOnNewDataBlock();
   return true;
}

//--------------------------------------------------------------------------
bool Explosion::prepRenderImage(SceneState* state, const U32 stateKey,
                                       const U32 /*startZone*/, const bool /*modifyBaseState*/)
{
   if (isLastState(state, stateKey))
      return false;
   setLastState(state, stateKey);

   // This should be sufficient for most objects that don't manage zones, and
   //  don't need to return a specialized RenderImage...
   if (state->isObjectRendered(this))
   {
      Point3F explosionPos;
      mObjToWorld.getColumn(3,&explosionPos);

      if (mExplosionInstance)
      {
         Point3F cameraOffset = explosionPos - state->getCameraPosition();
         mFog = state->getHazeAndFog(cameraOffset.len(),cameraOffset.z);
      }
      else
      {
         mFog = 0.0;
      }

      SceneRenderImage* image = new SceneRenderImage;
      image->obj              = this;
      image->isTranslucent    = true;
      image->sortType         = SceneRenderImage::Point;
      image->textureSortKey   = (U32)(dsize_t)mDataBlock;
      state->setImageRefPoint(this, image);
      state->insertRenderImage(image);
   }

   return false;
}

void Explosion::setCurrentScale()
{
   F32 t = F32(mCurrMS) / F32(mEndingMS);

   for( U32 i = 1; i < ExplosionData::EC_NUM_TIME_KEYS; i++ )
   {
      if( mDataBlock->times[i] >= t )
      {
         F32 firstPart =   t - mDataBlock->times[i-1];
         F32 total     =   mDataBlock->times[i] -
                           mDataBlock->times[i-1];

         firstPart /= total;

         mObjScale =      (mDataBlock->sizes[i-1] * (1.0 - firstPart)) +
                          (mDataBlock->sizes[i]   * firstPart);

         return;
      }
   }

}

void Explosion::prepModelView(SceneState* state)
{
   MatrixF rotMatrix( true );
   Point3F targetVector;
   if (mDataBlock->faceViewer == true)
   {
      targetVector = getPosition() - state->getCameraPosition();
      targetVector.normalize();
      rotMatrix.set( EulerF( 0.0, mRandAngle, 0.0 ) );
   }
   else
   {
      targetVector = mInitialNormal;
   }

   // rotate explosion each time so it's a little different
   MatrixF explOrient = MathUtils::createOrientFromDir( targetVector );
   explOrient.mul( rotMatrix );
   explOrient.setPosition( getPosition() );
   dglMultMatrix( &explOrient );
   setCurrentScale();
   glScalef(mObjScale.x, mObjScale.y, mObjScale.z);

}

void Explosion::renderObject(SceneState* state, SceneRenderImage*)
{
   AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on entry");

   RectI viewport;
   glMatrixMode(GL_PROJECTION);
   glPushMatrix();
   dglGetViewport(&viewport);

   // Uncomment this if this is a "simple" (non-zone managing) object
   state->setupObjectProjection(this);

   glMatrixMode(GL_MODELVIEW);
   glPushMatrix();

   prepModelView(state);

   if( mExplosionInstance )
   {
      mExplosionInstance->animate();

      if (mFade == 1.0)
      {
         mExplosionInstance->setupFog(mFog, state->getFogColor());
      }
      else
      {
         mExplosionInstance->setupFog(0.0, state->getFogColor());
         mExplosionInstance->setAlphaAlways(mFade * (1.0 - mFog));
      }
      mExplosionInstance->render();
   }

   glDisable(GL_TEXTURE_2D);
   glDisable(GL_BLEND);
   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
   glScalef( 1.0, 1.0, 1.0 );

   glMatrixMode(GL_MODELVIEW);
   glPopMatrix();

   glMatrixMode(GL_PROJECTION);
   glPopMatrix();
   glMatrixMode(GL_MODELVIEW);
   dglSetViewport(viewport);

   AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on exit");
}


//--------------------------------------------------------------------------

void Explosion::registerLights(LightManager * lightManager, bool lightingScene)
{
   if (lightingScene)
      return;

   // Update the light's info and add it to the scene, the light will
   // only be visible for this current frame.
   getRenderTransform().getColumn(3, &mLight.mPos);
   F32 t = F32(mCurrMS) / F32(mEndingMS);
   mLight.mRadius = mDataBlock->lightStartRadius +
      (mDataBlock->lightEndRadius - mDataBlock->lightStartRadius) * t;
   mLight.mColor  = mDataBlock->lightStartColor +
      (mDataBlock->lightEndColor - mDataBlock->lightStartColor) * t;
   lightManager->addLight(&mLight);
}


//--------------------------------------------------------------------------
void Explosion::processTick(const Move*)
{
   mCurrMS += TickMs;

   if( mCurrMS >= mEndingMS )
      deleteObject();

   if( (mCurrMS > mDelayMS) && !mActive )
      explode();
}

void Explosion::advanceTime(F32 dt)
{
   if (dt == 0.0)
      return;

#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsServerObject
   if(!isServerObject())
      return;
#endif

   updateEmitters( dt );

   if( mExplosionInstance )
      mExplosionInstance->advanceTime(dt, mExplosionThread);
}

//----------------------------------------------------------------------------
// Update emitters
//----------------------------------------------------------------------------
void Explosion::updateEmitters( F32 dt )
{
   Point3F pos = getPosition();

   for( int i=0; i<ExplosionData::EC_NUM_EMITTERS; i++ )
   {
      if( mEmitterList[i] )
      {
         mEmitterList[i]->emitParticles( pos, pos, mInitialNormal, Point3F( 0.0, 0.0, 0.0 ), (U32)(dt * 1000));
      }
   }

}

//----------------------------------------------------------------------------
// Launch Debris
//----------------------------------------------------------------------------
void Explosion::launchDebris( Point3F &axis )
{
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsServerObject
   if(!isServerObject())
      return;
#endif

   bool hasDebris = false;
   for( int j=0; j<ExplosionData::EC_NUM_DEBRIS_TYPES; j++ )
   {
      if( mDataBlock->debrisList[j] )
      {
         hasDebris = true;
         break;
      }
   }
   if( !hasDebris )
   {
      return;
   }

   Point3F axisx;
   if (mFabs(axis.z) < 0.999f)
      mCross(axis, Point3F(0, 0, 1), &axisx);
   else
      mCross(axis, Point3F(0, 1, 0), &axisx);
   axisx.normalize();

   Point3F pos = getPosition() + Point3F( 0.0, 0.0, 0.5 );


   U32 numDebris = mDataBlock->debrisNum + sgRandom.randI( -mDataBlock->debrisNumVariance, mDataBlock->debrisNumVariance );

   for( int i=0; i<numDebris; i++ )
   {

      Point3F launchDir = MathUtils::randomDir( axis, mDataBlock->debrisThetaMin, mDataBlock->debrisThetaMax,
                                                mDataBlock->debrisPhiMin, mDataBlock->debrisPhiMax );

      F32 debrisVel = mDataBlock->debrisVelocity + mDataBlock->debrisVelocityVariance * sgRandom.randF( -1.0, 1.0 );

      launchDir *= debrisVel;

      Debris *debris = new Debris;
      debris->setDataBlock( mDataBlock->debrisList[0] );
      debris->setTransform( getTransform() );
      debris->init( pos, launchDir );

      if( !debris->registerObject() )
      {
         Con::warnf( ConsoleLogEntry::General, "Could not register debris for class: %s", mDataBlock->getName() );
         delete debris;
         debris = NULL;
      }
   }
}

//----------------------------------------------------------------------------
// Spawn sub explosions
//----------------------------------------------------------------------------
void Explosion::spawnSubExplosions()
{
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsServerObject
   if(!isServerObject())
      return;
#endif

   for( S32 i=0; i<ExplosionData::EC_MAX_SUB_EXPLOSIONS; i++ )
   {
      if( mDataBlock->explosionList[i] )
      {
         MatrixF trans = getTransform();
         Explosion* pExplosion = new Explosion;
         pExplosion->setDataBlock( mDataBlock->explosionList[i] );
         pExplosion->setTransform( trans );
         pExplosion->setInitialState( trans.getPosition(), mInitialNormal, 1);
         if (!pExplosion->registerObject())
            delete pExplosion;
      }
   }
}

//----------------------------------------------------------------------------
// Explode
//----------------------------------------------------------------------------
bool Explosion::explode()
{
   mActive = true;

#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsServerObject
   if(!isServerObject())
      return true;
#endif

   launchDebris( mInitialNormal );
   spawnSubExplosions();

   if (bool(mDataBlock->explosionShape) && mDataBlock->explosionAnimation != -1)
   {
      mExplosionInstance = new TSShapeInstance(mDataBlock->explosionShape, true);

      mExplosionThread   = mExplosionInstance->addThread();
      mExplosionInstance->setSequence(mExplosionThread, mDataBlock->explosionAnimation, 0);
      mExplosionInstance->setTimeScale(mExplosionThread, mDataBlock->playSpeed);

      mCurrMS   = 0;
      mEndingMS = U32(mExplosionInstance->getScaledDuration(mExplosionThread) * 1000.0f);

      mObjScale.convolve(mDataBlock->explosionScale);
      mObjBox = mDataBlock->explosionShape->bounds;
      resetWorldBox();
   }

   if (mDataBlock->soundProfile)
      alxPlay(mDataBlock->soundProfile, &getTransform() );

   if (mDataBlock->particleEmitter)
   {
      ParticleEmitter* emitter = new ParticleEmitter;
      emitter->setDataBlock(mDataBlock->particleEmitter);
      emitter->registerObject();

      emitter->emitParticles(getPosition(), mInitialNormal, mDataBlock->particleRadius,
                             Point3F(0, 0, 0), U32(mDataBlock->particleDensity * mFade));
      emitter->deleteWhenEmpty();
   }

   for( int i=0; i<ExplosionData::EC_NUM_EMITTERS; i++ )
   {
      if( mDataBlock->emitterList[i] != NULL )
      {
         ParticleEmitter * pEmitter = new ParticleEmitter;
         pEmitter->setDataBlock( mDataBlock->emitterList[i] );
         if( !pEmitter->registerObject() )
         {
            Con::warnf( ConsoleLogEntry::General, "Could not register emitter for particle of class: %s", mDataBlock->getName() );
            SAFE_DELETE(pEmitter);
         }
         mEmitterList[i] = pEmitter;
      }
   }

   return true;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -