具有随机速度的 2D 粒子系统

发布于 2024-11-30 09:05:12 字数 1810 浏览 1 评论 0原文

我最近使用 Visual Basic .Net 编写了一个粒子系统,该系统在 x 和 y 方向上以随机速度发射粒子,并受到重力的影响。我转向 C# .Net 并使用 XNA Game Studio,这使得图形处理比 GDI+ 方便得多。

我在 C# 中遇到的问题是随机数不够“随机”。我的粒子系统有 2500 个粒子,但您可以清楚地看到粒子以网格状分布,相距约 100 个像素,并且我使用 Visual Basic 的 Rnd() 函数没有遇到这个问题。

Visual Basic 能做什么而 C# 不能,以及如何在 C# 中获得相同的结果?

我尝试在游戏循环的不同阶段重新初始化我的随机数,但最终我的粒子要么停留在一个位置,要么以恒定的流向一个方向发射。

这是我的 C# 代码:程序启动后首先调用 LoadContent。我使用毫秒作为种子,以便每次都以不同的配置开始。

下一次我重新播种是在渲染之前在系统上完成所有计算之后。我尝试的另一种选择是在每计算 100 个粒子后重新播种,但没有区别。

        protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);
        mousePos = Content.Load<Texture2D>("Point");
        spriteTex = Content.Load<Texture2D >("Point");
        rnd = new Random(a.Millisecond);
        for (int i = 0; i < spritePos .Length; i++)
        {
            newPos[i] = new Vector2(800, 450);
            spritePos[i] = newPos[i] ;
            Scale[i] = rnd.Next(100,500);
            renderCol[i] = new Color(rnd.Next(255), rnd.Next(255), rnd.Next(255), 1);
            spriteVelocity[i] = new Vector2((rnd.Next(2000)-1000)/100, -rnd.Next(500,1500)/100);
            Life[i] = rnd.Next(60);
            Rotate[i] = (rnd.Next(1000)-500) * 0.001f;
            RotateSpeed[i] = (rnd.Next(1000)-500) * 0.0001f;

        }

    }

这是我的 VB 代码,是我使用 rnd 函数的唯一地方:

            For i = x To x + 1000
                ptc(i) = New particle(New Vector((Rnd() * 200) - 200 * Rnd(), Rnd() * -100 - 200 * Rnd() - 200), New Vector(e.X, e.Y), 500, Color.FromArgb(Rnd() * 255, 255, 0))
                x += 1
            Next

在我的 VB 代码中,没有地方可以调用 randomize 函数,我注意到如果调用的话,我的粒子具有相同的类似模式的行为。请原谅所有奇怪的算术,这只是实验。

I have recently used Visual Basic .Net to write a particle system which emits particles with random velocities in the x and y direction and is affected by gravity. I switched to C# .Net and used the XNA Game Studio which makes the graphics handling much more convenient than GDI+.

The problem I have with C# is that the random numbers are not "random enough". My particle system has 2500 particles but you can clearly see that the particles are distributed in a grid-like fashion about 100 pixels apart and I did not have that problem with Visual Basic's Rnd() function.

What does Visual Basic do which C# does not, and how can I get the same results in C#?

I have tried to re-initialise my random numbers at different stages of the game loop but I end up either with my particles staying at one position or emitting just in a constant stream in one direction.

This is my C# code: LoadContent is called first thing after the program has started. I'm using the millisecond as a seed just so that I start each time with a different configuration.

The next time I re-seed is after all the calculations are done on the system just before rendering. The other alternative I tried is to re-seed after every 100 particles have been calculated but with no difference.

        protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);
        mousePos = Content.Load<Texture2D>("Point");
        spriteTex = Content.Load<Texture2D >("Point");
        rnd = new Random(a.Millisecond);
        for (int i = 0; i < spritePos .Length; i++)
        {
            newPos[i] = new Vector2(800, 450);
            spritePos[i] = newPos[i] ;
            Scale[i] = rnd.Next(100,500);
            renderCol[i] = new Color(rnd.Next(255), rnd.Next(255), rnd.Next(255), 1);
            spriteVelocity[i] = new Vector2((rnd.Next(2000)-1000)/100, -rnd.Next(500,1500)/100);
            Life[i] = rnd.Next(60);
            Rotate[i] = (rnd.Next(1000)-500) * 0.001f;
            RotateSpeed[i] = (rnd.Next(1000)-500) * 0.0001f;

        }

    }

This is my VB code, the only place where I use the rnd function:

            For i = x To x + 1000
                ptc(i) = New particle(New Vector((Rnd() * 200) - 200 * Rnd(), Rnd() * -100 - 200 * Rnd() - 200), New Vector(e.X, e.Y), 500, Color.FromArgb(Rnd() * 255, 255, 0))
                x += 1
            Next

In my VB code there is no place where I call the randomize function, I have noticed that my particles have the same pattern-like behaviour if I do. Excuse all the strange arithmetic, it's all just experimentation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

甜扑 2024-12-07 09:05:13

随机类确保伪随机性(如果您正在使用的话)。查看 RNGCryptoServiceProvider

Random class ensures pseudo-randomness, if that is what you are using. Have a look at RNGCryptoServiceProvider.

请叫√我孤独 2024-12-07 09:05:12

好吧,查尔,你要解决这个问题,就是创建一个没有种子的随机对象(你就是),然后一遍又一遍地使用它。所以类似:

const double max = 1000.0;
Random rand = new Random();     // Like mentioned, don't provide a seed, .NET already picks a great seed for you
for(int iParticle = 0; iParticle < 2500; iParticle++)
{
    double x = rand.NextDouble() * max;     // Will generate a random number between 0 and max
    double y = rand.NextDouble() * max;
}

要获得下限和上限之间的随机浮点值(浮点或双精度),您可以使用类似的东西:

double x = (rand.NextDouble() * (max - min)) + min;

编辑:并确保使用双精度或浮点。整型只是整数,双精度和浮点数可以存储实数,这可能就是 VB 所使用的。

Ok, what you do to fix it Charl, is to create a single Random object (which you are) with no seed, and use it over and over again. So something like:

const double max = 1000.0;
Random rand = new Random();     // Like mentioned, don't provide a seed, .NET already picks a great seed for you
for(int iParticle = 0; iParticle < 2500; iParticle++)
{
    double x = rand.NextDouble() * max;     // Will generate a random number between 0 and max
    double y = rand.NextDouble() * max;
}

To get a random floating point value (float or double) between a lower and upper bound, you can use something like:

double x = (rand.NextDouble() * (max - min)) + min;

EDIT: And make sure to use double or float. Ints are whole numbers only, doubles and floats can store real numbers and is probably what VB was using.

热鲨 2024-12-07 09:05:12

如果您发布了一些代码,我们可能能够指出您在哪里为每个调用创建一个 new Random() 对象。

例如, 循环中的随机数


看到代码后,

您是否知道 (rnd.Next(2000)-1000)/100 是一个纯整数表达式吗?结果将转换为 float 但始终以 ##.0 结尾。

在 VB 中,I / J 产生一个双精度值。

If you had posted some code we would probably have been able to point out where you are creating a new Random() object for each call .

Like in, for example, Random number in a loop


After seeing the code,

are you aware that (rnd.Next(2000)-1000)/100 is an integer only expression? The result will be converted to float but always end in ##.0.

In VB I / J yields a double.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文