PS:自己翻译的,转载请著明出处
在贝塞尔曲线上通过Cubed2D来移动个精灵
几乎所有的XNA初学者教程开始了同样的事情,使一个精灵沿着屏幕移动。我将会告诉你如何去做相同的事情,但是,是在曲线上,非常典型的例子是贝塞尔曲线。为某些游戏弯曲的行为它是一个非常有趣的事情。你可以设置一个物理引擎去解决,在你游戏里的所有移动(相对复杂的事情),但是某些游戏是不必要的。例如,如果你使你的飞机向一边旋转然后发射导弹,你可以很容易使你的导弹离开你的飞机,曲线向后然后速度向前。有点象这样。。。
我看见我的疯狂的艺术技能,使你用这个方法生成这个行为非常真实!但是首先,让我们仔细的看下这个曲线。什么是贝塞尔曲线?它是一个叫贝塞尔的法国人空想出来的曲线函数。如果你给它一个变量T(它是在0到1之间的),它将返回一个曲线的位置。所以每一祯,我们传递一个更高的T值到这个函数中,我们得到新的导弹位置。为什么它的曲线会向后?如果你仔细的看你可以想象3个控制点在这个曲线上,这3个点控制它的外观。我们有起始点和终点。另外一个点是比屏幕上的终点低并且比起始点更靠左,他拉着曲线朝着它(不是通过它)。如果我们移动中间控制点左右,我们得到一个不同的曲线行为。现在基础已经了解,让我们到编码上吧!
就象大多数事物的数学一样,它是样例最好的开始。所以我们将开始贝塞尔的最低的顺序,一个条直线曲线(它只有2个控制点)。
归根到底是很好的一行代码。
1 public static Vector2 Linear(Vector2 pos1, Vector2 pos2, float t)
2 {
3 return pos1 = pos1 + (pos2 - pos1) * t;
4 }
如果你把它用一个静态类捆扎并且设置一个精灵去使用它输出,现在你可以测试它。记住去提供给他pos1(开始点)和pos2(结束点)。关于XNA的向量2类的好的事情是你可以操作在他们上不用pulling out their individual floats并且重新构造它们。这将让我们计算X和Y轴一起。记住去使用t象一个时间变量。如果一切顺利,你可以得到一个移动就象如下所示。2 {
3 return pos1 = pos1 + (pos2 - pos1) * t;
4 }
晔,不错...一条直线。让我们看看贝塞尔曲线的下个order,二次方曲线。它给我们第三个控制点,因此是曲线!
它看起来很复杂,它实际上是做什么的呢?
如果你仔细看这个曲线的标图,你可以看见我们实际有两个直线性贝塞尔曲线。一个从p0到p1,并且一个从p1到p2.这个功能合并结果成一条曲线。
1 //returns the position on a quadratic bezier curve
2 public static Vector2 Quad(Vector2 pos1, Vector2 pos2, Vector2 pos3, float t)
3 {
4 return (1 - t) * (1 - t) * pos1 + 2 * t * (1 - t) * pos2 + t * t * pos3;
5 }
如果你把它应用在你的精灵的移动上,现在你应该得到一个曲线路径!它仍然看起来odd,这个精灵不能旋转因为它沿着这个路径走,幸运的是数学可以sort that out too.2 public static Vector2 Quad(Vector2 pos1, Vector2 pos2, Vector2 pos3, float t)
3 {
4 return (1 - t) * (1 - t) * pos1 + 2 * t * (1 - t) * pos2 + t * t * pos3;
5 }
正如你看见的,来自自角三角形的红色的线。我们可以用两边的长度,d1和d2到一个arctan函数调用去得到q1点上的角度r。我们可以使用这个角度通过它自己旋转一个精灵,但是它看起来并不好,因为它太远离弧线它本身。理想上我们要其次的r.幸运的是,我们可以得到它!我们知道在一个三角形里所有角度总共是180度(或者pi弧度)。我们同样知道45度是pi/4弧度,在弧度上我们已经有了r,所以如果我们接收pi-((pi/4)-r)我们为r得到我们的新值,通过这个数值来旋转!
1 private void CalcRotation(Vector2 pos1, Vector2 pos2, Vector2 pos3, Vector2 currentPos)
2 {
3 Vector2 q1 = Bezier.Linear(pos1, pos2,t);
4 Vector2 q2 = Bezier.Linear(pos2, pos3,t);
5 //make sure you run this after you update the position on the curve
6 float d1 = Vector2.Distance(q1, new Vector2(currentPos.X, pos1.Y));
7 float d2 = Vector2.Distance(q2, new Vector2(currentPos.X, pos1.Y));
8 r = (float)Math.Atan2(d1, d2);
9 r = -((float)Math.PI - ((float)Math.PI / 4) - r);
10 }
所有的都这么简单!2 {
3 Vector2 q1 = Bezier.Linear(pos1, pos2,t);
4 Vector2 q2 = Bezier.Linear(pos2, pos3,t);
5 //make sure you run this after you update the position on the curve
6 float d1 = Vector2.Distance(q1, new Vector2(currentPos.X, pos1.Y));
7 float d2 = Vector2.Distance(q2, new Vector2(currentPos.X, pos1.Y));
8 r = (float)Math.Atan2(d1, d2);
9 r = -((float)Math.PI - ((float)Math.PI / 4) - r);
10 }
源代码:http://www.ziggyware.com/readarticle.php?article_id=92
(完)