回 帖 发 新 帖 刷新版面

主题:粒子系统

由粒子系统(5000个粒子)实现的黄金火焰十字架。
平台DOS + Watcom C

[img]http://www.wodutom.com/coolwindows/10z.PNG[/img]

这个是50000个粒子形成的粒子星云

[img]http://www.wodutom.com/coolwindows/star.PNG[/img]

#include <i86.h>
#include <iostream.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>

#include "x\xsvga.hpp"
#include "x\xtimer.hpp"
#include "x\xkey.hpp"
#include "x\xpsystem.hpp"
#include "x\xmath.hpp"

cMath *pmath;
int angle=0;

/*坐标更新*/
cParticleF2D& drop(cParticleF2D& x,cParameterQueue& paras)
{
        float t;
        paras.Peek(&t);

        x.vx+=x.ax*t;
        x.vy+=x.ay*t;
        x.x+=x.vx*t;
        x.y+=x.vy*t;

        return x;
}
/*坐标转换并显示*/
cParticleF2D& draw(cParticleF2D& x,cParameterQueue& paras)
{
        cBitmap *bmp;
        paras.Peek(&bmp);
        char *p;

        long dx,dy;
        dx=(x.x-400)*pmath->fcos(angle)-(300-x.y)*pmath->fsin(angle)+400;
        dy=(x.x-400)*pmath->fsin(angle)+(300-x.y)*pmath->fcos(angle)+300;

        if(dx>0&&dx<799&&dy>0&&dy<599)
        {
                p=(char *)bmp->GetBuffer(dx,600-dy);
                bmp->Set(p,&x.C);
        }

        if(dx<0||dx>=800) x.vx=-x.vx;
        if(dy<0||dy>=600) x.vy=-x.vy;
        return x;
}

void main()
{
        long i;
        float t=0.01;
        cTimer timer;
        cSVGA* svga=cSVGA::Instance();
        float RGB[256][3];
        cBitmap bmp;
        pmath=cMath::Instance();

        cParticleF2D particle;
        cParticleGroup<cParticleF2D> pg(50000,2);  /*第一个例子是5000*/

        memset(&particle,0,sizeof(particle));
        particle.y=300;
        particle.x=400;
        particle.C=255;
        for(i=0;i<50000;i++)
        {
                particle.ax=rand()%10191/1000.0-5;  /*水平随机加速度*/
                particle.ay=rand()%8191/1000.0-4;   /*垂直随机加速度*/
                pg.Add(particle);
        }
        pg.AddTransFunc(drop);  /*绑定函数*/
        pg.AddTransPara(&t);    /*绑定参数*/

        svga->SetMode(800,600,8,cSVGA::_c_linear);
        bmp.Create(svga->GetDirectBuffer(),800,600,8);

        cPALETTE pal;
        for(i=0;i<256;i++) RGB[i][0]=sqrt(i)/16.0;
        for(i=0;i<256;i++) RGB[i][1]=pow(i,0.7)/48.5;
        for(i=0;i<256;i++) RGB[i][2]=(float)(i*i)/65536.0;
        for(i=0;i<256;i++) pal[i].R=RGB[i][0]*256;
        for(i=0;i<256;i++) pal[i].G=RGB[i][1]*256;
        for(i=0;i<256;i++) pal[i].B=RGB[i][2]*256;
        svga->SetPal(&pal);

        pg.AddTransFunc(draw);
        pg.AddTransPointPara(&bmp);

        char *p,*q;
        while(cKey::Asc()!=27)
        {
                /*自动对pg里面的每一个粒子调用绑定的函数*/
                pg.Refresh();
                /*全屏 Blur*/
                for(p=(char *)bmp.GetBuffer(1,1),q=(char *)bmp.GetBuffer(bmp.Width()-2,bmp.Height()-2);p<q;p++)
                        *p=*(p-1)+*(p+1)+*(p-bmp.Width())+*(p+bmp.Width())>>2;
                /*全屏 FadeOut*/
                for(p=(char *)bmp.GetBuffer(0,0),q=(char *)bmp.GetBuffer(bmp.Width()-1,bmp.Height()-1);p<q;p++) if(*p>0) (*p)--;
                angle++; /*第一个例子是angle+=0;*/
        }
        delete pmath;
        delete svga;
}

回复列表 (共15个回复)

沙发

什么意思?[em10]

板凳

DOS下纯C++写的图像程序啊!

3 楼

可以为每一个粒子组独立绑定无限数量的坐标运算(vertex shader)或颜色运算(pixel shader)函数(可惜都是由CPU完成的,而且现在还不支持动态参数,用到只好用全局变量了(上面例子中的pmath->fcos(angle)就是一个动态参数,因为angle随时在变,如果做在参数表里就会因为不断刷新参数表冲击渲染流水线,严重降低效率,目前还没想到好的解决办法),要用显卡做还是只有OpenGL和DX,:)。由粒子组对象Refresh时统一调用。

4 楼

粒子系统主要可以用来实现物理模拟,比如自由落体、双(多)星系统、爆炸等,或某些自然效果,比如烟雨、瀑布等。

5 楼

如果要编写这样的程序,至少要具备什么知识,你的这个程序激起了对这方面强列的兴趣

6 楼

至少要具备比较扎实的语言功底,能够很清楚自己在什么地方操作什么数据(指指针)

7 楼

TC3.0好象不能运行!![em8][em4]

8 楼

当然,里面缺很多函数没给出来,这个只是主程序
#include "x\xsvga.hpp"
#include "x\xtimer.hpp"
#include "x\xkey.hpp"
#include "x\xpsystem.hpp"
#include "x\xmath.hpp"
这些是自己写的.而且TC3.0是16位的,要32位的编译器才可以.

9 楼

/*可以在TC下运行的简化版,最好不要在XP/2000下运行,否则速度很慢*/

[img]http://www.wodutom.com/coolwindows/startc.png[/img]

#include<math.h>
#include<mem.h>
#include<dos.h>
#include<stdlib.h>

#define p_num 2000

struct _Particle
{
    float vx,vy,ax,ay,x,y;
    unsigned char c;
};

void SetColor(int c,int r,int g,int b)
{
    outportb(0x3c6,255);
    outportb(0x3c8,c);
    outportb(0x3c9,r>>2);
    outportb(0x3c9,g>>2);
    outportb(0x3c9,b>>2);
}

char far *GetBuffer(long x,long y)
{
    return (char far *)(0xa0000000L+x+y*320);
}

void blur()
{
    unsigned char far *p, far *q;
    for(p=GetBuffer(1,1),q=GetBuffer(318,198);p<q;p++) *p=*(p-1)+*(p+1)+*(p-320)+*(p+320)>>2;
}

void main()
{
    struct _Particle pg[p_num];
    float fcos,fsin,t=0.01,angle=0.0;
    float RGB[256][3];
    int i;
    int dx,dy;

    memset(pg,0,p_num*sizeof(struct _Particle));
    for(i=0;i<p_num;i++)
    {
        pg[i].x=160;
        pg[i].y=100;
        pg[i].c=255;
        pg[i].ax=rand()%10191/1000.0-5;
        pg[i].ay=rand()%8191/1000.0-4;
    }
    for(i=0;i<256;i++) RGB[i][0]=sqrt(i)/16.0;
    for(i=0;i<256;i++) RGB[i][1]=pow(i,0.7)/48.5;
    for(i=0;i<256;i++) RGB[i][2]=(i*i)/65536.0;

    _AX=0x13;
    asm int 0x10;

    for(i=0;i<256;i++) SetColor(i,RGB[i][0]*256,RGB[i][1]*256,RGB[i][2]*256);

    while(inportb(0x60)!=1)
    {
        fcos=cos(angle);
        fsin=sin(angle);
        for(i=0;i<p_num;i++)
        {
            pg[i].vx+=pg[i].ax*t;
            pg[i].vy+=pg[i].ay*t;
            pg[i].x+=pg[i].vx*t;
            pg[i].y+=pg[i].vy*t;
            dx=(pg[i].x-160)*fcos-(100-pg[i].y)*fsin+160;
            dy=(pg[i].x-160)*fsin+(100-pg[i].y)*fcos+100;
            if(dx>0&&dx<319&&dy>0&&dy<199) *GetBuffer(dx,dy)=pg[i].c;
            if(dx<0||dx>=320) pg[i].vx=-pg[i].vx;
            if(dy<0||dy>=200) pg[i].vy=-pg[i].vy;
        }
        blur();
        angle+=0.01;
    }

    _AX=0x03;
    asm int 0x10;
}

10 楼

把粒子组初始化为直立椭圆,并在坐标系统中加入一些小幅度的随机运动分子,就可以做出如蜡烛火焰一样的动态效果。改变颜色基调,新建三个粒子组,让其一以不同的水平速度做抛物运动,到地面时回归原位,第二个组在地面做圆形振动,第三个组做爆炸效果,和起来就可以做成一个瀑布的效果。

我来回复

您尚未登录,请登录后再回复。点此登录或注册