定点定时抛物效果实现
定點定時拋物效果實現
要實現物體的移動效果,可以通過公式簡單得出。我們定義一個概念叫速度,在游戲步進的一段時間里,會改變自身的位置。假設由A點移動到B點,則為:
其中P為物體當前的位置,一開始為A點。當隨著時間流逝,P的值是在更新的。這意味著我在說:“我會一步一步的前往目的的,最終就會按預期的時間達到B點。但若是速度發生了變化,則可能到不了B點,或者沒有按期望的時間到達”,所以要其中的V是一個定值。假設我們期望t秒到達B點,那么很簡單得出V值:
不過,我們也可以換一個思路來計算物體的位置,不使用速度的概念。若是t秒從A移動到B,那么0.5t時間則走了一半路程,所以物體的位置是出發點位置加上已走路程。公式表示如下:
其中代表從A點出發已花費的時間,當等于時候,則說明進行了一半的路程,即是,其中B-A即是AB之間的路程。簡單驗證一下沒有問題,很好理解。
這種做法的一個好處是,即便AB點的位置發生變化,最終物體還是會按時移動到B點,雖然路徑是不是直線了,但總比打歪了好。這正好符合了我們標題所說的定點定時,代碼和效果如下:
//線性位置變換 Vector2 pos = p[0] + (p[1] - p[0]) * (_tCount / _tMax); 丟咖啡接下來,我們就來實現更高級一點的拋物線軌跡。但是拋物線方程有很多種,又如何和游戲的步進時間關聯起來呢??首先我們的起點與終點已經確定了,然后確定了運行需要花費的時間。我們隱約可以還感覺到需要確定的是這個拋物線的“彎度”,但是“彎度”不太好描述,所以我們再確定一個P點,或者Q點,來決定拋物線的方程。
y軸向下?確定P點的情況
首先變換B點坐標系到A為原點的坐標系:
然后假設P點在AB的x距離的m倍處(P點可以隨便調整,從而影響整個曲線),所以P點坐標為
,其中y軸為0,x值是一個已知量。我們定義Px為P點的x坐標,然后A點已經成為原點所以:
然后寫下拋物線方程:,代入原點得:,再代入P點得:
化簡寫成b的等式:
再將B點代入拋物線方程,再替換b得:
所以a已經求出為:
所以b為:
眾所周知,拋物線的x軸軌跡是線性的,所以x坐標和時間的關系如下:
那么通過a、b、x三個變量即可表示y值,再定義最終化簡為:
這個時候我們就不再需要求ab的值了,直接使用最終的公式計算結果:
觀察結果我們可以發現kt與m的范圍實際都在0到1,最后的式子也意外的簡潔。最后效果如下:
定點打擊代碼如下,最后我將不必要的計算給注釋掉了:
//將B轉換到A坐標系 Vector2 B = p->_pos[1] - p->_pos[0]; //AB x軸距離 //float d = B.a; //x方程 float k_t = GetKSafe(p->_tCount, p->_tMax);//有警告的返回,防止除數為0 float x = k_t * B.a; //y = a * x^2 + b * x + c ,由于A成為了原點,所以c等于0 //然后假設與x相交的點為p,則px是我們估計的一個常數(小于d) constexpr float m = 0.75f; //float p_x = m * d; //所以 0 = a * p_x^2 + b * p_x,化簡得 // b = -a * p_x; //然后方程又過點B,所以By = a * Bx^2 + b * Bx,再消去b化簡得 //float a = B.b / (B.a * B.a - p_x * B.a); //然后求得b值 //float b = -a * p_x; //最后y值為 //float y = a * x * x + b * x; //float y = k_t * (k_t - m) * B.b / (1 - m); float y = k_t * B.b * (k_t - m) / (1 - m);//最后轉換回原坐標系 Vector2 pos = Vector2(x, y) + p->_pos[0];??確定Q點的情況
以Q點確定拋物線的公式我還沒有推導,太晚了,等下次再試試,說不定是差不多的公式~
10-15更新:
其實Q的x值是P點的一半,所以其實是一樣的,只不過m變小了一倍。
總結
以上是生活随笔為你收集整理的定点定时抛物效果实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 光速AStar寻路算法(C++)
- 下一篇: 【pnglib】解析png格式的图像