XNA“内存不足异常”设计重播选项

时间:2011-11-09 09:43:16

标签: c# xna

执行此代码时出现“内存不足异常”问题。该代码拍摄主板的快照,并将其存储起来以便稍后重新编译成电影。

如果有另一种方法来重播该字段,我将非常感激,因为现在我必须拍摄电路板然后将其重新编译成avi电影。 请帮忙。

 public class JSTART_Main : Microsoft.Xna.Framework.Game
{
    private GraphicsDeviceManager graphics;
    private SpriteBatch spriteBatch;
    private Texture2D background;
    private Rectangle mainFrame;
    private SpriteFont font;

    private bool finished = false;
    private BackgroundWorker bw = new BackgroundWorker();
    private Navigation navigation;

    public JSTART_Main()
    {
        graphics = new GraphicsDeviceManager(this);
        this.graphics.PreferredBackBufferWidth = 1280;
        this.graphics.PreferredBackBufferHeight = 768;
        navigation = new Navigation();
        navigation.graphics = graphics;
        navigation.window = Window;
        navigation.CreateClasses();

        //this.graphics.IsFullScreen = true;
        Content.RootDirectory = "Content";
        this.IsMouseVisible = true;

        navigation.controls.CreateControls();
        bw.WorkerSupportsCancellation = true;

        bw.DoWork += new DoWorkEventHandler(bw_screenshots);

    }

    protected override void Initialize()
    {
        base.Initialize();
        bw.RunWorkerAsync();         
    }
    void bw_screenshots(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;


            capture();
            capture();

            if ((worker.CancellationPending == true))
            {
                e.Cancel = true;

            }
            else
            {
                bw.Dispose();

            }              
        }
    void capture()
    {

        while (finished == false)
        {              
                count += 1;
                string counter = count.ToString();

                int w = GraphicsDevice.PresentationParameters.BackBufferWidth;
                int h = GraphicsDevice.PresentationParameters.BackBufferHeight;

                //force a frame to be drawn (otherwise back buffer is empty) 
                Draw(new GameTime());

                //pull the picture from the buffer 
                int[] backBuffer = new int[w * h];
                GraphicsDevice.GetBackBufferData(backBuffer);

                //copy into a texture 
                Texture2D texture = new Texture2D(GraphicsDevice, w, h, false, GraphicsDevice.PresentationParameters.BackBufferFormat);
                texture.SetData(backBuffer);                
                    //save to disk 
                    Stream stream = File.OpenWrite(counter + ".jpg");

                    texture.SaveAsJpeg(stream, w, h);
                    stream.Flush();
                    stream.Close();
                    texture.Dispose();

             }

    }
    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        background = Content.Load<Texture2D>("Background");
        mainFrame = new Rectangle(0, 0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);
        font = Content.Load<SpriteFont>("font");

    }

    protected override void UnloadContent()
    {

    }
    int count = 0;

    protected override void Update(GameTime gameTime)
    {

        //if (Keyboard.GetState().IsKeyDown(Keys.Escape))
        //this.Exit();
        foreach (Unit enemy in navigation.players.enemies.Values)
        {
            enemy.EnemyAI(navigation.aiCollision);
        }
        navigation.input.UpdateKeyboard();
        navigation.networking.Receive();
        navigation.players.SpotEnemy();
        navigation.input.UpdateMouse();

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        try
        {
            base.Draw(gameTime);

            spriteBatch.Begin();
            spriteBatch.Draw(background, mainFrame, Color.White);
            spriteBatch.DrawString(font, "X: " + navigation.players.server.pos.X.ToString() + "\nY: " + navigation.players.server.pos.Y.ToString(), new Vector2(22, 22), Color.White);
            spriteBatch.End();
            navigation.players.server.LoadContent(Content);
            navigation.players.server.Draw(spriteBatch, Color.Transparent);
            foreach (MainObject map in navigation.players.map)
            {
                map.LoadContent(Content);
                map.Draw(spriteBatch);
            }

            foreach (Unit enemy in navigation.players.enemies.Values)
            {
                if (navigation.controls.cbxShowEnemies.Checked || enemy.visible == true)
                {
                    enemy.LoadContent(Content);
                    enemy.Draw(spriteBatch, Color.Red);
                }
            }

            foreach (Unit unit in navigation.players.players.Values)
            {
                if (unit != null && unit.visible)
                {
                    unit.LoadContent(Content);
                    unit.Draw(spriteBatch, Color.White);
                }
            }

        }
        catch (Exception )
        { }

    }
}

}

2 个答案:

答案 0 :(得分:3)

如果你能够画一次游戏并登上游戏,你肯定可以再玩一次。您所要做的就是存储每个单元所做的动作,然后重播。

如果您尝试将其保存到avi文件,请考虑将每个帧写入硬盘而不是将其保存在内存中。

答案 1 :(得分:1)

如果您将所有场景帧存储到RAM中,您可能很快就会结束记忆,请尝试进行此计算:

number_of_frame_stored * frame_height* frame_width * 32 = ....

因此,请定期将存储的帧转储到磁盘,并确保释放先前分配的内存(垃圾回收)。

我在你的代码中看到了另一个问题:你在主Draw方法中做了几个LoadContent。磁盘访问可能是一个瓶颈,因此请尝试加载游戏启动时所需的所有内容。