C# 绘制船舶的二维轨迹。新华社
一段时间以来,我一直在寻找解决方案,已经有很多元素需要处理,但实际上并没有如何将它们组合在一起 目标:为玩家的飞船绘制轨迹 到目前为止:由于船的方向是不可预测的,我只有玩家船的先前位置可以使用。为了绘制轨迹,我可以简单地在播放器的前一个位置绘制一个像素(或纹理),但这是一个内存开销大的问题,而且它不会绘制曲线,也不会达到令人赏心悦目的曲线效果 我一直在寻找Beziers路径和Cathmull Rom的解决方案 现在我可以得到一个给定点的控制点,然后从2个点和2个控制点计算出一条曲线,从这里我制作了一个顶点曝光颜色数组,点之间有一个距离,从曲线上生成一个三角形条纹 到目前为止,我拥有以下主要功能:C# 绘制船舶的二维轨迹。新华社,c#,xna,draw,xna-4.0,bezier,C#,Xna,Draw,Xna 4.0,Bezier,一段时间以来,我一直在寻找解决方案,已经有很多元素需要处理,但实际上并没有如何将它们组合在一起 目标:为玩家的飞船绘制轨迹 到目前为止:由于船的方向是不可预测的,我只有玩家船的先前位置可以使用。为了绘制轨迹,我可以简单地在播放器的前一个位置绘制一个像素(或纹理),但这是一个内存开销大的问题,而且它不会绘制曲线,也不会达到令人赏心悦目的曲线效果 我一直在寻找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
通过这个我已经达到了这个效果,它几乎看不见,但它产生了效果
我将简单地解释这是如何工作的:
它是接收位置的函数,每次您想要添加下一段轨迹时都会调用它
调用该函数时,它会在位置上添加两个顶点,查看上一步中的切线向量,创建到当前位置的法线向量,并根据轨迹宽度沿该法线放置顶点
接下来,它查看前两个顶点,并根据当前切线和前一个切线的平均值将它们对齐,从而创建梯形
我建议