项目: 互动粒子仿真
生活随笔
收集整理的這篇文章主要介紹了
项目: 互动粒子仿真
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
目錄
- 一、最終效果展示
- 二、靜態(tài)小球的初始化顯示
- 三、小球的運(yùn)動(dòng)與反彈
- 四、小球運(yùn)動(dòng)的規(guī)范化
- 五、鼠標(biāo)的吸引力
- 六、鼠標(biāo)的擊打斥力
- 七、鼠標(biāo)的擾動(dòng)力
一、最終效果展示
效果圖如下:
二、靜態(tài)小球的初始化顯示
代碼如下:
#include<stdio.h> #include<string.h> #include<graphics.h> #include<time.h> #include<math.h>#define WIDTH 1024 //屏幕的寬 #define HEIGHT 768 //屏幕的高 #define NUM_MOVERS 800 //小球的數(shù)量//定義小球結(jié)構(gòu) struct Mover {COLORREF color;//顏色float x,y;//坐標(biāo)float vX,vY;//速度float radius;//半徑 };//定義全局變量 struct Mover movers[NUM_MOVERS];//小球數(shù)組 void startup() {//設(shè)置隨機(jī)種子srand((unsigned int)time(NULL));//初始化小球數(shù)組for(int i=0;i<NUM_MOVERS;i++){movers[i].color=RGB(rand()%256,rand()%256,rand()%256);movers[i].x=rand()%WIDTH;movers[i].y=rand()%HEIGHT;movers[i].vX=float(cos(float(i)))*(rand()%34);movers[i].vY=float(sin(float(i)))*(rand()%34);movers[i].radius=(rand()%34)/15.0;}initgraph(WIDTH,HEIGHT);BeginBatchDraw(); }void show() {int i;clearrectangle(0,0,WIDTH-1,HEIGHT-1);//清除畫面中的全部矩形區(qū)域for(i=0;i<NUM_MOVERS;i++){//畫小球setcolor(movers[i].color);setfillstyle(movers[i].color);fillcircle(int(movers[i].x+0.5),int(movers[i].y+0.5),int(movers[i].radius+0.5));}FlushBatchDraw();Sleep(2); }void updateWithoutInput() {}void updateWithInput() {}void gameover() {EndBatchDraw();closegraph(); }int main() {startup();//數(shù)據(jù)的初始化while(1){show();//顯示畫面updateWithoutInput();//與用戶輸入無(wú)關(guān)的更新updateWithInput();//與用戶輸入有關(guān)的更新}gameover();//游戲結(jié)束,進(jìn)行后續(xù)處理return 0; }效果圖如下:
三、小球的運(yùn)動(dòng)與反彈
代碼如下:
#include<stdio.h> #include<string.h> #include<graphics.h> #include<time.h> #include<math.h>#define WIDTH 1024 //屏幕的寬 #define HEIGHT 768 //屏幕的高 #define NUM_MOVERS 800 //小球的數(shù)量//定義小球結(jié)構(gòu) struct Mover {COLORREF color;//顏色float x,y;//坐標(biāo)float vX,vY;//速度float radius;//半徑 };//定義全局變量 struct Mover movers[NUM_MOVERS];//小球數(shù)組 void startup() {//設(shè)置隨機(jī)種子srand((unsigned int)time(NULL));//初始化小球數(shù)組for(int i=0;i<NUM_MOVERS;i++){movers[i].color=RGB(rand()%256,rand()%256,rand()%256);movers[i].x=rand()%WIDTH;movers[i].y=rand()%HEIGHT;movers[i].vX=float(cos(float(i)))*(rand()%34);movers[i].vY=float(sin(float(i)))*(rand()%34);movers[i].radius=(rand()%34)/15.0;}initgraph(WIDTH,HEIGHT);BeginBatchDraw(); }void show() {int i;clearrectangle(0,0,WIDTH-1,HEIGHT-1);//清除畫面中的全部矩形區(qū)域for(i=0;i<NUM_MOVERS;i++){//畫小球setcolor(movers[i].color);setfillstyle(movers[i].color);fillcircle(int(movers[i].x+0.5),int(movers[i].y+0.5),int(movers[i].radius+0.5));}FlushBatchDraw();Sleep(2); }void updateWithoutInput() {int i;float x,y,vX,vY;float nextX,nextY;for(i=0;i<NUM_MOVERS;i++){float x = movers[i].x;//當(dāng)前小球的坐標(biāo)float y = movers[i].y;float vX = movers[i].vX;//當(dāng)前小球的速度float vY = movers[i].vY;//根據(jù)“位置+速度”更新小球的坐標(biāo)nextX=x +vX;nextY=y+vY;//如果小球超過(guò)上、下、左、右4個(gè)邊界,將位置設(shè)為邊界處,速度反向if(nextX>WIDTH){nextX=WIDTH;vX=-1*vX;}else if(nextX<0){nextX=0;vX=-1*vX;}if(nextY>HEIGHT){nextY=HEIGHT;vY=-1*vY;}else if(nextY<0){nextY=0;vY=-1*vY;}//更新小球位置movers[i].vX=vX;movers[i].vY=vY;movers[i].x=nextX;movers[i].y=nextY;} }void updateWithInput() {}void gameover() {EndBatchDraw();closegraph(); }int main() {startup();//數(shù)據(jù)的初始化while(1){show();//顯示畫面updateWithoutInput();//與用戶輸入無(wú)關(guān)的更新updateWithInput();//與用戶輸入有關(guān)的更新}gameover();//游戲結(jié)束,進(jìn)行后續(xù)處理return 0; }效果圖如下:
四、小球運(yùn)動(dòng)的規(guī)范化
加入阻尼,模擬真實(shí)世界中運(yùn)動(dòng)物體受摩檫力逐漸變慢的效果,為了避免小球絕對(duì)靜止, 當(dāng)小球速度過(guò)小時(shí) 使其速度增加,修改小球的半徑,速度越大則半徑越大。代碼如下:
#include<stdio.h> #include<string.h> #include<graphics.h> #include<time.h> #include<math.h>#define WIDTH 1024 //屏幕的寬 #define HEIGHT 768 //屏幕的高 #define NUM_MOVERS 800 //小球的數(shù)量 #define FRICTION 0.96f//摩檫力、阻尼系數(shù)//定義小球結(jié)構(gòu) struct Mover {COLORREF color;//顏色float x,y;//坐標(biāo)float vX,vY;//速度float radius;//半徑 };//定義全局變量 struct Mover movers[NUM_MOVERS];//小球數(shù)組 void startup() {//設(shè)置隨機(jī)種子srand((unsigned int)time(NULL));//初始化小球數(shù)組for(int i=0;i<NUM_MOVERS;i++){movers[i].color=RGB(rand()%256,rand()%256,rand()%256);movers[i].x=rand()%WIDTH;movers[i].y=rand()%HEIGHT;movers[i].vX=float(cos(float(i)))*(rand()%34);movers[i].vY=float(sin(float(i)))*(rand()%34);movers[i].radius=(rand()%34)/15.0;}initgraph(WIDTH,HEIGHT);BeginBatchDraw(); }void show() {int i;clearrectangle(0,0,WIDTH-1,HEIGHT-1);//清除畫面中的全部矩形區(qū)域for(i=0;i<NUM_MOVERS;i++){//畫小球setcolor(movers[i].color);setfillstyle(movers[i].color);fillcircle(int(movers[i].x+0.5),int(movers[i].y+0.5),int(movers[i].radius+0.5));}FlushBatchDraw();Sleep(2); }void updateWithoutInput() {int i;float x,y,vX,vY;float nextX,nextY;float avgVX,avgVY,avgV,sc;for(i=0;i<NUM_MOVERS;i++){float x = movers[i].x;//當(dāng)前小球的坐標(biāo)float y = movers[i].y;float vX = movers[i].vX;//當(dāng)前小球的速度float vY = movers[i].vY;//小球運(yùn)動(dòng)有一個(gè)阻尼(摩擦力),速度逐漸減小vX=vX*FRICTION;vY=vY*FRICTION;//速度的絕對(duì)值avgVX=abs(vX);avgVY=abs(vY);//兩個(gè)方向速度的平均avgV=(avgVX+avgVY)*0.5f;//因?yàn)橛猩厦孀枘岬淖饔?#xff0c;如果速度過(guò)小,乘以一個(gè)0~3的隨機(jī)數(shù),//會(huì)以比較大的概率讓速度變大if(avgVX<0.1)vX=vX*float(rand())/RAND_MAX*3;if(avgVY<0.1)vY=vY*float(rand())/RAND_MAX*3;//小球的半徑在0.4~3.5之間,速度越大,半徑越大sc=avgV*0.45f;sc=max(min(sc,3.5f),0.4f);movers[i].radius=sc;//根據(jù)“位置+速度”更新小球的坐標(biāo)nextX=x +vX;nextY=y+vY;//如果小球超過(guò)上、下、左、右4個(gè)邊界,將位置設(shè)為邊界處,速度反向if(nextX>WIDTH){nextX=WIDTH;vX=-1*vX;}else if(nextX<0){nextX=0;vX=-1*vX;}if(nextY>HEIGHT){nextY=HEIGHT;vY=-1*vY;}else if(nextY<0){nextY=0;vY=-1*vY;}//更新小球位置movers[i].vX=vX;movers[i].vY=vY;movers[i].x=nextX;movers[i].y=nextY;} }void updateWithInput() {}void gameover() {EndBatchDraw();closegraph(); }int main() {startup();//數(shù)據(jù)的初始化while(1){show();//顯示畫面updateWithoutInput();//與用戶輸入無(wú)關(guān)的更新updateWithInput();//與用戶輸入有關(guān)的更新}gameover();//游戲結(jié)束,進(jìn)行后續(xù)處理return 0; }效果圖如下:
五、鼠標(biāo)的吸引力
增加鼠標(biāo)對(duì)一定范圍內(nèi)小球的吸引力,小球距離鼠標(biāo)越近,吸引力越大。代碼如下:
#include<stdio.h> #include<string.h> #include<graphics.h> #include<time.h> #include<math.h>#define WIDTH 1024 //屏幕的寬 #define HEIGHT 768 //屏幕的高 #define NUM_MOVERS 800 //小球的數(shù)量 #define FRICTION 0.96f//摩檫力、阻尼系數(shù)//定義小球結(jié)構(gòu) struct Mover {COLORREF color;//顏色float x,y;//坐標(biāo)float vX,vY;//速度float radius;//半徑 };//定義全局變量 struct Mover movers[NUM_MOVERS];//小球數(shù)組 int mouseX,mouseY;//當(dāng)前鼠標(biāo)坐標(biāo) void startup() {//設(shè)置隨機(jī)種子srand((unsigned int)time(NULL));//初始化小球數(shù)組for(int i=0;i<NUM_MOVERS;i++){movers[i].color=RGB(rand()%256,rand()%256,rand()%256);movers[i].x=rand()%WIDTH;movers[i].y=rand()%HEIGHT;movers[i].vX=float(cos(float(i)))*(rand()%34);movers[i].vY=float(sin(float(i)))*(rand()%34);movers[i].radius=(rand()%34)/15.0;}//初始化當(dāng)前鼠標(biāo)在畫布中心mouseX=WIDTH/2;mouseY=HEIGHT/2;initgraph(WIDTH,HEIGHT);BeginBatchDraw(); }void show() {int i;clearrectangle(0,0,WIDTH-1,HEIGHT-1);//清除畫面中的全部矩形區(qū)域for(i=0;i<NUM_MOVERS;i++){//畫小球setcolor(movers[i].color);setfillstyle(movers[i].color);fillcircle(int(movers[i].x+0.5),int(movers[i].y+0.5),int(movers[i].radius+0.5));}FlushBatchDraw();Sleep(2); }void updateWithoutInput() {int i;float x,y,vX,vY;float nextX,nextY;float avgVX,avgVY,avgV,sc;//阻尼float toDist=WIDTH*0.36;//吸引距離,若小球與鼠標(biāo)的距離在此范圍內(nèi)則會(huì)受向內(nèi)的引力float d;//當(dāng)前小球和鼠標(biāo)位置的距離float dX,dY;//計(jì)算小球當(dāng)前位置的差 for(i=0;i<NUM_MOVERS;i++){x = movers[i].x;//當(dāng)前小球的坐標(biāo)y = movers[i].y;vX = movers[i].vX;//當(dāng)前小球的速度vY = movers[i].vY;dX=x-mouseX;//計(jì)算小球當(dāng)前位置的差 dY=y-mouseY;d=sqrt(dX*dX+dY*dY);//當(dāng)前小球和鼠標(biāo)位置的距離//下面將dX,dY歸一化,僅反映方向,和距離無(wú)關(guān)if(d!=0){dX=dX/d;dY=dY/d;}else{dX=0;dY=0;}//小球距離鼠標(biāo)<toDist,再次范圍內(nèi)小球會(huì)受到鼠標(biāo)的吸引if(d<toDist){//吸引力引起的加速度幅度,小球距離鼠標(biāo)越近引起的加速度越大float toAcc=(1-(d/toDist))*WIDTH*0.0014f;//由dX,dY歸一化方向信息,加速度幅度值為toAcc,得到新的小球高度vX=vX-dX*toAcc;vY=vY-dY*toAcc;}//小球運(yùn)動(dòng)有一個(gè)阻尼(摩擦力),速度逐漸減小vX=vX*FRICTION;vY=vY*FRICTION;//速度的絕對(duì)值avgVX=abs(vX);avgVY=abs(vY);//兩個(gè)方向速度的平均avgV=(avgVX+avgVY)*0.5f;//因?yàn)橛猩厦孀枘岬淖饔?#xff0c;如果速度過(guò)小,乘以一個(gè)0~3的隨機(jī)數(shù),//會(huì)以比較大的概率讓速度變大if(avgVX<0.1)vX=vX*float(rand())/RAND_MAX*3;if(avgVY<0.1)vY=vY*float(rand())/RAND_MAX*3;//小球的半徑在0.4~3.5之間,速度越大,半徑越大sc=avgV*0.45f;sc=max(min(sc,3.5f),0.4f);movers[i].radius=sc;//根據(jù)“位置+速度”更新小球的坐標(biāo)nextX=x +vX;nextY=y+vY;//如果小球超過(guò)上、下、左、右4個(gè)邊界,將位置設(shè)為邊界處,速度反向if(nextX>WIDTH){nextX=WIDTH;vX=-1*vX;}else if(nextX<0){nextX=0;vX=-1*vX;}if(nextY>HEIGHT){nextY=HEIGHT;vY=-1*vY;}else if(nextY<0){nextY=0;vY=-1*vY;}//更新小球位置movers[i].vX=vX;movers[i].vY=vY;movers[i].x=nextX;movers[i].y=nextY;} }void updateWithInput() {MOUSEMSG m;//定義鼠標(biāo)消息while(MouseHit())//檢測(cè)當(dāng)前是否有鼠標(biāo)消息{m=GetMouseMsg();//如果鼠標(biāo)移動(dòng),更新當(dāng)前鼠標(biāo)坐標(biāo)變量if(m.uMsg==WM_MOUSEMOVE)//如果鼠標(biāo)移動(dòng),更新當(dāng)前鼠標(biāo)坐標(biāo)變量{mouseX=m.x;mouseY=m.y;}} }void gameover() {EndBatchDraw();closegraph(); }int main() {startup();//數(shù)據(jù)的初始化while(1){show();//顯示畫面updateWithoutInput();//與用戶輸入無(wú)關(guān)的更新updateWithInput();//與用戶輸入有關(guān)的更新}gameover();//游戲結(jié)束,進(jìn)行后續(xù)處理return 0; }效果圖如下:
六、鼠標(biāo)的擊打斥力
當(dāng)鼠標(biāo)左鍵按下時(shí)會(huì)對(duì)一定范圍內(nèi)的小球產(chǎn)生擊打斥力, 類似于往池塘中扔一個(gè)石頭,距離越近影響越大。代碼如下:
#include<stdio.h> #include<string.h> #include<graphics.h> #include<time.h> #include<math.h>#define WIDTH 1024 //屏幕的寬 #define HEIGHT 768 //屏幕的高 #define NUM_MOVERS 800 //小球的數(shù)量 #define FRICTION 0.96f//摩檫力、阻尼系數(shù)//定義小球結(jié)構(gòu) struct Mover {COLORREF color;//顏色float x,y;//坐標(biāo)float vX,vY;//速度float radius;//半徑 };//定義全局變量 struct Mover movers[NUM_MOVERS];//小球數(shù)組 int mouseX,mouseY;//當(dāng)前鼠標(biāo)坐標(biāo) int isMouseDown;//鼠標(biāo)左鍵是否按下 void startup() {//設(shè)置隨機(jī)種子srand((unsigned int)time(NULL));//初始化小球數(shù)組for(int i=0;i<NUM_MOVERS;i++){movers[i].color=RGB(rand()%256,rand()%256,rand()%256);movers[i].x=rand()%WIDTH;movers[i].y=rand()%HEIGHT;movers[i].vX=float(cos(float(i)))*(rand()%34);movers[i].vY=float(sin(float(i)))*(rand()%34);movers[i].radius=(rand()%34)/15.0;}//初始化當(dāng)前鼠標(biāo)在畫布中心mouseX=WIDTH/2;mouseY=HEIGHT/2;isMouseDown=0;//初始鼠標(biāo)未按下initgraph(WIDTH,HEIGHT);BeginBatchDraw(); }void show() {int i;clearrectangle(0,0,WIDTH-1,HEIGHT-1);//清除畫面中的全部矩形區(qū)域for(i=0;i<NUM_MOVERS;i++){//畫小球setcolor(movers[i].color);setfillstyle(movers[i].color);fillcircle(int(movers[i].x+0.5),int(movers[i].y+0.5),int(movers[i].radius+0.5));}FlushBatchDraw();Sleep(2); }void updateWithoutInput() {int i;float x,y,vX,vY;float nextX,nextY;float avgVX,avgVY,avgV,sc;//阻尼float toDist=WIDTH*0.36;//吸引距離,若小球與鼠標(biāo)的距離在此范圍內(nèi)則會(huì)受向內(nèi)的引力float blowDist=WIDTH*0.25;//擊打距離,小球與鼠標(biāo)的距離在次范圍內(nèi)會(huì)受到向外的斥力float stirDist=WIDTH*0.125;//擾動(dòng)距離,小球距離鼠標(biāo)在此范圍內(nèi)會(huì)受到鼠標(biāo)的擾動(dòng)float d;//當(dāng)前小球和鼠標(biāo)位置的距離float dX,dY;//計(jì)算小球當(dāng)前位置的差 for(i=0;i<NUM_MOVERS;i++){x = movers[i].x;//當(dāng)前小球的坐標(biāo)y = movers[i].y;vX = movers[i].vX;//當(dāng)前小球的速度vY = movers[i].vY;dX=x-mouseX;//計(jì)算小球當(dāng)前位置的差 dY=y-mouseY;d=sqrt(dX*dX+dY*dY);//當(dāng)前小球和鼠標(biāo)位置的距離//下面將dX,dY歸一化,僅反映方向,和距離無(wú)關(guān)if(d!=0){dX=dX/d;dY=dY/d;}else{dX=0;dY=0;}//小球距離鼠標(biāo)<toDist,再次范圍內(nèi)小球會(huì)受到鼠標(biāo)的吸引if(d<toDist){//吸引力引起的加速度幅度,小球距離鼠標(biāo)越近引起的加速度越大//但吸引力的值明顯比上面斥力的值小很多float toAcc=(1-(d/toDist))*WIDTH*0.0014f;//由dX,dY歸一化方向信息,加速度幅度值為toAcc,得到新的小球高度vX=vX-dX*toAcc;vY=vY-dY*toAcc;}//當(dāng)鼠標(biāo)左鍵按下,并且小球距離鼠標(biāo)<blowDist(在擊打范圍內(nèi))時(shí)會(huì)受到向外的斥力if(isMouseDown&&d<blowDist){//擊打力引起的加速度幅度,這個(gè)公式表示小球距離鼠標(biāo)越近擊打斥力引起的加速度越大float blowAcc=(1-(d/blowDist))*10;//由上面得到的dX,dY歸一化方向信息,上面的加速度幅度值為blowAcc,得到新的小球速度//float(rand())/RAND_MAX產(chǎn)生0~1的隨機(jī)數(shù)//0.5f-float(rand())/RAND_MAX產(chǎn)生-0.5~0.5的隨機(jī)數(shù),加入一些擾動(dòng)vX=vX+dX*blowAcc+0.5f-float(rand())/RAND_MAX;vY=vY+dY*blowAcc+0.5f-float(rand())/RAND_MAX;}//小球運(yùn)動(dòng)有一個(gè)阻尼(摩擦力),速度逐漸減小vX=vX*FRICTION;vY=vY*FRICTION;//速度的絕對(duì)值avgVX=abs(vX);avgVY=abs(vY);//兩個(gè)方向速度的平均avgV=(avgVX+avgVY)*0.5f;//因?yàn)橛猩厦孀枘岬淖饔?#xff0c;如果速度過(guò)小,乘以一個(gè)0~3的隨機(jī)數(shù),//會(huì)以比較大的概率讓速度變大if(avgVX<0.1)vX=vX*float(rand())/RAND_MAX*3;if(avgVY<0.1)vY=vY*float(rand())/RAND_MAX*3;//小球的半徑在0.4~3.5之間,速度越大,半徑越大sc=avgV*0.45f;sc=max(min(sc,3.5f),0.4f);movers[i].radius=sc;//根據(jù)“位置+速度”更新小球的坐標(biāo)nextX=x +vX;nextY=y+vY;//如果小球超過(guò)上、下、左、右4個(gè)邊界,將位置設(shè)為邊界處,速度反向if(nextX>WIDTH){nextX=WIDTH;vX=-1*vX;}else if(nextX<0){nextX=0;vX=-1*vX;}if(nextY>HEIGHT){nextY=HEIGHT;vY=-1*vY;}else if(nextY<0){nextY=0;vY=-1*vY;}//更新小球位置movers[i].vX=vX;movers[i].vY=vY;movers[i].x=nextX;movers[i].y=nextY;} }void updateWithInput() {MOUSEMSG m;//定義鼠標(biāo)消息while(MouseHit())//檢測(cè)當(dāng)前是否有鼠標(biāo)消息{m=GetMouseMsg();//如果鼠標(biāo)移動(dòng),更新當(dāng)前鼠標(biāo)坐標(biāo)變量if(m.uMsg==WM_MOUSEMOVE)//如果鼠標(biāo)移動(dòng),更新當(dāng)前鼠標(biāo)坐標(biāo)變量{mouseX=m.x;mouseY=m.y;}else if(m.uMsg==WM_LBUTTONDOWN)//鼠標(biāo)左鍵按下isMouseDown=1;else if(m.uMsg==WM_LBUTTONUP)//鼠標(biāo)左鍵抬起isMouseDown=0;} }void gameover() {EndBatchDraw();closegraph(); }int main() {startup();//數(shù)據(jù)的初始化while(1){show();//顯示畫面updateWithoutInput();//與用戶輸入無(wú)關(guān)的更新updateWithInput();//與用戶輸入有關(guān)的更新}gameover();//游戲結(jié)束,進(jìn)行后續(xù)處理return 0; }效果圖如下:
七、鼠標(biāo)的擾動(dòng)力
實(shí)現(xiàn)鼠標(biāo)移動(dòng)時(shí)對(duì)粒子的擾動(dòng)力,類似于在水面上拿樹(shù)枝攪動(dòng),攪動(dòng)的越快擾動(dòng)越大。代碼如下:
#include<stdio.h> #include<string.h> #include<graphics.h> #include<time.h> #include<math.h>#define WIDTH 1024 //屏幕的寬 #define HEIGHT 768 //屏幕的高 #define NUM_MOVERS 800 //小球的數(shù)量 #define FRICTION 0.96f//摩檫力、阻尼系數(shù)//定義小球結(jié)構(gòu) struct Mover {COLORREF color;//顏色float x,y;//坐標(biāo)float vX,vY;//速度float radius;//半徑 };//定義全局變量 struct Mover movers[NUM_MOVERS];//小球數(shù)組 int mouseX,mouseY;//當(dāng)前鼠標(biāo)坐標(biāo) int prevMouseX,prevMouseY;//上次鼠標(biāo)坐標(biāo) int mouseVX,mouseVY;//鼠標(biāo)的速度 int isMouseDown;//鼠標(biāo)左鍵是否按下 void startup() {//設(shè)置隨機(jī)種子srand((unsigned int)time(NULL));//初始化小球數(shù)組for(int i=0;i<NUM_MOVERS;i++){movers[i].color=RGB(rand()%256,rand()%256,rand()%256);movers[i].x=rand()%WIDTH;movers[i].y=rand()%HEIGHT;movers[i].vX=float(cos(float(i)))*(rand()%34);movers[i].vY=float(sin(float(i)))*(rand()%34);movers[i].radius=(rand()%34)/15.0;}//初始化當(dāng)前鼠標(biāo)在畫布中心mouseX=WIDTH/2;mouseY=HEIGHT/2;isMouseDown=0;//初始鼠標(biāo)未按下initgraph(WIDTH,HEIGHT);BeginBatchDraw(); }void show() {int i;clearrectangle(0,0,WIDTH-1,HEIGHT-1);//清除畫面中的全部矩形區(qū)域for(i=0;i<NUM_MOVERS;i++){//畫小球setcolor(movers[i].color);setfillstyle(movers[i].color);fillcircle(int(movers[i].x+0.5),int(movers[i].y+0.5),int(movers[i].radius+0.5));}FlushBatchDraw();Sleep(2); }void updateWithoutInput() {int i;float x,y,vX,vY;float nextX,nextY;float avgVX,avgVY,avgV,sc;//阻尼float toDist=WIDTH*0.36;//吸引距離,若小球與鼠標(biāo)的距離在此范圍內(nèi)則會(huì)受向內(nèi)的引力float blowDist=WIDTH*0.25;//擊打距離,小球與鼠標(biāo)的距離在次范圍內(nèi)會(huì)受到向外的斥力float stirDist=WIDTH*0.125;//擾動(dòng)距離,小球距離鼠標(biāo)在此范圍內(nèi)會(huì)受到鼠標(biāo)的擾動(dòng)float d;//當(dāng)前小球和鼠標(biāo)位置的距離float dX,dY;//計(jì)算小球當(dāng)前位置的差 //前后兩次運(yùn)行間鼠標(biāo)移動(dòng)的距離,即鼠標(biāo)的速度mouseVX=mouseX-prevMouseX;mouseVY=mouseY-prevMouseY;//為記錄這次鼠標(biāo)的坐標(biāo),更新上次鼠標(biāo)坐標(biāo)變量prevMouseX=mouseX;prevMouseY=mouseY;for(i=0;i<NUM_MOVERS;i++){x = movers[i].x;//當(dāng)前小球的坐標(biāo)y = movers[i].y;vX = movers[i].vX;//當(dāng)前小球的速度vY = movers[i].vY;dX=x-mouseX;//計(jì)算小球當(dāng)前位置的差 dY=y-mouseY;d=sqrt(dX*dX+dY*dY);//當(dāng)前小球和鼠標(biāo)位置的距離//下面將dX,dY歸一化,僅反映方向,和距離無(wú)關(guān)if(d!=0){dX=dX/d;dY=dY/d;}else{dX=0;dY=0;}//小球距離鼠標(biāo)<toDist,再次范圍內(nèi)小球會(huì)受到鼠標(biāo)的吸引if(d<toDist){//吸引力引起的加速度幅度,小球距離鼠標(biāo)越近引起的加速度越大//但吸引力的值明顯比上面斥力的值小很多float toAcc=(1-(d/toDist))*WIDTH*0.0014f;//由dX,dY歸一化方向信息,加速度幅度值為toAcc,得到新的小球高度vX=vX-dX*toAcc;vY=vY-dY*toAcc;}//當(dāng)鼠標(biāo)左鍵按下,并且小球距離鼠標(biāo)<blowDist(在擊打范圍內(nèi))時(shí)會(huì)受到向外的斥力if(isMouseDown&&d<blowDist){//擊打力引起的加速度幅度,這個(gè)公式表示小球距離鼠標(biāo)越近擊打斥力引起的加速度越大float blowAcc=(1-(d/blowDist))*10;//由上面得到的dX,dY歸一化方向信息,上面的加速度幅度值為blowAcc,得到新的小球速度//float(rand())/RAND_MAX產(chǎn)生0~1的隨機(jī)數(shù)//0.5f-float(rand())/RAND_MAX產(chǎn)生-0.5~0.5的隨機(jī)數(shù),加入一些擾動(dòng)vX=vX+dX*blowAcc+0.5f-float(rand())/RAND_MAX;vY=vY+dY*blowAcc+0.5f-float(rand())/RAND_MAX;}//若小球距離鼠標(biāo)<stirDist,在此范圍內(nèi)小球會(huì)受到鼠標(biāo)的擾動(dòng)if(d<stirDist){//擾動(dòng)力引起的加速度幅度,小球距離鼠標(biāo)越近引起的加速度越大,擾動(dòng)力的值更小float mAcc=(1-(d/stirDist))*WIDTH*0.00026f;//鼠標(biāo)速度越大,引起的擾動(dòng)力越大vX=vX+mouseVX*mAcc;vY=vY+mouseVY*mAcc;}//小球運(yùn)動(dòng)有一個(gè)阻尼(摩擦力),速度逐漸減小vX=vX*FRICTION;vY=vY*FRICTION;//速度的絕對(duì)值avgVX=abs(vX);avgVY=abs(vY);//兩個(gè)方向速度的平均avgV=(avgVX+avgVY)*0.5f;//因?yàn)橛猩厦孀枘岬淖饔?#xff0c;如果速度過(guò)小,乘以一個(gè)0~3的隨機(jī)數(shù),//會(huì)以比較大的概率讓速度變大if(avgVX<0.1)vX=vX*float(rand())/RAND_MAX*3;if(avgVY<0.1)vY=vY*float(rand())/RAND_MAX*3;//小球的半徑在0.4~3.5之間,速度越大,半徑越大sc=avgV*0.45f;sc=max(min(sc,3.5f),0.4f);movers[i].radius=sc;//根據(jù)“位置+速度”更新小球的坐標(biāo)nextX=x +vX;nextY=y+vY;//如果小球超過(guò)上、下、左、右4個(gè)邊界,將位置設(shè)為邊界處,速度反向if(nextX>WIDTH){nextX=WIDTH;vX=-1*vX;}else if(nextX<0){nextX=0;vX=-1*vX;}if(nextY>HEIGHT){nextY=HEIGHT;vY=-1*vY;}else if(nextY<0){nextY=0;vY=-1*vY;}//更新小球位置movers[i].vX=vX;movers[i].vY=vY;movers[i].x=nextX;movers[i].y=nextY;} }void updateWithInput() {MOUSEMSG m;//定義鼠標(biāo)消息while(MouseHit())//檢測(cè)當(dāng)前是否有鼠標(biāo)消息{m=GetMouseMsg();//如果鼠標(biāo)移動(dòng),更新當(dāng)前鼠標(biāo)坐標(biāo)變量if(m.uMsg==WM_MOUSEMOVE)//如果鼠標(biāo)移動(dòng),更新當(dāng)前鼠標(biāo)坐標(biāo)變量{mouseX=m.x;mouseY=m.y;}else if(m.uMsg==WM_LBUTTONDOWN)//鼠標(biāo)左鍵按下isMouseDown=1;else if(m.uMsg==WM_LBUTTONUP)//鼠標(biāo)左鍵抬起isMouseDown=0;} }void gameover() {EndBatchDraw();closegraph(); }int main() {startup();//數(shù)據(jù)的初始化while(1){show();//顯示畫面updateWithoutInput();//與用戶輸入無(wú)關(guān)的更新updateWithInput();//與用戶輸入有關(guān)的更新}gameover();//游戲結(jié)束,進(jìn)行后續(xù)處理return 0; }效果圖如下:
總結(jié)
以上是生活随笔為你收集整理的项目: 互动粒子仿真的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 如何看你的信息有没有泄露
- 下一篇: 【学习Python】的网站