Trotz richtiger Daten, falsches Bild wird gezeichnet?!

mavinatic

Bekanntes Mitglied
Hallo Community,

ich bin momentan dabei ein Server-Client Spiel zu schreiben, bis jetzt geht es nur um die Anzeige der Spielerpositionen...

Wenn ich z.B. 3 Spieler hinzufüge, werden alle 3 Spieler auch gezeichnet, das ist kein Problem, jedoch wenn ich dann einen Spieler entferne, wird er immernoch gezeichnet, obwohl die Ausgabe des Arrays bestätigt, dass es dann nur noch 2 Spieler sind!

Was mache ich falsch?


In dieser Datei wird alles gezeichnet:
Java:
package org.game.gui;


import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.net.Socket;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

import org.game.client.DataHandler;
import org.game.client.SharedData;
import org.game.ressource.Player;

public class MainPanel extends JPanel {
	/*
	 * GameInfo
	 */
	private DataHandler handler = null;
	private Player[] currentPlayers = null;
	private SharedData data = null;
	
	/*
	 * Graphical Inits.
	 */
	private Image backBuffer = null;
	Image img = null; // TestImage
	
	public MainPanel(SharedData data, Socket socket) throws Exception
	{
		this.data = data;
		this.handler = new DataHandler(socket, this);
		testPrepare();
		init();
		gameloop();
	}
	
	private void testPrepare() {
		handler.send("POST /createGame?name="+data.getCurrentGameName()+"&maxPlayers=10 URLGS/1.0");
		handler.send("POST /addNewPlayer?playerName="+data.getCurrentPlayerName()+"&playerPositionX=500&playerPositionY=52&game="+data.getCurrentGameName()+" URLGS/1.0");
//		handler.closeConnection(data.getCurrentGameName(), data.getCurrentPlayerName());
	}
	
	/*
	 * Initialisieren
	 * Spielname festlegen
	 * 
	 * Spieler / Position abfragen
	 */
	public void init()
	{
		setDoubleBuffered(false);
		
		try {
			img = ImageIO.read(new File("pic/blue.PNG"));
		} catch(Exception e)
		{
			e.printStackTrace();
		}
		
		handler.recieve();
		handler.send("GET /commonRequest?game=XYZ URLGS/1.0");
		
		//Draw BackBufferImage
		renderScreen();
		//Set BackBuffer to Front
		updateScreen();
	}
	
	private void gameloop()
	{
		Thread loop = new Thread() {
			@Override
			public void run() 
			{
				try
				{
					while(true)
					{
						handler.send("GET /refreshPositionGet?game=XYZ URLGS/1.0");
						renderScreen();
						updateScreen();
						Thread.sleep(1000);
					}
				} catch(Exception e)
				{
					e.printStackTrace();
				}
			}
		};
		loop.start();
	}
	/*
	 * 
	 * 
	 * Graphic Methods
	 * 
	 * 
	 * 
	 */
	public void renderScreen()
	{
		if(backBuffer==null)
		{
			createBackBuffer();
		} else
		{
			Graphics graph = backBuffer.getGraphics();
			
			if(currentPlayers!=null)
			{
				System.out.println(currentPlayers.length);
				for(int i=0;i<currentPlayers.length;i++)
				{
					graph.drawImage(img, currentPlayers[i].getX(), currentPlayers[i].getY(), this);
				}
			}
			
		}		
	}
	
	public void updateScreen()
	{
		Graphics g = getGraphics();
		if(g!=null)
		{
			if(backBuffer!=null)
			{
				g.drawImage(backBuffer, 0, 0, null);
			} else 
			{
				createBackBuffer();
				renderScreen();
			}
		}
	}
	
	private void createBackBuffer() 
	{
		if(backBuffer==null)
		{
			backBuffer = createImage(getWidth(), getHeight());
		} else
		{
			backBuffer = createImage(getWidth(), getHeight());
		}			
	}
	
	
	/*
	 * GETTER & SETTER
	 */
	public void setPlayers(Player[] players)
	{
		this.currentPlayers = players;
	}
	public DataHandler getDataHandler()
	{
		return this.handler;
	}
}

Bei der Console von Eclipse, erkennt man die Zahl 2, welche für aktuelle Spieler steht, jedoch werden immernoch 3 gezeichnet?! Die Zahl 2 kommt vom Server, welche via XML-Daten an den Client schickt.
gsscreenshot01.jpg
 
du malst auf den Bild die neuen Kreise, aber der alte bleibt auch, warum sollte der verschwinden?
fülle das Bild bei jedem Zeichnen intitial mit einem großen weißen Rechteck um zu löschen

auch schön testweise ist nicht zu löschen und nach jeder Sekunde in der Thread-Schleife einen Versatz einzubauen, male jeweils 100 Pixel weiter unten,
dann solltest du zuerst oben die drei Kreise sehen, später in unteren Zeilen nur noch zwei oder ähnliches

--------
ansonsten:

Java:
        if(backBuffer==null)
        {
            backBuffer = createImage(getWidth(), getHeight());
        } else
        {
            backBuffer = createImage(getWidth(), getHeight());
        }
ist ja nicht sehr sinnvolle Unterscheidung..


wichtiger:
streiche updateScreen(), rufe NIE getGraphics() von einer Swing-Komponente auf,
überschreibe die paintComponent-Methode, wie es in jedem Lehrbuch zum Thema steht..
(wie kommt es nur immer wieder zu anderen Varianten?..)
in der paint-Methode male das Bild, wenn nicht vorhanden könntest du auch gar nichts machen, musst nicht unbedingt das Bild anlegen,
im Moment legst du es in updateScreen() evtl. an, malst es dann aber nicht, das bringt ja auch wenig..

um das normale painten zu starten muss in der Schleife repaint() aufgerufen werden,

siehe auch meine beiden Links in
http://www.java-forum.org/awt-swing-swt/124900-thread-zeichnen.html#post809721
immerhin der Thread ist hier ja schon schön gelungen 😉
 
Du hast recht, dass das es keine sinnvolle Unterscheidung war mit der If-Abfrage, aber da habe ich einfach was gelöscht (backbuffer = null);

Warum ist es so schlimm sich mit getGraphics() das Grafik-Objekt zu holen?

Danke für den Tipp 🙂
 
schlecht ist es z.B. weil das normale painten immer noch besteht und dir vielleicht alles löscht, wann immer paint drankommt,
was im Zweifel unvorhersehbar ist,

das ist so als wenn du einen Aufzugssystem nutzt (Swing), dann aber nicht in den normalen Fahrstuhl (paint) einsteigst,
sondern selber da kreuz und quer rumkletterst wie John McClane 😉
 

Zurück
Oben