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