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

📄 vehicle.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
📖 第 1 页 / 共 4 页
字号:
{
   Parent::writePacketData(connection, stream);
   mathWrite(*stream, mSteering);

   mathWrite(*stream, mRigid.linPosition);
   mathWrite(*stream, mRigid.angPosition);
   mathWrite(*stream, mRigid.linMomentum);
   mathWrite(*stream, mRigid.angMomentum);
   stream->writeFlag(mRigid.atRest);
   stream->writeFlag(mContacts.count == 0);

   stream->writeFlag(mDisableMove);
   stream->setCompressionPoint(mRigid.linPosition);
}

void Vehicle::readPacketData(GameConnection *connection, BitStream *stream)
{
   Parent::readPacketData(connection, stream);
   mathRead(*stream, &mSteering);

   mathRead(*stream, &mRigid.linPosition);
   mathRead(*stream, &mRigid.angPosition);
   mathRead(*stream, &mRigid.linMomentum);
   mathRead(*stream, &mRigid.angMomentum);
   mRigid.atRest = stream->readFlag();
   if (stream->readFlag())
      mContacts.count = 0;

   // Update the rigid state based on the new information
   mRigid.updateInertialTensor();
   mRigid.updateVelocity();
   mRigid.updateCenterOfMass();

   mDisableMove = stream->readFlag();
   stream->setCompressionPoint(mRigid.linPosition);
}


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

U32 Vehicle::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
{
   U32 retMask = Parent::packUpdate(con, mask, stream);

   stream->writeFlag(mJetting);

   // The rest of the data is part of the control object packet update.
   // If we're controlled by this client, we don't need to send it.
   if (stream->writeFlag(getControllingClient() == con && !(mask & InitialUpdateMask)))
      return retMask;

   F32 yaw = (mSteering.x + mDataBlock->maxSteeringAngle) / (2 * mDataBlock->maxSteeringAngle);
   F32 pitch = (mSteering.y + mDataBlock->maxSteeringAngle) / (2 * mDataBlock->maxSteeringAngle);
   stream->writeFloat(yaw,9);
   stream->writeFloat(pitch,9);
   mDelta.move.pack(stream);

   if (stream->writeFlag(mask & PositionMask))
   {
      stream->writeCompressedPoint(mRigid.linPosition);
      mathWrite(*stream, mRigid.angPosition);
      mathWrite(*stream, mRigid.linMomentum);
      mathWrite(*stream, mRigid.angMomentum);
      stream->writeFlag(mRigid.atRest);
   }

   // send energy only to clients which need it
   bool found = false;
   if (mask & EnergyMask)
   {
      for (ShapeBase* ptr = getMountList(); ptr; ptr = ptr->getMountLink())
      {
         GameConnection * controllingClient = ptr->getControllingClient();
         if(controllingClient == con)
         {
            if(controllingClient->getControlObject() != this)
               found = true;
            break;
         }
      }
   }

   // write it...
   if(stream->writeFlag(found))
      stream->writeFloat(mClampF(getEnergyValue(), 0.f, 1.f), 8);

   return retMask;
}

void Vehicle::unpackUpdate(NetConnection *con, BitStream *stream)
{
   Parent::unpackUpdate(con,stream);

   mJetting = stream->readFlag();

   if (stream->readFlag())
      return;

   F32 yaw = stream->readFloat(9);
   F32 pitch = stream->readFloat(9);
   mSteering.x = (2 * yaw * mDataBlock->maxSteeringAngle) - mDataBlock->maxSteeringAngle;
   mSteering.y = (2 * pitch * mDataBlock->maxSteeringAngle) - mDataBlock->maxSteeringAngle;
   mDelta.move.unpack(stream);

   if (stream->readFlag()) {
      mPredictionCount = sMaxPredictionTicks;
      F32 speed = mRigid.linVelocity.len();
      mDelta.warpRot[0] = mRigid.angPosition;

      // Read in new position and momentum values
      stream->readCompressedPoint(&mRigid.linPosition);
      mathRead(*stream, &mRigid.angPosition);
      mathRead(*stream, &mRigid.linMomentum);
      mathRead(*stream, &mRigid.angMomentum);
      mRigid.atRest = stream->readFlag();
      mRigid.updateVelocity();

      if (isProperlyAdded()) {
         // Determin number of ticks to warp based on the average
         // of the client and server velocities.
         Point3F cp = mDelta.pos + mDelta.posVec * mDelta.dt;
         mDelta.warpOffset = mRigid.linPosition - cp;

         // Calc the distance covered in one tick as the average of
         // the old speed and the new speed from the server.
         F32 dt,as = (speed + mRigid.linVelocity.len()) * 0.5 * TickSec;

         // Cal how many ticks it will take to cover the warp offset.
         // If it's less than what's left in the current tick, we'll just
         // warp in the remaining time.
         if (!as || (dt = mDelta.warpOffset.len() / as) > sMaxWarpTicks)
            dt = mDelta.dt + sMaxWarpTicks;
         else
            dt = (dt <= mDelta.dt)? mDelta.dt : mCeil(dt - mDelta.dt) + mDelta.dt;

         // Adjust current frame interpolation
         if (mDelta.dt) {
            mDelta.pos = cp + (mDelta.warpOffset * (mDelta.dt / dt));
            mDelta.posVec = (cp - mDelta.pos) / mDelta.dt;
            QuatF cr;
            cr.interpolate(mDelta.rot[1],mDelta.rot[0],mDelta.dt);
            mDelta.rot[1].interpolate(cr,mRigid.angPosition,mDelta.dt / dt);
            mDelta.rot[0].extrapolate(mDelta.rot[1],cr,mDelta.dt);
         }

         // Calculated multi-tick warp
         mDelta.warpCount = 0;
         mDelta.warpTicks = (S32)(mFloor(dt));
         if (mDelta.warpTicks) {
            mDelta.warpOffset = mRigid.linPosition - mDelta.pos;
            mDelta.warpOffset /= mDelta.warpTicks;
            mDelta.warpRot[0] = mDelta.rot[1];
            mDelta.warpRot[1] = mRigid.angPosition;
         }
      }
      else {
         // Set the vehicle to the server position
         mDelta.dt  = 0;
         mDelta.pos = mRigid.linPosition;
         mDelta.posVec.set(0,0,0);
         mDelta.rot[1] = mDelta.rot[0] = mRigid.angPosition;
         mDelta.warpCount = mDelta.warpTicks = 0;
         setPosition(mRigid.linPosition, mRigid.angPosition);
      }

      mRigid.updateCenterOfMass();
   }

   // energy?
   if(stream->readFlag())
      setEnergyLevel(stream->readFloat(8) * mDataBlock->maxEnergy);
}


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

void Vehicle::initPersistFields()
{
   Parent::initPersistFields();

   addField("disableMove",   TypeBool,   Offset(mDisableMove, Vehicle));
}


void Vehicle::mountObject(ShapeBase* obj, U32 node)
{
   Parent::mountObject(obj, node);

   // Clear objects off the working list that are from objects mounted to us.
   //  (This applies mostly to players...)
   for (CollisionWorkingList* itr = mConvex.getWorkingList().wLink.mNext; itr != &mConvex.getWorkingList(); itr = itr->wLink.mNext) {
      if (itr->mConvex->getObject() == obj) {
         CollisionWorkingList* cl = itr;
         itr = itr->wLink.mPrev;
         cl->free();
      }
   }
}

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

void Vehicle::updateLiftoffDust( F32 dt )
{
   if( !mDustEmitterList[0] ) return;

   Point3F startPos = getPosition();
   Point3F endPos = startPos + Point3F( 0.0, 0.0, -mDataBlock->triggerDustHeight );


   RayInfo rayInfo;
   if( !getContainer()->castRay( startPos, endPos, TerrainObjectType, &rayInfo ) )
   {
      return;
   }

   TerrainBlock* tBlock = static_cast<TerrainBlock*>(rayInfo.object);
   S32 mapIndex = tBlock->mMPMIndex[0];

   MaterialPropertyMap* pMatMap = static_cast<MaterialPropertyMap*>(Sim::findObject("MaterialPropertyMap"));
   const MaterialPropertyMap::MapEntry* pEntry = pMatMap->getMapEntryFromIndex(mapIndex);

   if(pEntry)
   {
      S32 x;
      ColorF colorList[ParticleEngine::PC_COLOR_KEYS];

      for(x = 0; x < 2; ++x)
         colorList[x].set( pEntry->puffColor[x].red, pEntry->puffColor[x].green, pEntry->puffColor[x].blue, pEntry->puffColor[x].alpha );
      for(x = 2; x < ParticleEngine::PC_COLOR_KEYS; ++x)
         colorList[x].set( 1.0, 1.0, 1.0, 0.0 );

      mDustEmitterList[0]->setColors( colorList );
   }
   Point3F contactPoint = rayInfo.point + Point3F( 0.0, 0.0, mDataBlock->dustHeight );
   mDustEmitterList[0]->emitParticles( contactPoint, contactPoint, rayInfo.normal, getVelocity(), (U32)(dt * 1000) );
}


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

void Vehicle::updateDamageSmoke( F32 dt )
{

   for( S32 j=VehicleData::VC_NUM_DAMAGE_LEVELS-1; j>=0; j-- )
   {
      F32 damagePercent = mDamage / mDataBlock->maxDamage;
      if( damagePercent >= mDataBlock->damageLevelTolerance[j] )
      {
         for( int i=0; i<mDataBlock->numDmgEmitterAreas; i++ )
         {
            MatrixF trans = getTransform();
            Point3F offset = mDataBlock->damageEmitterOffset[i];
            trans.mulP( offset );
            Point3F emitterPoint = offset;

            if( pointInWater(offset ) )
            {
               U32 emitterOffset = VehicleData::VC_BUBBLE_EMITTER;
               if( mDamageEmitterList[emitterOffset] )
               {
                  mDamageEmitterList[emitterOffset]->emitParticles( emitterPoint, emitterPoint, Point3F( 0.0, 0.0, 1.0 ), getVelocity(), (U32)( dt * 1000 ) );
               }
            }
            else
            {
               if( mDamageEmitterList[j] )
               {
                  mDamageEmitterList[j]->emitParticles( emitterPoint, emitterPoint, Point3F( 0.0, 0.0, 1.0 ), getVelocity(), (U32)(dt * 1000));
               }
            }
         }
         break;
      }
   }

}


//--------------------------------------------------------------------------
void Vehicle::updateFroth( F32 dt )
{
   // update bubbles
   Point3F moveDir = getVelocity();

   Point3F contactPoint;
   if( !collidingWithWater( contactPoint ) )
   {
      if(waterWakeHandle)
      {
         alxStop(waterWakeHandle);
         waterWakeHandle = 0;
      }
      return;
   }

   F32 speed = moveDir.len();
   if( speed < mDataBlock->splashVelEpsilon ) speed = 0.0;

   U32 emitRate = (U32)(speed * mDataBlock->splashFreqMod * dt);

   U32 i;
   if(!waterWakeHandle)
      waterWakeHandle = alxPlay(mDataBlock->waterSound[VehicleData::Wake], &getTransform());
   alxSourceMatrixF(waterWakeHandle, &getTransform());

   for( i=0; i<VehicleData::VC_NUM_SPLASH_EMITTERS; i++ )
   {
      if( mSplashEmitterList[i] )
      {
         mSplashEmitterList[i]->emitParticles( contactPoint, contactPoint, Point3F( 0.0, 0.0, 1.0 ),
                                               moveDir, emitRate );
      }
   }

}


//--------------------------------------------------------------------------
// Returns true if vehicle is intersecting a water surface (roughly)
//--------------------------------------------------------------------------
bool Vehicle::collidingWithWater( Point3F &waterHeight )
{
   Point3F curPos = getPosition();

   F32 height = mFabs( mObjBox.max.z - mObjBox.min.z );

   RayInfo rInfo;
   if( gClientContainer.castRay( curPos + Point3F(0.0, 0.0, height), curPos, WaterObjectType, &rInfo) )
   {
      waterHeight = rInfo.point;
      return true;
   }

   return false;
}

void Vehicle::setEnergyLevel(F32 energy)
{
   Parent::setEnergyLevel(energy);
   setMaskBits(EnergyMask);
}

//-----------------------------------------------------------------------------
//
void Vehicle::renderImage(SceneState *state, SceneRenderImage *image)
{
	Parent::renderImage(state, image);

   if (gShowBoundingBox) {
      glDisable(GL_LIGHTING);
      glPushMatrix();
      dglMultMatrix(&getRenderTransform());

      // Box for the center of Mass
      glDisable(GL_DEPTH_TEST);
      glColor3f(1, 1, 1);
      wireCube(Point3F(0.1,0.1,0.1),mDataBlock->massCenter);
      glPopMatrix();

      // Collision points
      for (int i = 0; i < mCollisionList.count; i++) {
         glColor3f(0, 0, 1);
         Collision& collision = mCollisionList.collision[i];
         wireCube(Point3F(0.05,0.05,0.05),collision.point);
         glColor3f(1, 1, 1);
         glBegin(GL_LINES);
         glVertex3fv(collision.point);
         glVertex3fv(collision.point + collision.normal * 0.05);
         glEnd();
      }

      // Build and render the collision polylist which is returned
      // in the server's world space.
      ClippedPolyList polyList;
      polyList.mPlaneList.setSize(6);
      polyList.mPlaneList[0].set(getWorldBox().min,VectorF(-1,0,0));
      polyList.mPlaneList[1].set(getWorldBox().min,VectorF(0,-1,0));
      polyList.mPlaneList[2].set(getWorldBox().min,VectorF(0,0,-1));
      polyList.mPlaneList[3].set(getWorldBox().max,VectorF(1,0,0));
      polyList.mPlaneList[4].set(getWorldBox().max,VectorF(0,1,0));
      polyList.mPlaneList[5].set(getWorldBox().max,VectorF(0,0,1));
      Box3F dummyBox;
      SphereF dummySphere;
      buildPolyList(&polyList, dummyBox, dummySphere);
      polyList.render();

      //
      glEnable(GL_DEPTH_TEST);
      glEnable(GL_LIGHTING);
   }
}

//-----------------------------------------------------------------------------
// Demonstrates adding rendering to mounted objects.
//
void Vehicle::renderMountedImage
(SceneState *state, ShapeImageRenderImage *image)
{
	Parent::renderMountedImage(state, image);
	if (gShowBoundingBox) {
		U32 index = image->mIndex;
		if (mMountedImageList[index].dataBlock != NULL) {
			Point3F muzzlePoint, muzzleVector, endpoint;
			getMuzzlePoint(index, &muzzlePoint);
			getMuzzleVector(index, &muzzleVector);
			endpoint = muzzlePoint + muzzleVector * 250;
			// Lighting has been installed by ShapeBase::renderObject.  Switch lighting
			// off while rendering the debug graphics.
			glDisable(GL_LIGHTING);
			glEnable(GL_BLEND);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			glLineWidth(1);
			glBegin(GL_LINES);
			glColor4ub(0, 255, 0, 255);
			glVertex3fv(muzzlePoint);
			glVertex3fv(endpoint);
			glEnd();
			glLineWidth(1);
			glDisable(GL_BLEND);
			glEnable(GL_LIGHTING);
		}
	}
}
bool Vehicle::getAIMove(Move *move)
{
   return false;
}

⌨️ 快捷键说明

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