zoukankan      html  css  js  c++  java
  • 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贝塞尔曲线>>)

    二次贝塞尔曲线演示动画,t in [0,1]

    下面的例子,根据鼠标的位置,绘制经过指定起始点、结束点和鼠标位置的曲线。

    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: }
     
    上面仅仅支持线条的绘制,如果是一个影片剪辑想要移动,则会比较麻烦。好在AS3的类库TweenMax已经完全支持了。
    image
     
    参考文档说明,实现如下的示例效果:

    先定义一个名为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: }
     
  • 相关阅读:
    ASP.NET在禁用视图状态的情况下仍然使用ViewState对象【转】
    Atcoder Regular Contest 061 D Card Game for Three(组合数学)
    Solution 「CERC 2016」「洛谷 P3684」机棚障碍
    Solution 「CF 599E」Sandy and Nuts
    Solution 「洛谷 P6021」洪水
    Solution 「ARC 058C」「AT 1975」Iroha and Haiku
    Solution 「POI 2011」「洛谷 P3527」METMeteors
    Solution 「CF 1023F」Mobile Phone Network
    Solution 「SP 6779」GSS7
    Solution 「LOCAL」大括号树
  • 原文地址:https://www.cnblogs.com/bluesea-flash/p/3460935.html
Copyright © 2011-2022 走看看