C# 绘制船舶的二维轨迹。新华社

C# 绘制船舶的二维轨迹。新华社,c#,xna,draw,xna-4.0,bezier,C#,Xna,Draw,Xna 4.0,Bezier,一段时间以来,我一直在寻找解决方案,已经有很多元素需要处理,但实际上并没有如何将它们组合在一起 目标:为玩家的飞船绘制轨迹 到目前为止:由于船的方向是不可预测的,我只有玩家船的先前位置可以使用。为了绘制轨迹,我可以简单地在播放器的前一个位置绘制一个像素(或纹理),但这是一个内存开销大的问题,而且它不会绘制曲线,也不会达到令人赏心悦目的曲线效果 我一直在寻找Beziers路径和Cathmull Rom的解决方案 现在我可以得到一个给定点的控制点,然后从2个点和2个控制点计算出一条曲线,从这里我制作

一段时间以来,我一直在寻找解决方案,已经有很多元素需要处理,但实际上并没有如何将它们组合在一起

目标:为玩家的飞船绘制轨迹

到目前为止:由于船的方向是不可预测的,我只有玩家船的先前位置可以使用。为了绘制轨迹,我可以简单地在播放器的前一个位置绘制一个像素(或纹理),但这是一个内存开销大的问题,而且它不会绘制曲线,也不会达到令人赏心悦目的曲线效果

我一直在寻找Beziers路径和Cathmull Rom的解决方案

现在我可以得到一个给定点的控制点,然后从2个点和2个控制点计算出一条曲线,从这里我制作了一个顶点曝光颜色数组,点之间有一个距离,从曲线上生成一个三角形条纹

到目前为止,我拥有以下主要功能:

        public Vector2[] GetControlPoints(Vector2 p0, Vector2 p1, Vector2 p2, float tension = 0.5f)
        {
            // get length of lines [p0-p1] and [p1-p2]
            float d01 = Vector2.Distance(p0, p1);
            float d12 = Vector2.Distance(p1, p2);
            // calculate scaling factors as fractions of total
            float sa = tension * d01 / (d01 + d12);
            float sb = tension * d12 / (d01 + d12);
            // left control point
            float c1x = p1.X - sa * (p2.X - p0.X);
            float c1y = p1.Y - sa * (p2.Y - p0.Y);
            // right control point
            float c2x = p1.X + sb * (p2.X - p0.X);
            float c2y = p1.Y + sb * (p2.Y - p0.Y);
            return new Vector2[] {new Vector2(c1x, c1y), new Vector2(c2x, c2y) };
        }

         // Given 2 points and 2 control points
        public static VertexPositionColor[] bezierCurve(Vector2 start, Vector2 end, Vector2 c1, Vector2 c2)
        {
            VertexPositionColor[] points = new VertexPositionColor[SUBDIVISIONS + 2];

            float fraction;

            for (int i = 0; i < SUBDIVISIONS + 2; i++)
            {
                fraction = i * (1f / (float)SUBDIVISIONS);
                points[i] = new VertexPositionColor(new Vector3((float)((start.X * Math.Pow((1 - fraction), 3))
                    +(c1.X * 3 * fraction * Math.Pow(1-fraction, 2))
                    +(c2.X * 3 * Math.Pow(fraction,2) * (1-fraction))
                    +(end.X * Math.Pow(fraction,3))),

                    (float)((start.Y * Math.Pow((1 - fraction), 3))
                    + (c1.Y * 3 * fraction * Math.Pow(1 - fraction, 2))
                    + (c2.Y * 3 * Math.Pow(fraction, 2) * (1 - fraction))
                    + (end.Y * Math.Pow(fraction, 3))), 0), UNLIT);
            }

            return points;
        }

        /*
        * This function treats the curve as a series of straight lines and calculates points on a line perpendicular to each point, resulting in two points THICKNESS appart. 
        * Requires THICKNESS to be set
        */
        public static VertexPositionColor[] curveToStrip(VertexPositionColor[] curve)
        {
            VertexPositionColor[] strip = new VertexPositionColor[curve.Length * 2];
            VertexPositionColor[] new1 = new VertexPositionColor[curve.Length];
            VertexPositionColor[] new2 = new VertexPositionColor[curve.Length];

            for (int i = 0; i < curve.Length; i++)
            {
                if (i < curve.Length-1)
                {
                    Vector2 p1 = new Vector2(curve[i].Position.X, curve[i].Position.Y);
                    Vector2 p2 = new Vector2(curve[i + 1].Position.X, curve[i + 1].Position.Y);
                    Vector2 perpPoint = perpendicularPoint(p1, p2);

                    new1[i] = new VertexPositionColor(new Vector3(distanceToPoint(p1, perpPoint, THICKNESS / 2), 0), UNLIT);
                    new2[i] = new VertexPositionColor(new Vector3(distanceToPoint(p1, perpPoint, -1 * THICKNESS / 2), 0), UNLIT);
                }
                else
                {
                    Vector2 p1 = new Vector2(curve[i].Position.X, curve[i].Position.Y);
                    Vector2 p2 = new Vector2(curve[i - 1].Position.X, curve[i - 1].Position.Y);
                    Vector2 perpPoint = perpendicularPoint(p1, p2);

                    new1[i] = new VertexPositionColor(new Vector3(distanceToPoint(p1, perpPoint, -1 * THICKNESS / 2), 0), UNLIT);
                    new2[i] = new VertexPositionColor(new Vector3(distanceToPoint(p1, perpPoint, THICKNESS / 2), 0), UNLIT);
                }
            }
public Vector2[]获取控制点(Vector2 p0、Vector2 p1、Vector2 p2、浮动张力=0.5f)
{
//获取线的长度[p0-p1]和[p1-p2]
浮点d01=矢量2.距离(p0,p1);
浮点d12=矢量2.距离(p1,p2);
//将比例因子计算为总比例的分数
浮子sa=张力*d01/(d01+d12);
浮动sb=张力*d12/(d01+d12);
//左控制点
浮点c1x=p1.X-sa*(p2.X-p0.X);
浮点数c1y=p1.Y-sa*(p2.Y-p0.Y);
//右控制点
浮点数c2x=p1.X+sb*(p2.X-p0.X);
浮点数c2y=p1.Y+sb*(p2.Y-p0.Y);
返回新的Vector2[]{newvector2(c1x,c1y),newvector2(c2x,c2y)};
}
//给出2个点和2个控制点
公共静态VertexPositionColor[]Bezier曲线(矢量2开始、矢量2结束、矢量2 c1、矢量2 c2)
{
VertexPositionColor[]点=新的VertexPositionColor[细分+2];
浮点数;
对于(int i=0;i
我曾考虑在绘制阶段调用函数,但仅仅绘制一条小曲线和绘制一条更大的Beziers路径似乎非常昂贵,我认为情况更糟。因为我会在每一帧上获得一个点,所以会调用每个函数来计算点之间的曲线,只需绘制一条3像素(或更少)的曲线

我该怎么做?有什么建议吗

我还是这类东西的初学者

所有这些我都是从几个渠道得到的:


一种方法是,创建一个轨迹/粒子列表,然后在每一帧上初始化,或者你喜欢多少。我将尝试在下面的伪代码中进行解释。我还对每个轨迹旋转一点,使用不同大小和颜色的烟雾纹理,并在初始化中添加一点OFSET+-5像素

class Trail
    position as vector2d
    duration as single
    velocity as vector2d
    fade as integer = 1
    active = true
end class

class Trails
    inherits list of Trail
    sub Init(position as vector2d, velocity as vector2d)
        // add trail to list
    end sub
    sub Update()
        for each trail in me.findAll(function(c) c.active))
            position += velocity
            fade -= .05 // or some value
        end for
        me.removeAll(function(c) not(c.active)) // remove from list when unused
    end sub
    sub Draw()
        for each trail in me.findAll(function(c) c.active))
            draw(smokeTexture, position, size, rotate, color * trail.fade)
        end for
    end sub
end class
通过这个我已经达到了这个效果,它几乎看不见,但它产生了效果

我将简单地解释这是如何工作的:

它是接收位置的函数,每次您想要添加下一段轨迹时都会调用它

调用该函数时,它会在位置上添加两个顶点,查看上一步中的切线向量,创建到当前位置的法线向量,并根据轨迹宽度沿该法线放置顶点

接下来,它查看前两个顶点,并根据当前切线和前一个切线的平均值将它们对齐,从而创建梯形

我建议