本文由鄒啟文授權網易雲社群發布。
郵箱大師pc版中,設計師提出了乙個很妙的想法: 發信時,出現乙個飛機,從寫信**飛往進度目的地。
附加要求:
1,飛行曲線,飛機先加速,然後減速抵達終點
2,飛行途中,需要轉換飛機朝向
3,飛行途中,飛機漸漸變小
體驗:網易郵箱大師電腦版
實現方法:
飛行曲線
我們選擇了二次貝塞爾曲線,原因是簡單,可計算。
數學公式:b(t) = (1-t)^2 p0 + 2 t (1-t) p1 + t^2 *p2, t=[0,1]
(**於網路,此處是為了講解清楚)
已知起飛點p0,終點p2,起飛角度(或斜率,切線p0p1),降落角度(或斜率,切線p1p2),求p1
將起飛角度轉換(k=tan(θ))成斜率k1,降落角度轉成斜率k2,根據斜率公式y=k*x+b可得
p0.y = k1 * p0.x + b1;
p1.y = k1 * p1.x + b1;
p2.y = k2 * p2.x + b2;
p1.y = k2 * p1.x + b2;
至此,便可求得p1座標。(可調整角度(或k1,k2)以滿足實際要求)
曲線雖然推導出來,但是,飛機先加速然後減速,如何實現呢?
注意觀察,公式中t的取值範圍是0~1,我們可以讓飛機在前面小部分時間走過大部分距離,後面
大部分時間走過小部分距離來做到。
為了靈活調整,以及總時間固定的情況下,我們選擇了一種簡單的方法,將時間分片,人為的構造
出一段前面加速後面減速的時間曲線。
示例:
const int kpiece = ;
定時器設定為10ms,每隔10ms,計算一次t=kpiece(0~i) / kpiece(0~n) * t;
kpiece(0~i)為前i項和,kpiece(0~n)為總和,t為固定的總時間
飛機朝向
飛機的頭要隨著曲線改變朝向。很顯然,這個朝向就是曲線的切線方向。
求切線,正確的方式是求導。
在這裡,我們選擇了一種簡單的方法:
記住當前點和上一點,然後計算2點的斜率,再轉換成角度。
飛機大小
飛機大小變化沒有嚴格要求,可採取線性變化,在總時間t內從1.0到0.25(根據素材大小決定),恰好做到與曲線同時變化結束。
特別注意
i、起飛角度轉換成斜率,在計算機世界,其座標系與數學中的座標系不一致,x軸一致,而y軸相反,所以角度可能是負數(比如起始時往左飛行)
ii、飛機朝向,斜率轉換成角度時,從a到b,b相對於a的位置可在4個象限,所以角度可能存在負角度,與此同時,素材中飛機也有個角度,那麼繪製時,注意矯正角度
iii、飛機降落時角度可能不正確(如從上方降落)。實際應用時,由於飛機變小且速度較快,而且降落時調整了角度,所以此問題不明顯。如要保證飛機降落角度一定不變,可以考慮三次貝塞爾曲線
gdiplus繪製飛機
gdiplus::graphics g(dc);
gdiplus::pointf center(cx / 2, cy / 2); // cx、cy為素材寬度和高度
g.translatetransform(center.x, center.y); // 轉換座標系
g.rotatetransform(angle_); // 旋轉角度
g.setinterpolationmode(gdiplus::interpolationmodehighqualitybilinear);
g.scaletransform(scale_, scale_); // 縮放
g.translatetransform(-center.x, -center.y);
g.drawimage(plane_.get(), 0, 0); // 繪製
免費領取驗證碼、內容安全、簡訊傳送、直播點播體驗包及雲伺服器等** 貝塞爾曲線
1.概述 貝塞爾曲線 b zier curve 又稱 貝茲曲線或貝濟埃曲線,是應用於二維圖形應用程式的數學曲線。一般的向量圖形 軟體通過它來精確畫出曲線,貝茲曲線由 線段與節點組成,節點是可拖動的支點,線段像可伸縮的皮筋,我們在繪圖工具上看到的鋼筆工具就是來做這種向量曲線的。貝塞爾曲線是計算機圖形學...
貝塞爾曲線
由於工作需要,最近在研究乙個類似qq訊息劃掉的效果 很多強迫症患者童鞋對這個簡直是愛不釋手,當然這個也包括我自己 貝塞爾曲線就是這樣的一條曲線,它是依據四個位置任意的點座標繪製出的一條 光滑曲線 在歷史上,研究貝塞爾曲線的人最初是按照已知曲線 引數方程 來確定四個點的思路設計出這種向量曲線繪製法。貝...
貝塞爾曲線
貝塞爾曲線在android中運用廣泛,可以用來繪製各類複雜曲線,因為貝塞爾曲線只需要指定控制點,就能繪製出特定的曲線。其次是做點和點的平滑過渡。為什麼可以做到如上兩點,看下面的講解 首先來說,貝塞爾曲線有階的概念,這個階可以理解為控制點,一階的控制點只有兩個。如上是一階的方程,其中t取值為0到1,可...