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: }
     
  • 相关阅读:
    Iis发布网站
    call和apply的用法和区别
    用脚手架搭建vue项目
    记录一键shell脚本清理MySQL碎片文件的脚本
    Tiny File Manager – 轻便PHP文件管理工具 WEB文件可视化管理文件
    Pure Highlightjs – WordPress站长必装轻便代码高亮插件
    6个实用方法有效确保WordPress网站数据安全
    WPOSS – WordPress阿里云对象存储OSS插件 网站图片分离加速
    WordPress安装WPCOS插件分离图片至腾讯云对象存储加速网站
    Autoptimize – WordPress压缩代码加速网站访问插件设置方法
  • 原文地址:https://www.cnblogs.com/bluesea-flash/p/3460935.html
Copyright © 2011-2022 走看看