#pragma once #include <math.h> #include "hge.h" class CBall { public: CBall(); CBall(float _x,float _y,float _speedX ,float _speedY,float _radius ,DWORD _color,float _density = 1.0f); ~CBall(){}; public: bool IsCollision(CBall *ball,float dt); //碰撞檢測 void CollisionWith(CBall *ball); //彈性正碰 void CollisionWith2(CBall *ball); //彈性斜碰 void SwapColor(CBall *ball); //好玩點,加個交換顏色 void MoveNext(float dt,float _width,float _height); //由於程序不大,方便起見所有就都public了 public: float x; //x軸坐標 float y; //y軸坐標 float speed_x; //x軸方向速度 float speed_y; //x軸方向速度 float radius; //球體半徑 float density; //密度 float weight; //質量 DWORD color; //混合顏色 };從Ball的類成員定義中可以看出來,球體的大概屬性基本包括全面了,不過多了個Color這個屬性是用來設置球體顏色的,因為圖片素材是純白實心圓,在使用color顏色進行頂點著色時候可直接設置獲得該顏色的圓。 (1)構造方法CBall(float _x,float _y,float ... ,float _density .0f);對成員變量初始化,需要注意,密度默認是1.0f,而質量通過體積和密度的計算求得。【球體質量 m=ρ*v , v = 4/3*π*r^3】。 (2)碰撞檢測,返回當前對象時候與參數ball發生碰撞,dt是一幀的時間。
bool CBall::IsCollision(CBall *ball,float dt) { //計算的是下一刻的位置,以免發生粘連 float disX = (this->x+this->speed_x*dt)-(ball->x+ball->speed_x*dt); float disY = (this->y+this->speed_y*dt)-(ball->y+ball->speed_y*dt); float dis = sqrt(disX*disX+disY*disY); //判斷下一刻是否 發生碰撞 if(dis < this->radius+ball->radius) return true; return false; }(3)彈性正碰 void CBallCollisionWith(CBall ball)根據動能定理和動量守恆定律得出公式 //彈性正碰撞公式 //v1' = [ (m1-m2)*v1 + 2*m2*v2 ] / (m1+m2) 碰撞後,兩小球的速度,方向,會發生改變。 ,文章的主角,由於計算比較復雜所以需要用到向量(Vector)。
void CBall::CollisionWith2(CBall *ball) { //參考資料: //http://www.cnblogs.com/kenkofox/archive/2011/09/06/2168944.html //http://tina0152.blog.163.com/blog/static/119447958200910229109326/ //球心點 float x1 = this->x ; float y1 = this->y ; float x2 = ball->x ; float y2 = ball->y ; //碰撞處切平面向量t,及其法向量s hgeVector s(x2-x1, y2-y1); s.Normalize();//標准化矢量 hgeVector t(x2-x1, y2-y1); t.Rotate(3.1415926f/2); t.Normalize(); //速度向量 hgeVector v1(this->speed_x,this->speed_y); hgeVector v2(ball->speed_x,ball->speed_y); //先算v1(v1x, v1y)在s和t軸的投影值,分別設為v1s和v1t //再算v2(v2x, v2y)在s和t軸的投影值,分別設為v2s和v2t: float v1s = v1.Dot(&s); float v1t = v1.Dot(&t); float v2s = v2.Dot(&s); float v2t = v2.Dot(&t); //轉換後於s向量上的彈性正碰撞。質量不等 //彈性正碰撞公式 //v1' = [ (m1-m2)*v1 + 2*m2*v2 ] / (m1+m2) //v2' = [ (m2-m1)*v2 + 2*m1*v1 ] / (m1+m2) float m1 = this->weight; float m2 = ball->weight; float temp_v1s = ((m1-m2)*v1s + 2*m2*v2s )/ (m1+m2); v2s = ((m2-m1)*v2s + 2*m1*v1s )/ (m1+m2); v1s = temp_v1s; //首先求出v1t和v2t在t軸的向量v1t'和v2t'(將數值變為向量) //再求出v1s'和v2s'在s軸的向量v1s'和v2s'(將數值變為向量) hgeVector v1tVector = t*v1t; hgeVector v1sVector = s*v1s; hgeVector v2tVector = t*v2t; hgeVector v2sVector = s*v2s; //新速度矢量 hgeVector v1_new = v1tVector+v1sVector; hgeVector v2_new = v2tVector+v2sVector; //劃分成x,y方向分量速度 this->speed_x = v1_new.x; this->speed_y = v1_new.y; ball->speed_x = v2_new.x; ball->speed_y = v2_new.y; }(5)交換顏色,發生碰撞後的兩個小球進行顏色交換,純屬娛樂。 void CBallSwapColor(CBall ball) (6)小球移動,參數 _width,_height分別是窗口的寬高,因為這個方法內包含邊界碰撞的檢測和反彈。
void CBall::MoveNext(float dt,float _width,float _height) { float moveX = speed_x*dt; float moveY = speed_y*dt; //x方向邊界 if (x+moveX<radius||x+moveX>_width-radius) speed_x = -speed_x; //Y方向邊界 if(y+moveY<radius||y+moveY>_height-radius) speed_y = -speed_y; x+=speed_x*dt; y+=speed_y*dt; }
主函數,使用,看源文件吧這裡不詳細說了。 (HGE是一個小型的2D游戲引擎,基於DirectX8,相關學習資料下載:http://pan.baidu.com/s/1dDtdd2h)