as3绘制抛物线
一般做页游的过程中,特效的释放可能是不是固定位置的播放,是需要进行“运动的”(其实就是移动特效这个影响剪辑)。举个例子:步兵射箭,不确定箭发射的 方向,事先也不确定发射点和动画的结束点位置,只知道攻击方与被攻击方的位置。一般特效是没有方向性的,特效只是一个在特定位置播放效果的影响剪辑而已, 表现上要突出的是从攻击方到被攻击方的一段运动轨迹,之后播放被攻击方的受伤或是防御动作。
从上面的描述中可以确定二点信息:
1、曲线开始的起点和结束的终点位置,可根据攻击方、被攻击方确定下来;
2、特效播放完毕后,需要知道它的结束时刻,以便回调函数里响应被攻击方的动作;
特效的播放,建议是采用监听Event.ENTER_FRAME来进行响应,不要根据特效播放的时长来处理。
以 抛物线运动为例,根据公式 y = a * x * x + b * x + c;已知曲线公通过两个点,起始点--攻击方的位置,结束点--被攻击方的位置,还要知道一个中点,就可以确定这个公式中的参数a、b、c的值了,选取中 间点为例。它的位置(Point)为x:(startPoint.x + (startPointx + endPoint.x) / 2),而y则等于抛物线的“幅度”。
现在就三个等式:
y1 = a * x1 * x1 + b * x1 + c;
y2 = a * x2 * x2 + b * x2 + c;
y3 = a * x3 * x3 + b * x3 + c;
解这三个方程,可得到a、b、c分别为:
b = ((y1 - y3) * (x1 * x1 - x2 * x2) - (y1 - y2) * (x1 * x1 - x3 * x3)) / ((x1 - x3) * (x1 * x1 - x2 * x2) - (x1 - x2) * (x1 * x1 - x3 * x3));
a = ((y1 - y2) - b * (x1 - x2)) / (x1 * x1 - x2 * x2);
c = y1 - a * x1 * x1 - b * x1;
其中(x1, y1)、(x2, y2)、(x3, y3)为已知的点--起始点、结束点、顶点。最终的效果如下图所示:
示例代码:
1: package
2: { 3: import flash.geom.Point;
4: /**
5: * ...
6: * @author Meteoric
7: */
8: public class Parabola
9: { 10: private var startPt:Point;
11: private var endPt:Point;
12: private var vertexPt:Point;
13: 14: private var a:Number;
15: private var b:Number;
16: private var c:Number;
17: 18: public function Parabola(pt1:Point, pt2:Point)
19: { 20: startPt = pt1; 21: endPt = pt2; 22: 23: parse(); 24: } 25: 26: public function parse(waveHeight:Number=140):void
27: { 28: vertexPt = new Point(startPt.x + (endPt.x - startPt.x) / 2, endPt.y - waveHeight);
29: 30: var x1:Number = startPt.x; 31: var x2:Number = endPt.x; 32: var x3:Number = vertexPt.x; 33: 34: var y1:Number = startPt.y; 35: var y2:Number = endPt.y; 36: var y3:Number = vertexPt.y; 37: 38: b = ((y1 - y3) * (x1 * x1 - x2 * x2) - (y1 - y2) * (x1 * x1 - x3 * x3)) / ((x1 - x3) * (x1 * x1 - x2 * x2) - (x1 - x2) * (x1 * x1 - x3 * x3)); 39: a = ((y1 - y2) - b * (x1 - x2)) / (x1 * x1 - x2 * x2); 40: c = y1 - a * x1 * x1 - b * x1; 41: 42: trace(a, b, c); 43: } 44: 45: public function getY(posX:Number):Number
46: { 47: var posY:Number = a * posX * posX + b * posX + c; 48: 49: return posY;
50: } 51: 52: } 53: 54: }//------------第二部分
上一篇文章,只是简单的求出了抛物线的坐标,而且也不够灵活。如果只是单纯的画线,使用as3自带的curveTo(二次贝塞尔曲线)就已经足够了。
二次贝塞尔曲线演示动画 t in [0, 1] (图片来源于wiki贝塞尔曲线>>)
![]()
下面的例子,根据鼠标的位置,绘制经过指定起始点、结束点和鼠标位置的曲线。
Code:
1: package
2: { 3: import flash.display.Sprite;
4: import flash.events.Event;
5: 6: /**
7: * ...
8: * @author Meteoric
9: */
10: public class DrawCurveDemo extends Sprite
11: { 12: private var x0:Number = 100;
13: private var y0:Number = 400;
14: private var x1:Number;
15: private var y1:Number;
16: private var x2:Number = 500;
17: private var y2:Number = 400;
18: 19: public function DrawCurveDemo()
20: { 21: initView(); 22: } 23: 24: private function initView():void
25: { 26: addEventListener(Event.ENTER_FRAME, onEnterFrameHandler); 27: 28: onEnterFrameHandler(); 29: } 30: 31: private function onEnterFrameHandler(e:Event=null):void
32: { 33: x1 = mouseX; 34: y1 = mouseY; 35: 36: graphics.clear(); 37: graphics.lineStyle(2, 0x3399cc); 38: graphics.moveTo(x0, y0); 39: graphics.curveTo(x1, y1, x2, y2); 40: } 41: 42: } 43: 44: }
先定义一个名为Arrow.as,它用于在舞台上画一个红色的“箭头”
1: package
2: { 3: import flash.display.Sprite;
4: 5: /**
6: * ...
7: * @author Meteoric
8: */
9: public class Arrow extends Sprite
10: { 11: 12: public function Arrow()
13: { 14: initView(); 15: } 16: 17: private function initView():void
18: { 19: graphics.clear(); 20: graphics.lineStyle(1, 0xff0000); 21: graphics.moveTo(-100, -5); 22: graphics.lineTo(-20, -5); 23: graphics.lineTo(-20, -20); 24: graphics.lineTo(0, 0); 25: graphics.lineTo(-20, 20); 26: graphics.lineTo(-20, 5); 27: graphics.lineTo(-100, 5); 28: graphics.lineTo(-100, -5); 29: } 30: 31: } 32: 33: } 然后定义一个ArrowTest.as用于测试效果:
1: package
2: { 3: import flash.display.Sprite;
4: import flash.utils.setTimeout;
5: import gs.TweenMax;
6: /**
7: * ...
8: * @author Meteoric
9: */
10: public class ArrowTest extends Sprite
11: { 12: 13: public function ArrowTest()
14: { 15: initView(); 16: } 17: 18: private var arrow:Arrow;
19: 20: private function initView():void
21: { 22: if (arrow == null)
23: { 24: arrow = new Arrow();
25: addChild(arrow); 26: } 27: arrow.x = 100; 28: arrow.y = 300; 29: 30: graphics.clear(); 31: graphics.lineStyle(1, 0x000000); 32: graphics.moveTo(arrow.x, arrow.y); 33: 34: TweenMax.to(arrow, 3, {x:600, y:400, bezierThrough:[{x:300, y:100}], orientToBezier:true, onUpdate:onUpdateHandler, onComplete:onCompleteHandler}); 35: } 36: 37: private function onUpdateHandler():void
38: { 39: graphics.lineTo(arrow.x, arrow.y); 40: } 41: 42: private function onCompleteHandler():void
43: { 44: setTimeout(initView, 2 * 1000); 45: } 46: 47: } 48: 49: }
浙公网安备 33010602011771号