2016-09-11 6 views
0

Ich habe ein Spiel basierend auf einem TOTORAL erstellt, um zu lernen, ich rendere mein Spiel mit renderScreen(), wenn ich mein Fenster auf dem Bildschirm bewegt habe ich diese Ausnahme "Objekt ist derzeit in an anderer Stelle verwenden ". Ich kenne den Grund des Fehlers, aber ich konnte es nicht beheben, da ich nicht weiß, wie das geht. Was kann ich tun? Verzeih mir, wenn die Frage dumm ist.C# Grafikobjekt wird derzeit an anderer Stelle verwendet

engine.cs

//MEMBERS 
public static Graphics drawHandle; 
private Thread renderThread; 

public engine(Graphics g) 
{ 
    drawHandle = g; 
} 
private object bufferLock = new object(); 

public void init() 
{ 
    renderThread = new Thread(new ThreadStart(renderScreen)); 
    renderThread.Start(); 
} 

public void stop() 
{ 
    renderThread.Abort(); 
} 

public static Bitmap frame = new Bitmap(Globals.CANVAS_WIDTH, Globals.CANVAS_HEIGHT); 
Rectangle rect = new Rectangle(0, 0, frame.Width, frame.Height); 

private void renderScreen() 
{ 
    int framesRendered = 0; 
    long startTime = Environment.TickCount; 
    Graphics frameGraphics = Graphics.FromImage(frame); 
    Unit1 unit1 = new Unit1("test1"); 
    Unit1 unit2 = new Unit1("test2");unit2.x = 250; unit2.y = 100; 

    Globals.GameUnitsList.Add(unit1); Globals.GameUnitsList.Add(unit2); 

    while (true) 
    { 
     //BACKGROUND 
     frameGraphics.FillRectangle(new SolidBrush(Color.DarkBlue),0,0, Globals.CANVAS_WIDTH, Globals.CANVAS_HEIGHT); 

     //BOXES 
     Rectangle rect = new Rectangle(unit1.x, unit1.y, 50, 50); 

     unit1.rectangle = rect; 

     unit1.fillColor = Brushes.LightBlue; 
     unit1.hitPoints = 100; 
     unit1.Health = 10; 

     frameGraphics.FillRectangle(unit1.fillColor, unit1.rectangle); 
     frameGraphics.FillRectangle(unit1.fillColor, unit1.rectangle); 

     Rectangle rect2 = new Rectangle(unit2.x, unit2.y, 50, 50); 
     unit2.rectangle = rect2; 
     unit2.fillColor = Brushes.LightBlue; 
     unit2.hitPoints = 100; 
     unit2.Health = 50; 

     frameGraphics.FillRectangle(unit2.fillColor, unit2.rectangle); 
     frameGraphics.FillRectangle(unit2.fillColor, unit2.rectangle); 

     //HEALTH BAR 
     HealthBar hb = new HealthBar(); 
     hb.barColor = Brushes.YellowGreen; 
     hb.damageColor = Brushes.Red; 
     frameGraphics.FillRectangle(hb.damageColor, hb.Draw(unit1, unit1.x, unit1.y)[1]); 
     frameGraphics.FillRectangle(hb.barColor, hb.Draw(unit1, unit1.x, unit1.y)[0]); 
     HealthBar hb2 = new HealthBar(); 
     hb2.barColor = Brushes.YellowGreen; 
     hb2.damageColor = Brushes.Red; 
     frameGraphics.FillRectangle(hb2.damageColor, hb2.Draw(unit2, unit2.x, unit2.y)[1]); 
      frameGraphics.FillRectangle(hb2.barColor, hb2.Draw(unit2, unit2.x, unit2.y)[0]); 

     //UNIT NAMES 
     frameGraphics.DrawString(unit1.unitName, new Font("Arial", 24, FontStyle.Bold), Brushes.Yellow, unit1.x + 50, unit1.y + 50); 
     frameGraphics.DrawString(unit2.unitName, new Font("Arial", 24, FontStyle.Bold), Brushes.Yellow, unit2.x + 50, unit2.y + 50); 

     drawHandle.DrawImage(frame, 0, 0); 

     //BENCHMARKING 
     if (Environment.TickCount >= startTime + 750) 
     { 
      framesRendered++; 
     } 

     if (Environment.TickCount>=startTime+1000) 
     { 
      Console.WriteLine("Gomi-Invade Plan Game:"+framesRendered +"fps "+ Environment.TickCount); 
      framesRendered = 0; 
      startTime = Environment.TickCount; 
     } 
    } 
} 

gamewindow.cs

... 
public static GameWindow gameW; 
Game game = new Game(); 
... 
//I have this code inside it but is this wrong ?   
private void canvas_Paint(object sender, PaintEventArgs e) 
{ 
    Graphics g = canvas.CreateGraphics(); 
    game.startGraphics(g); 
} 
... 

game.cs

private engine Gengine; 

public void startGraphics(Graphics g) 
{ 
    Gengine = new GomiEngine(g); 
    Gengine.init(); 
} 

public void stopGame() 
{ 
    Gengine.stop(); 
} 
+0

_Graphics g = canvas.CreateGraphics(); _ Dies ist in der Tat falsch. Sie haben das gültige Graphics-Objekt in den PainArgs: 'e.Graphics'. Beachten Sie, dass Sie es zum Zeichnen weitergeben können, aber Sie sollten es nicht für die spätere Verwendung speichern oder zwischenspeichern! Stattdessen müssen Sie das Paint-Ereignis auslösen, wenn neue Daten gezeichnet werden müssen! Außerdem mischen Sie das Zeichnen auf ein Control im Paint-Event und zeichnen es in eine Bitmap. Das mag gut sein, aber Sie müssen verstehen, was Sie tun !! – TaW

Antwort

0

Sie nicht Bildschirm machen kann i In Ihrem eigenen Thread, müssen Sie in Invoke Invalidate aufrufen, die Windows-Nachricht in Windows-Meldungsschleife, die auf Hauptthread verarbeitet werden wird Enqueue.

private void DoWorkInThread(object sender, EventArgs e) 
{ 
    while (true) 
    { 
     lock(this) 
     { 
       //update member properties 
     } 

     if (this.InvokeRequired) 
      this.Invoke((MethodInvoker)delegate void() 
      { 
       //this.Invalidate(); //if you don't need to render every frame, invalidate is better then refresh 
       this.Refresh(); //call refresh for immediate update 
      }); 
    }  
} 

protected override void OnPaint(PaintEventArgs e) { 
    base.OnPaint(e); 
    lock(this) 
    { 
     //read your member which are modifies by the thread 
    } 
    //do rendering 
    e.Graphics.Draw(...); 

}

Verwandte Themen