2017-01-06 15 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

レンダリングとゲームのロジックは2つの異なるものです。あなたの資産にロジックと描画機能を混在させましたか(この場合、改善を提案するのは苦しいでしょう)。 – Creep

関連する問題