我刚刚开始使用MonoGame和C#,我遇到了一个问题,试图将1个图像用于对象列表。
我正在尝试制作带有1张图像的20个气球,但它们应该都有不同的位置和计时器。它们被添加到循环0-19中的List中,在每次迭代时我创建一个新的Balloon(图像),构造函数给它随机的起始坐标和计时器,并从参数中获取图像。
我遇到的问题是列表中的所有气球都获得了循环结束后添加的最后一个气球的值,如果它们都是相同的对象,那就是这样,但我创建一个新的气球每次都不知道这里发生了什么?
气球课:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace Game1
{
public class Balloon
{
private const int SCREEN_WIDTH = 640;
private const int SCREEN_HEIGHT = 480;
private const int MIN_VELOCITY = 30;
//picture from contents
private Texture2D image;
//balloons current position
private Vector2 position;
//how fast its moving
private Vector2 velocity;
private bool moving;
//timer, so they can pop up at a diferent time, number 1-9
private int timer;
public Balloon(Texture2D image)
{
this.image = image;
setRandomPosition();
setRandomTimer();
//no balloon is moving when initialsied
moving = false;
//start with 0 speed
velocity = new Vector2(0.0f, 0.0f);
}
//sets random X for the balloon, with Y just out of screen visible area
public void setRandomPosition()
{
position = new Vector2(new Random().Next(SCREEN_WIDTH), SCREEN_HEIGHT + 1);
}
//number 1-9 , balloon starts moving when seconds elapsed % timer is 0
public void setRandomTimer()
{
timer = new Random().Next(1, 10);
}
private void calculateRandomVelocity()
{
velocity = new Vector2(velocity.X, new Random().Next(50) + MIN_VELOCITY);
}
//starts moving the balloon by subtracting the Y
public void go(GameTime gameTime)
{
moving = true;
calculateRandomVelocity();
//subtract Y so balloon goes up
position -= velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;
}
//stops the balloon and sets random X with Y outside visible area
public void stop()
{
moving = false;
setRandomPosition();
}
//--------Getters and Setters------------//
public Vector2 getPosition()
{
return position;
}
public void setMoving(bool moving)
{
this.moving = moving;
}
public bool isMoving()
{
return moving;
}
public Texture2D getImage()
{
return image;
}
public void setImage(Texture2D image)
{
this.image = image;
}
public int getTimer()
{
return timer;
}
}
}
游戏课程:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Game1
{
public class Game1 : Game
{
const int NUM_BALLOONS = 20;
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
List<Balloon> balloons;
public Game1()
{
Content.RootDirectory = "Content";
graphics = new GraphicsDeviceManager(this);
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
loadBalloonsIntoList();
}
public void loadBalloonsIntoList()
{
balloons = new List<Balloon>();
Texture2D image = Content.Load<Texture2D>("balloon");
//load 20 balloons into the list
//after loading here it ends up with same properties - exact same object for all the elements
//they all take the values from the last one added
for (int i = 0; i < NUM_BALLOONS; i++)
{
Balloon b = new Balloon(image);
balloons.Add(b);
}
}
public void moveBalloons(GameTime gameTime)
{
foreach(Balloon b in balloons)
{
//cant be 0 because all balloons would start on first iteration, start moving a balloon that is not moving already
//and its time has come
if (gameTime.ElapsedGameTime.Seconds > 0 && gameTime.ElapsedGameTime.Seconds % b.getTimer() == 0 && !b.isMoving())
{
b.go(gameTime);
}
//stop the balloon when it goes out of visible area
if (b.getPosition().Y <= 0)
{
b.stop();
}
}
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
moveBalloons(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.White);
spriteBatch.Begin();
foreach(Balloon b in balloons)
{
spriteBatch.Draw(b.getImage(), b.getPosition(), Color.White);
}
spriteBatch.End();
}
}
}
答案 0 :(得分:2)
您的setRandomPosition方法会在每次调用时创建Random类的新实例。由于20个气球正在快速连续地实例化(即在循环中),因此每个新的Random类实例可能以相同的种子值结束,因此输出相同的“随机”值。因此,所有气球对象最终都具有相同的坐标。尝试在类级别创建一个单独的static
Random实例。
来自https://msdn.microsoft.com/en-us/library/h343ddh9(v=vs.110).aspx
默认种子值是从系统时钟派生的,并且是有限的 解析度。结果,创建了不同的Random对象 通过调用默认构造函数来关闭连续 相同的默认种子值,因此,将产生相同的 随机数集。