hgeparticle.cpp
上传用户:maxiaolivb
上传日期:2022-06-07
资源大小:915k
文件大小:7k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /*
  2. ** Haaf's Game Engine 1.5
  3. ** Copyright (C) 2003-2004, Relish Games
  4. ** hge.relishgames.com
  5. **
  6. ** hgeParticleSystem helper class implementation
  7. */
  8. #include "....includehgeparticle.h"
  9. HGE *hgeParticleSystem::hge=0;
  10. hgeParticleSystem::hgeParticleSystem(const char *filename, hgeSprite *sprite, float fps)
  11. {
  12. void *psi;
  13. hge=hgeCreate(HGE_VERSION);
  14. psi=hge->Resource_Load(filename);
  15. if(!psi) return;
  16. memcpy(&info, psi, sizeof(hgeParticleSystemInfo));
  17. hge->Resource_Free(psi);
  18. info.sprite=sprite;
  19. vecLocation.x=vecPrevLocation.x=0.0f;
  20. vecLocation.y=vecPrevLocation.y=0.0f;
  21. fTx=fTy=0;
  22. fEmissionResidue=0.0f;
  23. nParticlesAlive=0;
  24. fAge=-2.0;
  25. if(fps!=0.0f) fUpdSpeed=1.0f/fps;
  26. else fUpdSpeed=0.0f;
  27. fResidue=0.0f;
  28. rectBoundingBox.Clear();
  29. bUpdateBoundingBox=false;
  30. }
  31. hgeParticleSystem::hgeParticleSystem(hgeParticleSystemInfo *psi, float fps)
  32. {
  33. hge=hgeCreate(HGE_VERSION);
  34. memcpy(&info, psi, sizeof(hgeParticleSystemInfo));
  35. vecLocation.x=vecPrevLocation.x=0.0f;
  36. vecLocation.y=vecPrevLocation.y=0.0f;
  37. fTx=fTy=0;
  38. fEmissionResidue=0.0f;
  39. nParticlesAlive=0;
  40. fAge=-2.0;
  41. if(fps!=0.0f) fUpdSpeed=1.0f/fps;
  42. else fUpdSpeed=0.0f;
  43. fResidue=0.0f;
  44. rectBoundingBox.Clear();
  45. bUpdateBoundingBox=false;
  46. }
  47. hgeParticleSystem::hgeParticleSystem(const hgeParticleSystem &ps)
  48. {
  49. memcpy(this, &ps, sizeof(hgeParticleSystem));
  50. hge=hgeCreate(HGE_VERSION);
  51. }
  52. void hgeParticleSystem::Update(float fDeltaTime)
  53. {
  54.    if(fUpdSpeed==0.0f) _update(fDeltaTime);
  55.    else
  56.    {
  57.       fResidue+=fDeltaTime;
  58.       if(fResidue>=fUpdSpeed)
  59.   {
  60. _update(fUpdSpeed);
  61. while(fResidue>=fUpdSpeed) fResidue-=fUpdSpeed;
  62.   }
  63.    }
  64. }
  65. void hgeParticleSystem::_update(float fDeltaTime)
  66. {
  67. int i;
  68. float ang;
  69. hgeParticle *par;
  70. hgeVector vecAccel, vecAccel2;
  71. if(fAge >= 0)
  72. {
  73. fAge += fDeltaTime;
  74. if(fAge >= info.fLifetime) fAge = -2.0f;
  75. }
  76. // update all alive particles
  77. if(bUpdateBoundingBox) rectBoundingBox.Clear();
  78. par=particles;
  79. for(i=0; i<nParticlesAlive; i++)
  80. {
  81. par->fAge += fDeltaTime;
  82. if(par->fAge >= par->fTerminalAge)
  83. {
  84. nParticlesAlive--;
  85. memcpy(par, &particles[nParticlesAlive], sizeof(hgeParticle));
  86. i--;
  87. continue;
  88. }
  89. vecAccel = par->vecLocation-vecLocation;
  90. vecAccel.Normalize();
  91. vecAccel2 = vecAccel;
  92. vecAccel *= par->fRadialAccel;
  93. // vecAccel2.Rotate(M_PI_2);
  94. // the following is faster
  95. ang = vecAccel2.x;
  96. vecAccel2.x = -vecAccel2.y;
  97. vecAccel2.y = ang;
  98. vecAccel2 *= par->fTangentialAccel;
  99. par->vecVelocity += (vecAccel+vecAccel2)*fDeltaTime;
  100. par->vecVelocity.y += par->fGravity*fDeltaTime;
  101. par->vecLocation += par->vecVelocity;
  102. par->fSpin += par->fSpinDelta*fDeltaTime;
  103. par->fSize += par->fSizeDelta*fDeltaTime;
  104. par->colColor += par->colColorDelta*fDeltaTime;
  105. if(bUpdateBoundingBox) rectBoundingBox.Encapsulate(par->vecLocation.x, par->vecLocation.y);
  106. par++;
  107. }
  108. // generate new particles
  109. if(fAge != -2.0f)
  110. {
  111. float fParticlesNeeded = info.nEmission*fDeltaTime + fEmissionResidue;
  112. int nParticlesCreated = (unsigned int)fParticlesNeeded;
  113. fEmissionResidue=fParticlesNeeded-nParticlesCreated;
  114. par=&particles[nParticlesAlive];
  115. for(i=0; i<nParticlesCreated; i++)
  116. {
  117. if(nParticlesAlive>=MAX_PARTICLES) break;
  118. par->fAge = 0.0f;
  119. par->fTerminalAge = hge->Random_Float(info.fParticleLifeMin, info.fParticleLifeMax);
  120. par->vecLocation = vecPrevLocation+(vecLocation-vecPrevLocation)*hge->Random_Float(0.0f, 1.0f);
  121. par->vecLocation.x += hge->Random_Float(-2.0f, 2.0f);
  122. par->vecLocation.y += hge->Random_Float(-2.0f, 2.0f);
  123. ang=info.fDirection-M_PI_2+hge->Random_Float(0,info.fSpread)-info.fSpread/2.0f;
  124. if(info.bRelative) ang += (vecPrevLocation-vecLocation).Angle()+M_PI_2;
  125. par->vecVelocity.x = cosf(ang);
  126. par->vecVelocity.y = sinf(ang);
  127. par->vecVelocity *= hge->Random_Float(info.fSpeedMin, info.fSpeedMax);
  128. par->fGravity = hge->Random_Float(info.fGravityMin, info.fGravityMax);
  129. par->fRadialAccel = hge->Random_Float(info.fRadialAccelMin, info.fRadialAccelMax);
  130. par->fTangentialAccel = hge->Random_Float(info.fTangentialAccelMin, info.fTangentialAccelMax);
  131. par->fSize = hge->Random_Float(info.fSizeStart, info.fSizeStart+(info.fSizeEnd-info.fSizeStart)*info.fSizeVar);
  132. par->fSizeDelta = (info.fSizeEnd-par->fSize) / par->fTerminalAge;
  133. par->fSpin = hge->Random_Float(info.fSpinStart, info.fSpinStart+(info.fSpinEnd-info.fSpinStart)*info.fSpinVar);
  134. par->fSpinDelta = (info.fSpinEnd-par->fSpin) / par->fTerminalAge;
  135. par->colColor.r = hge->Random_Float(info.colColorStart.r, info.colColorStart.r+(info.colColorEnd.r-info.colColorStart.r)*info.fColorVar);
  136. par->colColor.g = hge->Random_Float(info.colColorStart.g, info.colColorStart.g+(info.colColorEnd.g-info.colColorStart.g)*info.fColorVar);
  137. par->colColor.b = hge->Random_Float(info.colColorStart.b, info.colColorStart.b+(info.colColorEnd.b-info.colColorStart.b)*info.fColorVar);
  138. par->colColor.a = hge->Random_Float(info.colColorStart.a, info.colColorStart.a+(info.colColorEnd.a-info.colColorStart.a)*info.fAlphaVar);
  139. par->colColorDelta.r = (info.colColorEnd.r-par->colColor.r) / par->fTerminalAge;
  140. par->colColorDelta.g = (info.colColorEnd.g-par->colColor.g) / par->fTerminalAge;
  141. par->colColorDelta.b = (info.colColorEnd.b-par->colColor.b) / par->fTerminalAge;
  142. par->colColorDelta.a = (info.colColorEnd.a-par->colColor.a) / par->fTerminalAge;
  143. if(bUpdateBoundingBox) rectBoundingBox.Encapsulate(par->vecLocation.x, par->vecLocation.y);
  144. nParticlesAlive++;
  145. par++;
  146. }
  147. }
  148. vecPrevLocation=vecLocation;
  149. }
  150. void hgeParticleSystem::MoveTo(float x, float y, bool bMoveParticles)
  151. {
  152. int i;
  153. float dx,dy;
  154. if(bMoveParticles)
  155. {
  156. dx=x-vecLocation.x;
  157. dy=y-vecLocation.y;
  158. for(i=0;i<nParticlesAlive;i++)
  159. {
  160. particles[i].vecLocation.x += dx;
  161. particles[i].vecLocation.y += dy;
  162. }
  163. vecPrevLocation.x=vecPrevLocation.x + dx;
  164. vecPrevLocation.y=vecPrevLocation.y + dy;
  165. }
  166. else
  167. {
  168. if(fAge==-2.0) { vecPrevLocation.x=x; vecPrevLocation.y=y; }
  169. else { vecPrevLocation.x=vecLocation.x; vecPrevLocation.y=vecLocation.y; }
  170. }
  171. vecLocation.x=x;
  172. vecLocation.y=y;
  173. }
  174. void hgeParticleSystem::FireAt(float x, float y)
  175. {
  176. Stop();
  177. MoveTo(x,y);
  178. Fire();
  179. }
  180. void hgeParticleSystem::Fire()
  181. {
  182. if(info.fLifetime==-1.0f) fAge=-1.0f;
  183. else fAge=0.0f;
  184. fResidue=0.0;
  185. }
  186. void hgeParticleSystem::Stop(bool bKillParticles)
  187. {
  188. fAge=-2.0f;
  189. if(bKillParticles) 
  190. {
  191. nParticlesAlive=0;
  192. rectBoundingBox.Clear();
  193. }
  194. }
  195. void hgeParticleSystem::Render()
  196. {
  197. int i;
  198. DWORD col;
  199. hgeParticle *par=particles;
  200. col=info.sprite->GetColor();
  201. for(i=0; i<nParticlesAlive; i++)
  202. {
  203. info.sprite->SetColor(par->colColor.GetHWColor());
  204. info.sprite->RenderEx(par->vecLocation.x+fTx, par->vecLocation.y+fTy, par->fSpin*par->fAge, par->fSize);
  205. par++;
  206. }
  207. info.sprite->SetColor(col);
  208. }