如何随机位置绘制一个精灵10次?

6
我完全是新手,有一个问题想问。我在学校和家里练习了一下,但是我不知道该怎么做。
我的问题是:我想在屏幕上的10个随机位置绘制单个精灵,而不使用特殊的精灵类。我的问题是,它们被绘制后会再次消失。
已解决,感谢所有的帮助!
public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    Texture2D turtleTexture;
    int counter = 0;
    Random randomera = new Random();
    int x;
    int y;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";        
    }

    protected override void Initialize()
    {
        base.Initialize();
    }

    /// <summary>
    /// </summary>
    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        turtleTexture = Content.Load<Texture2D>(@"Images/turtle_50x38");
    }

    protected override void UnloadContent()
    {
    }

    protected override void Update(GameTime gameTime)
    {
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

         /*
         if(counter < 10)
         {
             x = randomera.Next(600);
            y = randomera.Next(400);
            counter++;
         }
         */

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.White);

        spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend);


        if (counter < 10)
        {
            for (int i = 0; i < 10; i++)
            {
                spriteBatch.Draw(turtleTexture, new Vector2(randomera.Next(600), randomera.Next(400)),
                    Color.Black);
                counter++;
            }
        }

        spriteBatch.End();
        base.Draw(gameTime);
    }
}

}


你的意思是在绘制更多精灵时,要保持之前的帧可见吗? - Kendall Frey
你的代码中为什么会有 if(counter < 10),如果之后有一个计数到10的 for 循环呢? - Bartosz
我只想要10个精灵在不同的位置绘制,然后保持在那里。 - GalneGunnar
@Bartosz 我认为如果没有 "if(counter < 10)",循环将会循环10次,然后返回更新,再返回绘制并再次循环10次。 - GalneGunnar
我还要补充一点,就是在你的Draw函数中除了绘制精灵之外,不应该进行任何“处理”代码。这种代码应该放在Update函数中。 - JDB
显示剩余2条评论
3个回答

7

如果您希望精灵在每一帧的随机位置相同,同时仍然清除视口(例如,您可能想渲染其他内容),您只需将每一帧的随机种子重置为相同的值:

protected override void Draw(GameTime gameTime)
{
    randomera = new Random(seed);   
    GraphicsDevice.Clear(Color.White);

    spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend);


    if (counter < 10)
    {
        for (int i = 0; i < 10; i++)
        {
            spriteBatch.Draw(turtleTexture, new Vector2(randomera.Next(600), randomera.Next(400)),
                Color.Black);
            counter++;
        }
    }

    spriteBatch.End();
    base.Draw(gameTime);
}

在你的Initialize()方法中应随机生成种子,之后不应更改。

您也可以使用预定义的坐标初始化列表:

List<Vector2> coords = Enumerable.Range(0, 10).Select(i => new Vector2(randomera.Next(600), randomera.Next(400)).ToList();

并在您的绘图例程中使用此列表:

for (int i = 0; i < 10; i++)
{
    spriteBatch.Draw(turtleTexture, coords[i],
        Color.Black);
}

1
这个在技术上是可行的,但是生成一个包含10个向量的数组并在构造函数中使用它们会更合理吧?从长远来看,这样做还有更易于维护的好处。 - JDB
没错,我正在修改我的答案以反映这一点。现在它也在那里了。我想我只是想成为一个随机种子的聪明人;) - Bartosz
我完全不会选择第一种方法。我无法想象任何情况下这都是一个好主意。第二种方法好多了。将来,更容易控制数组,例如在随机位置启动龟并使其在屏幕上移动等。 - JDB
是的,在某些半程序化方法和场景设置阶段,设置种子可能会很有用,而不是在绘图过程中。 - Bartosz

1

你在你的绘制方法中调用了Clear

GraphicsDevice.Clear(Color.White);

这将清除屏幕。

删除此行,它将保留先前绘制的内容。


这是一个不好的想法。由于您的绘制函数每秒将被调用30次或更多,因此您的屏幕将在极短的时间内填满精灵。 - JDB
@Cyborgx37 我不认为你正确阅读了他的代码。它将绘制10个精灵,然后停止绘制。这修复了他的问题。 - IAmGroot
是的,你说得对......我漏掉了那部分内容。但是从应用程序中删除“Clear”函数仍然是一个糟糕的想法。这违背了XNA游戏的最佳实践,并将阻碍该应用程序的任何未来使用。我认为这不是一个好主意。 - JDB
@Cyborgx37。是的,他所绘制的一切都将是持久的。他需要重新调整他的方法。在启动时初始化坐标是一个好主意,Bartosz已经回答了这个问题,所以我给了他+1。 :) - IAmGroot

1
GraphicsDevice.Clear(Color.White);

这将清除屏幕(意味着之前绘制的任何内容都将被擦除)。包含此语句的Draw函数每秒大约调用30到60次,您的随机数生成器将在每个迭代中获取新值。

在每个Draw迭代中清除屏幕是正确的做法,因此不要在每次调用Draw时选择随机坐标,而是预先确定坐标。更好的方法可能是在构造函数中初始化一个包含10个向量的数组,然后在Draw函数中使用该数组(而不是一遍又一遍地调用randomera.Next())。

编辑:(有关示例,请参见Bartosz答案的后半部分。我目前无法打开我的XNA IDE,因此无法为您编写代码示例。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接