具有随机速度的 2D 粒子系统
我最近使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
随机类确保伪随机性(如果您正在使用的话)。查看 RNGCryptoServiceProvider。
Random class ensures pseudo-randomness, if that is what you are using. Have a look at RNGCryptoServiceProvider.
好吧,查尔,你要解决这个问题,就是创建一个没有种子的随机对象(你就是),然后一遍又一遍地使用它。所以类似:
要获得下限和上限之间的随机浮点值(浮点或双精度),您可以使用类似的东西:
编辑:并确保使用双精度或浮点。整型只是整数,双精度和浮点数可以存储实数,这可能就是 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:
To get a random floating point value (float or double) between a lower and upper bound, you can use something like:
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.
如果您发布了一些代码,我们可能能够指出您在哪里为每个调用创建一个
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 tofloat
but always end in##.0
.In VB
I / J
yields a double.