2014-01-14 5 views
1

У меня есть изометрический механизм плитки, написанный в XNA (Monogame). Он может только рисовать поверхность плитки. Но когда у меня большая карта (например, 50х50 плит), то она очень медленная (около 15 FPS). Когда у меня есть маленькая карта (например, 10х10 плиток), чем обрамление кадра (60 FPS).Оптимизация двигателя изометрической плитки для лучшего FPS

Я пытаюсь найти способ оптимизации моего кода, но я понятия не имею, как это сделать.

Это мой код:

using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Graphics; 
using Microsoft.Xna.Framework.Input; 
using Microsoft.Xna.Framework.Input.Touch; 
using System; 

namespace IsoEngine 
{ 
    public class Game1 : Game 
    { 
     GraphicsDeviceManager _graphics; 
     SpriteBatch _spriteBatch; 

     Texture2D Tile1; 
     Texture2D Tile2; 
     MouseState mouseState; 
     bool isMousePressed = false; 

     int[,] map = { {1, 1, 1, 1}, 
         {1, 0, 0, 1}, 
         {1, 0, 0, 1}, 
         {1, 1, 1, 1} }; 

     int tileWidth = 64; 
     int tileHeight = 32; 
     Vector2 scrollSpan = new Vector2(0, 0); 
     Vector2 mouseDragPos = new Vector2(0, 0); 

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

     protected override void Initialize() 
     { 
      base.IsMouseVisible = true; 
      base.Initialize(); 
     } 

     protected override void LoadContent() 
     { 
      _spriteBatch = new SpriteBatch(GraphicsDevice); 

      Tile1 = Content.Load<Texture2D>("1"); 
      Tile2 = Content.Load<Texture2D>("2"); 
     } 

     protected override void UnloadContent() 
     { 
     } 

     protected override void Update(GameTime gameTime) 
     { 
      mouseState = Mouse.GetState(); 

      if (mouseState.LeftButton == ButtonState.Pressed && !isMousePressed) 
      { 
       isMousePressed = true; 
       mouseDragPos.X = mouseState.X; 
       mouseDragPos.Y = mouseState.Y; 
      } 

      if (mouseState.LeftButton == ButtonState.Pressed && isMousePressed) 
      { 
       if (mouseDragPos.X < mouseState.X) 
       { 
        scrollSpan.X += mouseState.X - mouseDragPos.X; 
        mouseDragPos.X = mouseState.X; 
       } 
       if (mouseDragPos.X > mouseState.X) 
       { 
        scrollSpan.X -= mouseDragPos.X - mouseState.X; 
        mouseDragPos.X = mouseState.X; 
       } 
       if (mouseDragPos.Y < mouseState.Y) 
       { 
        scrollSpan.Y += (mouseState.Y - mouseDragPos.Y) * 2; 
        mouseDragPos.Y = mouseState.Y; 
       } 
       if (mouseDragPos.Y > mouseState.Y) 
       { 
        scrollSpan.Y -= (mouseDragPos.Y - mouseState.Y) * 2; 
        mouseDragPos.Y = mouseState.Y; 
       } 
      } 

      if (mouseState.LeftButton == ButtonState.Released && isMousePressed) 
       isMousePressed = false; 

      base.Update(gameTime); 
     } 

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

      _spriteBatch.Begin(); 
      DrawMap(); 
      _spriteBatch.End(); 

      base.Draw(gameTime); 
     } 

     private void DrawMap() 
     { 
      for (int osaY = 0; osaY < map.GetLength(0); osaY++) 
      { 
       for (int osaX = 0; osaX < map.GetLength(1); osaX++) 
       { 
        int x = osaX * 32; 
        int y = osaY * 32; 

        Texture2D thisTile = Tile1; 

        if (map[osaY, osaX] == 0) 
         thisTile = Tile1; 

        if (map[osaY, osaX] == 1) 
         thisTile = Tile2; 

        PlaceTile(thisTile, CartToIso(new Vector2(x, y)), new Vector2(osaX, osaY)); 
       } 
      } 
     } 

     public void PlaceTile(Texture2D tileImage, Vector2 tilePos, Vector2 tileCoords) 
     { 
      _spriteBatch.Draw(tileImage, new Vector2(tilePos.X - (tileWidth/2), tilePos.Y - tileHeight), Color.White); 
     } 

     public Vector2 CartToIso(Vector2 cartCoords) 
     { 
      Vector2 isoCoords = new Vector2(0, 0); 

      isoCoords.X = (cartCoords.X + scrollSpan.X) - cartCoords.Y; 
      isoCoords.Y = (cartCoords.X + scrollSpan.Y + cartCoords.Y)/2; 

      return isoCoords; 
     } 

     public Vector2 IsoToCart(Vector2 isoCoords) 
     { 
      Vector2 cartCoords = new Vector2(0, 0); 

      cartCoords.X = (2 * isoCoords.Y + isoCoords.X - scrollSpan.X - scrollSpan.Y)/2; 
      cartCoords.Y = (2 * isoCoords.Y - isoCoords.X + scrollSpan.X - scrollSpan.Y)/2; 

      return cartCoords; 
     } 
    } 
} 

ответ

0

Как правило, для увеличения Performace избежать создания unessesary объектов и не делает все, что вы не должны. Например, вы создаете одну бесполезную локальную текстуру в DrawMap(), также для одиночного вызова метода PlaceTile вы создаете 3 новых вектора, тогда как вам нужен one.etc. также обратите внимание, что это только minor улучшения.
Другими способами ускорения могут быть использование буферов (не уверены, что такое значение по умолчанию для XNA)
Но самое главное, распараллеливать, где только можно.

0

Прежде чем делать что-либо еще, профаймируйте свой код и посмотрите, сколько времени тратится. Только тогда вы можете начать оптимизировать

+0

Самое время beeng проводят в PlaceTile(), он потребляет 95% всех потраченных время. – Earlgray

1

Я бы предложил вам взглянуть на ответ, который я написал некоторое время назад, он рисует только одну видимую часть уровня, независимо от того, насколько большой уровень:

Я не копируя и вставляя ответ здесь, как я написал это уже, так пойти и посмотреть на него здесь:

https://gamedev.stackexchange.com/a/29930/16262

+1

Означает ли это, что вы должны были правильно задать вопрос, а не отвечать на него, не более, чем ссылку на отдельный вопрос? – DonBoitnott