Actionscript 3 坐标插值

Actionscript 3 坐标插值,actionscript-3,math,interpolation,Actionscript 3,Math,Interpolation,我们正在从服务器发送到客户端的坐标球每300毫秒。我们必须插值坐标,使移动平稳。以下是代码(AS3): 下图描述了该问题: 红点-终点 黑线-从当前点到目的地的线,没有 规范化 绿色点-球的路径 也许有一种方法可以使移动更平滑但更准确?您可以在每个刻度上发送多个坐标。或者随每个点发送一些额外的属性,比如说它是否是球反弹的点,或者它是否可以平滑 与发送、处理和接收的开销相比,在一个事务中发送一系列点可以提高准确性,并且不会增加太多的数据包大小。每个刻度可以发送多个坐标。或者随每个点发送一些额

我们正在从服务器发送到客户端的坐标球每300毫秒。我们必须插值坐标,使移动平稳。以下是代码(AS3):

下图描述了该问题:

  • 红点-终点

  • 黑线-从当前点到目的地的线,没有 规范化

  • 绿色点-球的路径


也许有一种方法可以使移动更平滑但更准确?

您可以在每个刻度上发送多个坐标。或者随每个点发送一些额外的属性,比如说它是否是球反弹的点,或者它是否可以平滑


与发送、处理和接收的开销相比,在一个事务中发送一系列点可以提高准确性,并且不会增加太多的数据包大小。

每个刻度可以发送多个坐标。或者随每个点发送一些额外的属性,比如说它是否是球反弹的点,或者它是否可以平滑

与发送、处理和接收的开销相比,在一个事务中发送一系列点可以提高准确性,并且不会增加太多的数据包大小

  • 如果要为精确的三个点插值路径步长,则需要使用数学来计算曲线上距离起点任意给定距离的任意位置。你需要这样才能在曲线上获得相等的步长,就像你在照片上看到的那样。这是相当棘手的,因为当您使用多项式形式的贝塞尔曲线方程时,对于等参数增量,沿曲线的距离并不相等。





    因此,您需要将贝塞尔曲线视为抛物线段(实际上是这样),并且可以将任务重新表示为“以相等长度的步长沿着抛物线走”。这仍然很棘手,但幸运的是有一个解决方案:




    我多次使用这个库(沿抛物线做相等的步数),它对我非常有效。

  • 你很可能想要在任意点集之间插值。如果是这种情况,你可以使用拉格朗日近似法

    下面是我对拉格朗日近似法的简单实现。(谷歌搜索它肯定会给你更多。)您可以为近似器提供任意数量的已知函数值,它可以为介于两者之间的任何参数值生成平滑函数的值
  • --

    package org.noregret.math
    {
    导入flash.geom.Point;
    导入flash.utils.Dictionary;
    /**
    *@作者Michael“Nox Noctis”Antipin
    */
    公共类拉格朗日逼近器{
    专用常量点:向量。=新向量。();
    private const pointByArg:Dictionary=new Dictionary();
    私有变量排序:布尔值;
    公共函数代理程序()
    {
    }
    公共函数addValue(参数:Number,值:Number):void
    {
    var点:点;
    if(pointByArg[参数]!=null){
    跟踪(“LagrangeApproximator.addValue(“+arguments+”):错误重复函数参数!”;
    point=pointByArg[参数];
    }否则{
    点=新点();
    点。推(点);
    pointByArg[参数]=点;
    }
    点x=参数;
    点y=值;
    isSorted=假;
    }
    公共函数getApproximationValue(参数:Number):Number
    {
    如果(!isSorted){
    isSorted=true;
    点。排序(排序);
    }
    变量listLength:uint=points.length;
    变量点1:点,点2:点;
    var结果:数值=0;
    var系数:个数;
    对于(变量i:uint=0;i
    
  • 如果你想为精确的三个点插值路径步数,你需要使用数学来计算曲线上从起点到任意给定距离的任何位置。你需要这一点来获得曲线上的相等步数,就像你在图片上看到的那样。这是相当棘手的,因为当你在多项式中使用贝塞尔曲线方程时因此,您需要将贝塞尔曲线视为抛物线段(实际上是这样),任务可以重新表述为“沿抛物线曲线以相等长度的步长进行步进”“。这仍然很棘手,但幸运的是有一个解决方案:




    我多次使用这个库(沿抛物线做相等的步数),它对我非常有效。

  • 你很可能想要在任意点集之间插值。如果是这种情况,你可以使用拉格朗日近似法

    下面是我对拉格朗日近似法的简单实现。(谷歌搜索它肯定会给你更多。)您可以为近似器提供任意数量的已知函数值,它可以为介于两者之间的任何参数值生成平滑函数的值
  • --

    package org.noregret.math
    {
    导入flash.geom.Point;
    导入flash.utils.Dictionary;
    /**
    *@作者Michael“Nox Noctis”Antipin
    */
    公共类拉格朗日逼近器{
    专用常量点:向量。=新向量。();
    private const pointByArg:Dictionary=new Dictionary();
    私有变量排序:布尔值;
    公共函数代理程序()
    {
    }
    公共函数addValue(参数:Number,值:Number):void
    {
    var点:点;
    if(pointByArg[参数]!=null){
    跟踪(“LagrangeApproximator.addValue(“+arguments+”):错误重复函数参数!”)
    
    private function run(event:Event):void
    {
        // Current frame ball position
        var currentPosition:Point = new Point(this.x, this.y);
    
        // Vector of the speed
        _velocity = _destinationPoint.subtract(currentPosition);
    
        // Interpolation
        // Game.timeLapse - time from last package with coordinates (last change of destinationPoint)
        // stage.frameRate - fps
        _velocity.normalize(_velocity.length * 1000 / Game.timeLapse / stage.frameRate);
    
        // If ball isn't at the end of the path, move it
        if (Point.distance(currentPosition, _destinationPoint) > 1) {
            this.x += _velocity.x;
            this.y += _velocity.y;
        } else {
            // Otherwise (we are at the end of the path - remove listener from this event
            this.removeEventListener(Event.ENTER_FRAME, run);
            this.dispatchEvent(new GameEvent(GameEvent.PLAYER_STOP));
        }
    }
    
    package org.noregret.math 
    {
        import flash.geom.Point;
        import flash.utils.Dictionary;
    
        /**
         * @author Michael "Nox Noctis" Antipin
         */
        public class LagrangeApproximator {
    
            private const points:Vector.<Point> = new Vector.<Point>();
            private const pointByArg:Dictionary = new Dictionary();
    
            private var isSorted:Boolean;
    
            public function LagrangeApproximator()
            {
            }
    
            public function addValue(argument:Number, value:Number):void
            {
                var point:Point;
                if (pointByArg[argument] != null) {
                    trace("LagrangeApproximator.addValue("+arguments+"): ERROR duplicate function argument!");
                    point = pointByArg[argument];
                } else {
                    point = new Point();
                    points.push(point);
                    pointByArg[argument] = point;
                }
                point.x = argument;
                point.y = value;
                isSorted = false;
            }
    
            public function getApproximationValue(argument:Number):Number
            {
                if (!isSorted) {
                    isSorted = true;
                    points.sort(sortByArgument);
                }
                var listLength:uint = points.length;
                var point1:Point, point2:Point;
                var result:Number = 0;
                var coefficient:Number;
                for(var i:uint =0; i<listLength; i++) {
                    coefficient = 1;
                    point1 = points[i];
                    for(var j:uint = 0; j<listLength; j++) {
                        if (i != j) {
                            point2 = points[j];
                            coefficient *= (argument-point2.x) / (point1.x-point2.x);
                        }
                    }        
                    result += point1.y * coefficient;
                }
                return result;
            }
    
            private function sortByArgument(a:Point, b:Point):int
            {
                if (a.x < b.x) {
                    return -1;
                }
                if (a.x > b.x) {
                    return 1;
                }            
                return 0;
            }
    
            public function get length():int
            {
                return points.length;            
            }
    
            public function clear():void
            {
                points.length = 0;
                var key:*;
                for (key in pointByArg) {
                    delete pointByArg[key];
                }
            }
        }
    }