【问题标题】:Questions about drawing 2D bullet paths in XNA关于在 XNA 中绘制 2D 子弹路径的问题
【发布时间】:2013-01-11 23:24:17
【问题描述】:

所以基本上它是一个 2D 平台射击游戏。我想画出每个子弹的路径。每个子弹后面应该有一条白线,并且alpha值应该从子弹到它被发射的位置递减。

我怎样才能创造出这样的效果?

编辑:我只是要求一个基本的方法而不是详细的代码。 我想我可能需要使用粒子效果来做到这一点?

编辑 2: 谢谢!但是我可以改变渐变线纹理的源矩形而不是缩放它吗?

如果我在某处弄错了,请纠正我,谢谢!

Texture2D 渐变线应如下所示:

(据我记得使用 Math.Atan2 求矢量角度时,0 度应该在 Y 轴正方向)

我正在使用这种方法来查找向量的度数。由于正 Y 在窗口坐标系中沿着窗口向下,我在这里改为 -vector.Y :(这对我来说更有意义)

protected float VectorToRadians(Vector2 vector)
{
    return (float)Math.Atan2(vector.X, -vector.Y);
}

我还需要找到子弹与发射位置之间的距离,以确定源矩形的高度。所以我有这样的方法

protected int GetRectangleHeight(Vector2 startingPos, Vector2 currentPos, int lineTextureLength)
{
    float distance = (startingPos - currentPos).Length();
    if (distance < lineTextureLength)  // if distance is smaller than the texture length, only draw part of it
        return distance;
    else                        // if distance is larger or equal to the texture length, draw the entire texture
        return lineTextureLength;
}

终于抽签了

spriteBatch.Draw(
  gradline,
  bulletCurrentPos,
  new Rectangle(0, 0, gradline.Width, GetRectangleHeight(bulletStartingPos, bulletCurrentPos),
  Color.White,
  VectorToRadians(bulletCurrentPos - bulletStartingPos),
  Vector2.Zero,     // actually i think setting the top-center as origin might look better
  1f,                  // full scale
  SpriteEffects.None,
  0f);

当子弹击中某物并消失时,路径仍应绘制在屏幕上。在此期间,源矩形的 y(以及高度,我认为,以确保矩形不会超出纹理)应更改为仅绘制轨迹的末端部分,直到 y 达到纹理。

【问题讨论】:

  • 当然,如果你的纹理有点宽,你应该改变原点向量。

标签: c# xna


【解决方案1】:

您可以使用渐变为透明颜色的线条图像来做到这一点。像这样:

这是一个从屏幕中心到光标(激光瞄准器)绘制轨迹的版本:

(如果您希望它从其他地方绘制,您可以将centerScreencursor_v2 替换为您喜欢的Vector2,例如子弹的当前位置以及该子弹最初发射的位置。为此,我答案末尾的代码段可能是最好的。)

Texture2D gradline; // set this var to your fading line texture in LoadContent 

Vector2 centerScreen = new Vector2(
  GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);
Vector2 cursor_v2 = new Vector2(currentMouseState.X, currentMouseState.Y);

spriteBatch.Draw(           // this is one of many Draw overloads
  gradline,                // your line texture
  centerScreen,           // we just set this to be at your game window center
  null,                  // this means entire texture will be drawn
  Color.White,                        // no tinting
  GetAngle(centerScreen, cursor_v2), // this rotates texture, see my code below
  Vector2.Zero,      // texture will be drawn from screen center without offset
  new Vector2(GetDistance(centerScreen, cursor_v2) / gradline.Width, 1),
    // ↑ This is scaling vector, X scales texture to distance from screen center
   //  to cursor and then divides by the texture's length.
  //  See how Y is set to 1, which means texture height will not be changed.

  SpriteEffects.None,  // this can mirror the texture, we don't do this now
  0f);                // everybody leaves this zero :p

再一次没有 cmets:

spriteBatch.Draw(gradline, centerScreen, null, Color.White, GetAngle(centerScreen, cursor_v2), Vector2.Zero, new Vector2(GetDistance(centerScreen, cursor_v2) / gradline.Width, 1), SpriteEffects.None, 0f );

我获取角度值的代码:(只需将它放在你的 Game 类中的某个位置)

public float GetAngle(Vector2 v1, Vector2 v2)
{
    Vector2 v = Vector2.Normalize(Vector2.Subtract(v2, v1));

    return (float)Math.Atan2(v.Y, v.X);
}

或者,您可以制作一个恒定长度的纹理,然后使用以下代码旋转它:

spriteBatch.Draw(gradline, centerScreen, null, Color.White,
  GetAngle(centerScreen, cursor_v2), Vector2.Zero, 1, SpriteEffects.None, 0f);
                                      // look here ↑
  // this Draw overload takes float value instead of Vector2 for scaling textures
  //   so with 1 the texture size will not be scaled

另一种方法是在游戏中每颗子弹的位置每半秒左右创建一次粒子,粒子过期后删除。我怀疑你的子弹是直线移动的,而不是抛物线,所以它可能不值得在性能方面这样做。

如果您的子弹经常改变方向,您可以绘制它们的完整路径,但这需要绘制VertexPositionColor 的列表,这更复杂,但可能会产生不错的结果。

【讨论】:

  • 谢谢,但我认为用 1.0f 全比例绘制渐变线纹理但修改源矩形会使其看起来更好。
  • 为什么是源矩形?您真的想将原始纹理裁剪为更小的纹理吗?但如果您指的是目标矩形,则它与缩放相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多