Я пытаюсь реализовать эффект фейерверка в C. У меня есть куб с размерами 10x10x10. Ракета начинается с земли, а когда она достигает 8-го этажа, она взрывается. Вот что я не могу сделать — взрыв. Как я могу реализовать это с помощью функции синуса или косинуса?
поэтому в точке (5,0,7) // (x, y, z) // ракета летит в воздухе
for (j=0; j<9; j++) {
setpoint(x, y, j);
delay(100);
clean(); //clears everything
}
Здесь наступает момент, чтобы сделать взрыв. Как этого можно достичь? Он может искриться и в случайных положениях. Заранее спасибо.
Лучше сделать это, используя перевернутую параболу вместо sin / cos. В точке взрыва дайте каждой частице случайную горизонтальную скорость. Эта скорость постоянна до тех пор, пока частица не упадет на землю. Вы также должны дать каждой частице случайную вертикальную скорость. на этот раз, однако, вы добавите к этой скорости величину, пропорциональную -0.5*g*dt^2
(Строго говоря, это численно неправильно, но вы не заметите, если не будете заниматься научным анализом). Вот, g
это ускорение из-за гравитации и dt
это шаг по времени. Это все.
Хех, я нашел немного времени (сделано за 1,5 часа) и буду для этого забавного материала 🙂
Хорошо, сначала несколько обновлений в классе LED_cube для поддержки вывода точек вокселей, а затемнение остального такое же, как для сферы из вашего другого вопроса …
//---------------------------------------------------------------------------
//--- LED cube class ver: 1.01 ----------------------------------------------
//---------------------------------------------------------------------------
#ifndef _LED_cube_h
#define _LED_cube_h
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
const int _LED_cube_size=32;
//---------------------------------------------------------------------------
class LED_cube
{
public:
int n,map[_LED_cube_size][_LED_cube_size][_LED_cube_size];
LED_cube() { n=_LED_cube_size; }
LED_cube(LED_cube& a) { *this=a; }
~LED_cube() { }
LED_cube* operator = (const LED_cube *a) { *this=*a; return this; }
//LED_cube* operator = (const LED_cube &a) { /*...copy...*/ return this; }
void cls(int col); // clear cube with col 0x00BBGGRR
void mul(int mul); // mull all channels by mul and then shr by 8
void point(int x,int y,int z,int col); // draws voxel with col 0x00BBGGRR
void sphere(int x0,int y0,int z0,int r,int col); // draws sphere surface with col 0x00BBGGRR
void glDraw(); // render cube by OpenGL as 1x1x1 cube at 0,0,0
};
//---------------------------------------------------------------------------
void LED_cube::cls(int col)
{
int x,y,z;
for (x=0;x<n;x++)
for (y=0;y<n;y++)
for (z=0;z<n;z++)
map[x][y][z]=col;
}
//---------------------------------------------------------------------------
void LED_cube::mul(int mul)
{
union { BYTE db[4]; int dd; } c;
int x,y,z,i;
for (x=0;x<n;x++)
for (y=0;y<n;y++)
for (z=0;z<n;z++)
{
c.dd=map[x][y][z];
i=c.db[0]; i=(i*mul)>>8; c.db[0]=i;
i=c.db[1]; i=(i*mul)>>8; c.db[1]=i;
i=c.db[2]; i=(i*mul)>>8; c.db[2]=i;
map[x][y][z]=c.dd;
}
}
//---------------------------------------------------------------------------
void LED_cube::point(int x,int y,int z,int col)
{
if ((x>=0)&&(x<n))
if ((y>=0)&&(y<n))
if ((z>=0)&&(z<n))
map[x][y][z]=col;
}
//---------------------------------------------------------------------------
void LED_cube::sphere(int x0,int y0,int z0,int r,int col)
{
int x,y,z,xa,ya,za,xb,yb,zb,xr,yr,zr,xx,yy,zz,rr=r*r;
// bounding box
xa=x0-r; if (xa<0) xa=0; xb=x0+r; if (xb>n) xb=n;
ya=y0-r; if (ya<0) ya=0; yb=y0+r; if (yb>n) yb=n;
za=z0-r; if (za<0) za=0; zb=z0+r; if (zb>n) zb=n;
// project xy plane
for (x=xa,xr=x-x0,xx=xr*xr;x<xb;x++,xr++,xx=xr*xr)
for (y=ya,yr=y-y0,yy=yr*yr;y<yb;y++,yr++,yy=yr*yr)
{
zz=rr-xx-yy; if (zz<0) continue; zr=sqrt(zz);
z=z0-zr; if ((z>0)&&(z<n)) map[x][y][z]=col;
z=z0+zr; if ((z>0)&&(z<n)) map[x][y][z]=col;
}
// project xz plane
for (x=xa,xr=x-x0,xx=xr*xr;x<xb;x++,xr++,xx=xr*xr)
for (z=za,zr=z-z0,zz=zr*zr;z<zb;z++,zr++,zz=zr*zr)
{
yy=rr-xx-zz; if (yy<0) continue; yr=sqrt(yy);
y=y0-yr; if ((y>0)&&(y<n)) map[x][y][z]=col;
y=y0+yr; if ((y>0)&&(y<n)) map[x][y][z]=col;
}
// project yz plane
for (y=ya,yr=y-y0,yy=yr*yr;y<yb;y++,yr++,yy=yr*yr)
for (z=za,zr=z-z0,zz=zr*zr;z<zb;z++,zr++,zz=zr*zr)
{
xx=rr-zz-yy; if (xx<0) continue; xr=sqrt(xx);
x=x0-xr; if ((x>0)&&(x<n)) map[x][y][z]=col;
x=x0+xr; if ((x>0)&&(x<n)) map[x][y][z]=col;
}
}
//---------------------------------------------------------------------------
void LED_cube::glDraw()
{
#ifdef __gl_h_
int x,y,z;
float p[3],dp=1.0/float(n-1);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE,GL_ONE);
glPointSize(2.0);
glBegin(GL_POINTS);
for (p[0]=-0.5,x=0;x<n;x++,p[0]+=dp)
for (p[1]=-0.5,y=0;y<n;y++,p[1]+=dp)
for (p[2]=-0.5,z=0;z<n;z++,p[2]+=dp)
{
glColor4ubv((BYTE*)(&map[x][y][z]));
glVertex3fv(p);
}
glEnd();
glDisable(GL_BLEND);
glPointSize(1.0);
#endif
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
//--------------------------------------------------------------------------
void mul(int mul);
— используется для затемнения всей карты вокселейvoid point(int x,int y,int z,int col);
— используется для задания цвета одного вокселяТеперь частицы
//---------------------------------------------------------------------------
class particle
{
public:
double x, y, z; // position
double vx,vy,vz; // velocity
double ax,ay,az; // acceleration driving force/m after update is reseted
double i; // intensity
particle()
{
x=0.0; y=0.0; z=0.0;
vx=0.0; vy=0.0; vz=0.0;
ax=0.0; ay=0.0; az=0.0;
i=0.0;
};
particle(particle& a){ *this=a; };
~particle(){};
particle* operator = (const particle *a) { *this=*a; return this; };
// particle* operator = (const particle &a) { ...copy... return this; };
void update(double dt)
{
double c0,c;
// gravity
ay-=9.81;
// friction in gass
c=0.001;
if (vx>0.0) c0=-c; else c0=+c; ax+=vx*vx*c0;
if (vy>0.0) c0=-c; else c0=+c; ay+=vy*vy*c0;
if (vz>0.0) c0=-c; else c0=+c; az+=vz*vz*c0;
// friction in liquid
c=0.0;
ax-=vx*vx*vx*c;
ay-=vy*vy*vy*c;
az-=vz*vz*vz*c;
// D'Lambert
vx+=ax*dt;
vy+=ay*dt;
vz+=az*dt;
x+=vx*dt;
y+=vy*dt;
z+=vz*dt;
// reset acceleration
ax=0.0; ay=0.0; az=0.0;
}
};
//---------------------------------------------------------------------------
List<particle> particles; // use any list/array you have at your disposal you need just function add and delete item
//---------------------------------------------------------------------------
вот как нарисовать сцену:
cube.mul(200); // dimm the voxel map insted of clearing it (intensity*=200/256)
for (int i=0;i<particles.num;i++)
{
particle *p=&particles[i];
int j=double(255.0*p->i);
if (j<0) j=0;
if (j>255) j=255;
cube.point(p->x,p->y,p->z,0x00010101*j);
}
cube.glDraw();
Это как обновить симуляцию в некотором таймере (double dt = интервал таймера в секундах !!!)
double i0=1.0; // intensity at shoot start
double i1=0.9*i0; // intensity after explosion
double v0=0.6*double(_LED_cube_size); // shoot start speed
double v1=0.5*v0,v1h=0.5*v1; // explosion speed
if (particles.num==0) // shoot new particle if none in list
{
particle p;
p.x=_LED_cube_size>>1;
p.y=0.0;
p.z=_LED_cube_size>>1;
p.vy=v0;
p.i=i0;
particles.add(p);
}
for (int i=0;i<particles.num;i++) // update all particles in list
{
particle *p=&particles[i];
p->update(dt);
if (fabs(p->i-i0)<1e-6) // intensity detect state before explosion
{
if (p->vy<=0.0) // explode near/after peak reached
{
particle q;
q.x=p->x; // copy position
q.y=p->y;
q.z=p->z;
q.i=i1; // new intensity
particles.del(i); // remove old particle
i--;
for (int j=0;j<50;j++) // add new random particles
{
q.vx=v1*Random()-v1h;
q.vy=v1*Random()-v1h;
q.vz=v1*Random()-v1h;
particles.add(q)-v1h;
}
continue; // avoid usage of p pointer after delete
}
}
else{ // after explosion
p->i*=0.95; // dimm intensity
}
if ((p->y<0.0)||(p->i<0.01))// remove particles below the ground or too dimmed out
{
particles.del(i);
i--;
continue; // avoid usage of p pointer after delete
}
}
Вот так это выглядит
Извините за баннер, но у меня нет ничего солидного для преобразования gif, и этот сайт не будет принимать wmv … Вы должны поиграть с константами, чтобы соответствовать желаемому результату на ваших константах размера светодиодного куба, чтобы играть с:
v0,v1,i0,i1
[Заметки]
List<>
это просто шаблон для динамического массива может использовать что угодно из std::
или собственный массив …
Не забудьте установить dt
постоянная времени между обновлениями. Надеюсь, я не забыл что-то скопировать. Надеюсь, поможет