Actionscript 3 坐标插值
我们正在从服务器发送到客户端的坐标球每300毫秒。我们必须插值坐标,使移动平稳。以下是代码(AS3): 下图描述了该问题:Actionscript 3 坐标插值,actionscript-3,math,interpolation,Actionscript 3,Math,Interpolation,我们正在从服务器发送到客户端的坐标球每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];
}
}
}
}