2016-01-09 2 views
1

Из того, что я видел в других вопросах, мне кажется, что я создаю новый материал в своем коде для рисования, который займет много памяти, но просматривает другой код. Я использую как ссылка, я не уверен, где проблема.C# XNA Out of Memory Исключение при попытке рисования

namespace Crucible 
{ 
    public class Crucible : Microsoft.Xna.Framework.Game 
    { 
     GraphicsDeviceManager graphics; 
     SpriteBatch spriteBatch; 
     //Drawing vars 
     public int renderLeft; 
     public int renderRight; 
     public int renderUp; 
     public int renderDown; 
     public Tile currentTile; 
     public Rectangle target; 
     public Rectangle source; 
     public Color tint; 
     public Texture2D img; 
     // 
     public static int baseTileWidth = 16; 
     public static int baseTileHeight = 16; 
     public static int mapWidthTile = 8400; 
     public static int mapHeightTile = 2400; 
     public static int mapWidthPixel = 8400 * baseTileWidth; 
     public static int mapHeightPixel = 2400 * baseTileHeight; 
     public static int screenWidth; 
     public static int screenHeight; 
     public static Player mainPlayer; 
     Tile[,] worldTilesFor; //Foreground Tiles 
     Tile[,] worldTilesBack; //Foreground Tiles 

     Texture2D coalOreSprite; 
     Texture2D dirtSprite; 

     public Crucible() 
     { 
      graphics = new GraphicsDeviceManager(this); 
      Content.RootDirectory = "Content"; 
      graphics.PreferredBackBufferHeight = 1080; 
      graphics.PreferredBackBufferWidth = 1920; 
     } 

     protected override void Initialize() 
     { 
      mainPlayer = new Player("tim", 1); 
      worldTilesFor = new Tile[8400,2400]; 
      worldTilesBack = new Tile[8400, 2400]; 
      for (int i = 0; i < worldTilesFor.GetLength(0); i++) 
      { 
       for (int j = 0; j < worldTilesFor.GetLength(1); j++) 
       { 
        worldTilesFor[i, j] = new Tile(0,i,j); 
        if (j >= 1200) 
        { 
         worldTilesFor[i, j].tileID = 1; 
        } 
       } 
      } 
      for (int i = 0; i < worldTilesBack.GetLength(0); i++) 
      { 
       for (int j = 0; j < worldTilesBack.GetLength(1); j++) 
       { 
        worldTilesBack[i, j] = new Tile(0, i, j); 
        if (j < 1200) 
        { 
         worldTilesFor[i, j].tileID = 1; 
        } 
       } 

      } 
      screenWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width; 
      screenHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height; 
      base.IsMouseVisible = true; 
      base.Initialize(); 
     } 

     protected override void LoadContent() 
     { 
      spriteBatch = new SpriteBatch(GraphicsDevice); 
      coalOreSprite = this.Content.Load<Texture2D>("Tile_coal ore"); 
      dirtSprite = this.Content.Load<Texture2D>("Tile_Dirt"); 
     } 

     protected override void UnloadContent() 
     { 
     } 


     protected override void Update(GameTime gameTime) 
     { 
      if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 
       this.Exit(); 
      renderLeft = (int)Math.Floor(mainPlayer.position.X) - (screenWidth/2); 
      if (renderLeft < 0) 
      { 
       renderLeft = 0; 
      } 

      renderRight = (int)Math.Ceiling(mainPlayer.position.X) + (screenWidth/2); 
      if (renderRight > mapWidthPixel) 
      { 
       renderRight = mapWidthPixel; 
      } 

      renderUp = (int)Math.Floor(mainPlayer.position.Y) - (screenHeight/2); 
      if (renderUp < 0) 
      { 
       renderUp = 0; 
      } 

      renderDown = (int)Math.Floor(mainPlayer.position.Y) + (screenHeight/2); 
      if (renderDown > mapHeightPixel) 
      { 
       renderDown = mapHeightPixel; 
      } 

      base.Update(gameTime); 
     } 


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

      spriteBatch.Begin(); 

      for (int i = renderLeft; i < renderRight; i++) 
      { 
       for (int j = renderUp; j < renderDown; j++) 
       { 
        currentTile = worldTilesBack[i/16, j/16]; 
        DrawTile(currentTile); 
       } 
      } 
      for (int i = renderLeft; i < renderRight; i++) 
      { 
       for (int j = renderUp; j < renderDown; j++) 
       { 
        currentTile = worldTilesFor[i/16, j/16]; 
        DrawTile(currentTile); 
       } 
      } 


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

     public void DrawTile(Tile tileIn) 
     { 
      switch (tileIn.tileID) 
      { 
       case 1: 
        img = dirtSprite; 
        break; 
       default: 
        img = dirtSprite; 
        break; 
      } 

      if (tileIn.foreground) 
      { 
       tint = Color.White; 
      } 
      else 
      { 
       tint = Color.Gray; //tint background objects grey 
      } 
      spriteBatch.Draw(dirtSprite, new Rectangle((int)(tileIn.posX * baseTileWidth - mainPlayer.position.X + screenWidth/2), (int)(tileIn.posY * baseTileHeight - mainPlayer.position.Y + screenHeight/2), baseTileWidth, baseTileHeight), new Rectangle?(new Rectangle(tileIn.frameX * 16, tileIn.frameY * 16, 16, 16)), tint); //error is thrown here at the source rectangle 
     } 
    } 
} 

Любая помощь или рекомендации относительно того, что вызывает ошибку, были бы весьма полезны.

ответ

0

Это ваши worldTilesFor и worldTilesBack массивы. Вы не показываете, как выглядит класс Tile, но даже если предположить, что каждый Tile содержит 100 байт данных, что, по-моему, маловероятно, это 8400 * 2400 = 20 160 000 экземпляров Tile * 100 байт, около 2 гигабайт бара PER ARRAY, 4 для обоих из них.

Я предполагаю, что вы храните свою карту. Вам понадобится меньшая карта, или вам понадобится какой-то способ виртуализации вашей карты, сохранив ее на диске и загрузив ее в куски по мере необходимости.

+0

Я думал, что это будет проблема, каждый класс плитки составляет около 5 байт прямо сейчас. Спасибо за совет. –

+0

Имейте в виду, что даже полностью пустая ссылка на объект занимает 8 байтов в операционных системах x64 и 4 на x86. С массивами, объявленными этим размером, даже до создания экземпляров 'Tile', вы используете значительный объем памяти. –

+0

Это интересно для меня как для поиска кода из игры, которую я декомпилировал, он создает и обрабатывает один и тот же массив (и больше тонны) с небольшим количеством проблем –