2017-01-06 7 views
0

현재 GDI +를 사용하는 2D 게임 엔진에서 작업 중입니다. 모든 것이 매우 원활하게 실행되지만 내 엔진 렌더링 그래픽을 더 빠르게 만들 수있는 몇 가지 사항이 있어야한다는 것을 알고 있습니다.GDI + 게임 엔진 (엔진을 빠르게 실행하려면 어떻게해야합니까?)

현재 800x600 픽셀의 빈 비트 맵을 화면에 렌더링하면 약 130fps가됩니다. 그러나 비트 맵에 800x600 픽셀의 이미지를 그리면 약 70fps가됩니다. 그건 전혀 문제가되지 않습니다. 저는 실제로 결과가 자랑 스럽습니다. 더 좋을 수 있다는 것을 압니다.

엔진을 더 빨리 작동시킬 수있는 방법에 대한 제안이 있다면 궁금한가요?

여기 내 창 클래스에 코드입니다 :

using System; 
using System.Windows.Forms; 
using GameEngine.Graphics; 
using System.Threading; 
using System.Drawing; 

namespace GameEngine.Core 
{ 
    public class Game : Form 
    { 
     // Just a class that checks the fps and such 
     private GameTime gameTime; 
     private GraphicsEngine graphicsEngine; 

     private bool isLoaded = false; 
     private bool isRunning = false; 

     public Game(int width, int height, string title) 
     { 
      this.Width = width; 
      this.Height = height; 
      this.Text = title; 

      this.MaximizeBox = false; 
      this.FormBorderStyle = FormBorderStyle.FixedSingle; 

      this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
      this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 

      this.Paint += Game_Paint; 
      this.FormClosing += Game_FormClosing; 

      gameTime = new GameTime(); 
      graphicsEngine = new GraphicsEngine(this); 

      Show(); 
     } 

     public void Run() 
     { 
      Initialize(); 
      Load(); 

      isRunning = true; 

      while (isRunning && isLoaded) 
      { 
       // Yes I know, this is frowned upon 
       Application.DoEvents(); 

       gameTime.Update(); 

       // Only update if the form is focused and if the GameTime class says we're allowed 
       if (this.Focused && gameTime.Cycled) 
       { 
        BeginUpdate(); 
        UpdateGame(); 
        LateUpdate(); 
        Render(); 
       } 
       else 
       { 
        Thread.Sleep(1); 
       } 
      } 

      Exit(); 
     } 

     public void Exit() 
     { 
      Unload(); 
      this.Close(); 

      // Using console application, so lets exit the console 
      Environment.Exit(0); 
     } 

     private void Initialize() 
     { 
      gameTime.Initialize(); 
     } 

     private new void Load() 
     { 
      isLoaded = true; 
     } 

     private void Unload() 
     { 

     } 

     private void BeginUpdate() 
     { 

     } 

     private void UpdateGame() 
     { 
      this.Title = "FPS: " + gameTime.FPS; 
     } 

     private void LateUpdate() 
     { 

     } 

     Bitmap bmp = new Bitmap("Test.jpg"); 

     private void Render() 
     { 
      // Draw the nice tree to the window 
      graphicsEngine.DrawBitmap(bmp, 0, 0); 

      // Cause the window to redraw it's self 
      this.Invalidate(); 
     } 

     private void Game_Paint(object sender, PaintEventArgs e) 
     { 
      // Lets just make sure once again that we're allowed to draw 
      if (gameTime.Cycled) 
      { 
       // Render the graphics to the screen 
       graphicsEngine.Render(e.Graphics); 
      } 
     } 

     private void Game_FormClosing(object sender, FormClosingEventArgs e) 
     { 
      isLoaded = false; 
     } 

     public string Title 
     { 
      get { return Text; } 
      set { Text = value; } 
     } 
    } 
} 

여기에 그래픽 엔진 클래스입니다 :

using System.Drawing; 
using GameEngine.Core; 
using System.Drawing.Drawing2D; 
using System.Drawing.Text; 

namespace GameEngine.Graphics 
{ 
    public class GraphicsEngine 
    { 
     private Game game; 

     private System.Drawing.Graphics backBuffer; 
     private System.Drawing.Bitmap backBufferBitmap; 

     public GraphicsEngine(Game game) 
     { 
      this.game = game; 

      backBufferBitmap = new Bitmap(800, 600); 
      backBuffer = System.Drawing.Graphics.FromImage(backBufferBitmap); 

      backBuffer.CompositingMode = CompositingMode.SourceOver; 
      backBuffer.CompositingQuality = CompositingQuality.HighSpeed; 
      backBuffer.SmoothingMode = SmoothingMode.None; 
      backBuffer.InterpolationMode = InterpolationMode.Low; 
      backBuffer.TextRenderingHint = TextRenderingHint.SystemDefault; 
      backBuffer.PixelOffsetMode = PixelOffsetMode.Half; 
     } 

     public void Render(System.Drawing.Graphics g) 
     { 
      g.CompositingMode = CompositingMode.SourceCopy; 
      g.CompositingQuality = CompositingQuality.AssumeLinear; 
      g.SmoothingMode = SmoothingMode.None; 
      g.InterpolationMode = InterpolationMode.NearestNeighbor; 
      g.TextRenderingHint = TextRenderingHint.SystemDefault; 
      g.PixelOffsetMode = PixelOffsetMode.HighSpeed; 

      g.DrawImage(backBufferBitmap, new Rectangle(0, 0, game.Width, game.Height), new Rectangle(0, 0, game.Width, game.Height), GraphicsUnit.Pixel); 

      backBuffer.Clear(Color.Black); 
     } 

     public void DrawString(string text, int x, int y) 
     { 
      backBuffer.DrawString(text, SystemFonts.DefaultFont, Brushes.White, x, y); 
     } 

     public void DrawBitmap(Bitmap bitmap, int x, int y) 
     { 
      backBuffer.DrawImage(bitmap, x, y); 
     } 

     public void DrawBitmap(Bitmap bitmap, int x, int y, int width, int height) 
     { 
      backBuffer.DrawImageUnscaled(bitmap, x, y, width, height); 
     } 
    } 
} 
+1

이 코드는 이미 작동중인 코드를 개선하는 데 중점을두고 있으므로 http://codereview.stackexchange.com/에 더 적합하다고 생각합니다. –

답변

0

당신은 당신의 그림 스레드에서 분리 된 논리 스레드의 종류를 운영하려고합니다. 어쩌면 당신의 논리에 잠 들어있는 스레드를 (tick management)로 바꿀 수도 있습니다.

아래 주석에서 묻는 것처럼 다른 스레드에서 UI & 로직을 분리하는 것이 두 작업에서 더 나은 흐름을 갖는 데 도움이 될 수 있습니다. 어려운 부분은 UI와 로직을 동기화 된 상태로 유지하는 것입니다.하지만 UI 속도가 느려지는 메소드/함수의 속도가 느려지지는 않습니다.

+1

실제로 드로잉과 게임 로직을 구분하는 것이 합리적인 일이지만, 동기화 중에는 약간의 동기화가 필요할 수도 있습니다 (업데이트 중에는 게임 상태가 일치하지 않을 수 있습니다). 당신이 당신의 대답을 정교하게 만들 수 있다면 약간의 OP가 그 가치를 보게 될 것입니다. – prof1990

+0

이 방법이 도움이되는 것을 보았습니다. 그러나 코드 자체가 이미 느리게 렌더링되기 때문에 이것이 의미하는 바는 다른 스레드에서 느리게 렌더링된다는 것입니다. –

+0

렌더링 및 게임 로직은 두 가지 다른 점이 있습니다. 자산에 논리 및 드로잉 기능을 혼합 했습니까 (이 경우 제안 된 개선 사항을 적용하는 데 어려움이 있습니까?). – Creep