发布时间:2019-09-14 09:45:54编辑:auto阅读(1514)
贝塞尔曲线被广泛用于塔防类的游戏,当然一些特殊的缓动效果有些 也用 到这个 , 目前 这个没必要我们担心 , TweenMax 为我们提供了这些功能.
package com.ainy.benz { import flash.geom.Point; public class Bezier{ // ===================================== 属性 // 对外变量 private var p0:Point; // 起点 private var p1:Point; // 控制点 private var p2:Point; // 终点 private var step:uint; // 分割份数 // 辅助变量 private var ax:int; private var ay:int; private var bx:int; private var by:int; private var A:Number; private var B:Number; private var C:Number; private var total_length:Number; // 长度 private static var $instance : Bezier; public static function instance() : Bezier{ if(null == $instance){ $instance = new Bezier(); } return $instance; } public function Bezier(){ if($instance != null ){ throw new Error("Bezier 类被设计成单例了!!!"); }else{ $instance = this; } } // ===================================== 方法 // 速度函数 private function s (t:Number):Number { return Math.sqrt(A * t * t + B * t + C); } // 长度函数 private function L (t:Number):Number { var temp1:Number = Math.sqrt(C + t * (B + A * t)); var temp2:Number = (2 * A * t * temp1 + B *(temp1 - Math.sqrt(C))); var temp3:Number = Math.log(B + 2 * Math.sqrt(A) * Math.sqrt(C)); var temp4:Number = Math.log(B + 2 * A * t + 2 * Math.sqrt(A) * temp1); var temp5:Number = 2 * Math.sqrt(A) * temp2; var temp6:Number = (B * B - 4 * A * C) * (temp3 - temp4); return (temp5 + temp6) / (8 * Math.pow(A, 1.5)); } // 长度函数反函数,使用牛顿切线法求解 private function InvertL (t:Number, l:Number):Number{ var t1:Number = t; var t2:Number; do{ t2 = t1 - (L(t1) - l)/s(t1); if (Math.abs(t1-t2) < 0.000001) break; t1 = t2; }while(true); return t2; } // 返回所需总步数 /** *获得所需步数 * @param $p0 ->起始点 * @param $p1 ->控制点 * @param $p2 ->结束点 * @param $speed ->速度 * @return * */ public function init ($p0:Point, $p1:Point, $p2:Point, $speed:Number):uint { p0 = $p0; p1 = $p1; p2 = $p2; //step = 30; ax = p0.x - 2 * p1.x + p2.x; ay = p0.y - 2 * p1.y + p2.y; bx = 2 * p1.x - 2 * p0.x; by = 2 * p1.y - 2 * p0.y; A = 4*(ax * ax + ay * ay); B = 4*(ax * bx + ay * by); C = bx * bx + by * by; // 计算长度 total_length = L(1); // 计算步数 step = Math.floor(total_length / $speed); if (total_length % $speed > $speed / 2) step ++; return step; } // 根据指定nIndex位置获取锚点:返回坐标和角度 public function getAnchorPoint (nIndex:Number):Array { if (nIndex >= 0 && nIndex <= step) { var t:Number = nIndex/step; // 如果按照线行增长,此时对应的曲线长度 var l:Number = t*total_length; // 根据L函数的反函数,求得l对应的t值 t = InvertL(t, l); // 根据贝塞尔曲线函数,求得取得此时的x,y坐标 var xx:Number = (1 - t) * (1 - t) * p0.x + 2 * (1 - t) * t * p1.x + t * t * p2.x; var yy:Number = (1 - t) * (1 - t) * p0.y + 2 * (1 - t) * t * p1.y + t * t * p2.y; // 获取切线 var Q0:Point = new Point((1 - t) * p0.x + t * p1.x, (1 - t) * p0.y + t * p1.y); var Q1:Point = new Point((1 - t) * p1.x + t * p2.x, (1 - t) * p1.y + t * p2.y); // 计算角度 var dx:Number = Q1.x - Q0.x; var dy:Number = Q1.y - Q0.y; var radians:Number = Math.atan2(dy, dx); var degrees:Number = radians * 180 / Math.PI; return new Array(xx, yy, degrees); } else { return []; } } } }
应用:
steps = Bezier.instance().init(startPoint,controlPoint,endPoint,8); var tmpArr:Array = Bezier.instance().getAnchorPoint(crtStep); arrow.x = tmpArr[0]; arrow.y = tmpArr[1]; arrow.rotation = tmpArr[2]; this.crtStep++; if(crtStep>steps){ crtStep=0; if(Math.random()>0.5){ tower.shooterLeft.gotoAndPlay(2); }else{ tower.shooterRight.gotoAndPlay(2); } }
http://blog.sqstudio.com/as3/algorithm/768.html#codesyntax_2
上一篇: JMS和ActiveMQ介绍(3)_Ac
下一篇: 3.redis集群部署3主3从
47848
46399
37285
34737
29318
25975
24918
19954
19548
18031
5795°
6419°
5931°
5964°
7070°
5917°
5948°
6441°
6405°
7782°