00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00030
00031 #include <math.h>
00032
00033 #include "stratagus.h"
00034 #include "particle.h"
00035 #include "video.h"
00036
00037
00038 static const int gravity = 32 * 12;
00039
00040 static inline float deg2rad(int degrees) {
00041 return degrees * (3.1415926535f / 180);
00042 }
00043
00044
00045 CChunkParticle::CChunkParticle(CPosition position, Animation *smokeAnimation) :
00046 CParticle(position), initialPos(position), nextSmokeTicks(0), age(0),
00047 height(0.f)
00048 {
00049 float radians = deg2rad(MyRand() % 360);
00050 direction.x = cos(radians);
00051 direction.y = sin(radians);
00052
00053 const int maxVelocity = 400;
00054 initialVelocity = MyRand() % maxVelocity;
00055
00056 int minTrajectoryAngle = 77;
00057 trajectoryAngle = deg2rad(MyRand() % (90 - minTrajectoryAngle) + minTrajectoryAngle);
00058
00059 lifetime = (int)(1000 * (initialVelocity * sin(trajectoryAngle) / gravity) * 2);
00060 this->smokeAnimation = smokeAnimation->clone();
00061 }
00062
00063 CChunkParticle::~CChunkParticle()
00064 {
00065 delete smokeAnimation;
00066 }
00067
00068 static float calculateScreenPos(float posy, float height)
00069 {
00070 return posy - height * 0.2f;
00071 }
00072
00073 void CChunkParticle::draw()
00074 {
00075 CPosition screenPos = ParticleManager.getScreenPos(pos);
00076 Uint32 color = ColorBlack;
00077
00078 Video.DrawRectangleClip(color, (int)screenPos.x - 1, (int)calculateScreenPos(screenPos.y, height) - 1, 2, 2);
00079 }
00080
00081 static float getHorizontalPosition(int initialVelocity, float trajectoryAngle, float time)
00082 {
00083 return (initialVelocity * cos(trajectoryAngle)) * time;
00084 }
00085
00086 static float getVerticalPosition(int initialVelocity, float trajectoryAngle, float time)
00087 {
00088 return (initialVelocity * sin(trajectoryAngle)) * time - (gravity / 2.0f) * (time * time);
00089 }
00090
00091 void CChunkParticle::update(int ticks)
00092 {
00093 age += ticks;
00094 if (age >= lifetime) {
00095 destroy();
00096 return;
00097 }
00098
00099 const int minSmokeTicks = 150;
00100 const int randSmokeTicks = 50;
00101
00102 if (age > nextSmokeTicks) {
00103 CPosition p(pos.x, calculateScreenPos(pos.y, height));
00104 Animation *animation = smokeAnimation->clone();
00105 CSmokeParticle *smoke = new CSmokeParticle(p, animation);
00106 ParticleManager.add(smoke);
00107
00108 nextSmokeTicks += MyRand() % randSmokeTicks + minSmokeTicks;
00109 }
00110
00111 float time = age / 1000.f;
00112
00113 float distance = getHorizontalPosition(initialVelocity, trajectoryAngle, time);
00114 pos.x = initialPos.x + distance * direction.x;
00115 pos.y = initialPos.y + distance * direction.y;
00116
00117 height = getVerticalPosition(initialVelocity, trajectoryAngle, time);
00118 }
00119
00120
00121 CParticle* CChunkParticle::clone()
00122 {
00123 return new CChunkParticle(pos, smokeAnimation);
00124 }
00125