Verwirrung mit AWT Frame und main Methode

Pincalibur

Mitglied
Hi liebes Forum,

ich versuche eine Spiele Engine für Java zu schreiben.
Dabei möchte ich die Spielszenenverwaltung mit meiner abstrakten Klasse scene lösen.
Erbende Klassen müssen die Methode update implementieren, die bei jedem Durchlauf ausgeführt werden soll.
Dazu gibt es eine Klasse die Global heißt. Sie verwaltet öffentliche Variabeln wie zB Global.scene.
In ihr steht die aktuelle Instanz von den Scene Klassen, die geupdatet wird.
Wird Global.scene auf null gesetzt, soll das Spiel beendet werden.
Funktioniert eigentlich gut, nur wenn ich dann einen AWT Frame einbaue laufe ich auf einen verwirrenden Umstand:
Er durchläuft die Hauptschleife nicht mehr. Gar nicht mehr. :/
Setze ich im Code des AWT Frames Global.scene auf null, reagiert die main Methode nicht mehr drauf.

Hier der src Code:

Java:
public abstract class Main {

	public static void main(final String[] args)
    {
		System.out.print("Starting...\n");
		initiateConfig();
		Global.window.show(true);
		while(true){
			if(Global.scene == null){
				break;
			}
			else
				Global.scene.update();
		}
		System.out.print("Closed.\n");
    }
	
	public static void initiateConfig(){
		//Fenster mit Fenstergröße
		Global.window = new Window(new Size(1280, 800));
		//Startszene
		Global.scene = new Scene_Title();
		//Default Sprache
		Global.language = new Lang_deDE();
	}
	
}

Java:
public class Window extends Canvas {
	
	// Attributes
	private Frame frame;
	private Size size;
	private ArrayList<ImageContainer> imgList;
	
	// Gets & Sets
	public void setImageList(ArrayList<ImageContainer> imageList){
		this.imgList = imageList;
	}
	
	// Constructors
	public Window(){
		init();
	}
	public Window(Size size){
		this.size = size;
		init();
	}
	
	// Methodes
	private void init(){
		frame =   new Frame( "Das Fenster zur Welt" );
		frame.setSize  ( size.getX(), size.getY() );
		frame.addWindowListener(new WindowAdapter() {
	         public void windowClosing(WindowEvent e) {
	        	 Global.scene = null;
	             Global.window.frame.dispose();
	         }
	      });
		System.out.print("Title Screen displays.\nWelcome to the Game.\n");	
	}
	
	public void show(boolean value){
		frame.setVisible  ( value );
	}
	
	public void paint(Graphics g) {
		for(ImageContainer img :imgList)
			g.drawImage(img.getImage(),img.getPosition().getX(),img.getPosition().getY(),this);	
		
	}
}

Java:
public abstract class Scene {
	
	// Attributes
	public int graphic_alpha;
	protected ArrayList<ImageContainer> imgList = new ArrayList<ImageContainer>() ;
	
	//Methods
	public void routine(){
		update();
		draw();
	}
	public abstract void init();
	public abstract void update();
	public abstract void draw();
	protected void addImage(ImageContainer img){
		imgList.add(img);
		Collections.sort(imgList);
	}
	protected ImageContainer getImage(int id){
		return imgList.get(id);
	}
}

Ich hoffe mir kann geholfen werden, warum meine Schleife in main nur durchlaufen wird, wenn ich hinterher nen Debugpunkt drauf mache.
 
Java:
while(true){
        if(Global.scene == null){
            break;
        }
        else
            Global.scene.update();
}

Witzige Idee, die Schleifenbedingung aus dem Schleifenkopf rauszunehmen und dir eine sinnlose Endlosschleife zu basteln.

Wie wärs stattdessen mit

Java:
while(Global.scene != null)
    Global.scene.update();

Zu deinem Problem kann ich leider nichts sagen. Wie kommst du darauf, dass die Schleife nicht mehr durchlaufen wird?
 
Diese While Konstruktion hatte ich vorher auch. Hab sie wegen meines Problems raus genommen um diese Überprüfung besser Debuggen zu können. Eine Endlosschleife ist das nicht.

Zu meinem eigentlichen Problem:
Schließe ich das Frame über den X-Button (Global.scene = null), so wird das Programm nicht beendet, sondern ich sehe im Debugmodus von Eclipse, dass die Java VM noch läuft.
Erst wenn ich einen Breakpoint auf die if-Abfrage in der "Endlosschleife" mache, wird dieser aktiv, läuft die if durch und landet (weil Global.scene == null -> true ergibt) im break.
Er sollte ja eigentlich schon drin landen, bevor ich den Breakpoint setze... Das verwirrt mich.

Edit2: Meine Endlosschleife hab ich auch primär deshalb so gebaut, weil ich beim debuggen sonst direkt auf der Anweisung lande und er OBWOHL Global.scene = null ist, die Schleife weiter ausführt und damit natürlich keine Objektreferenz mehr hat und eine Exception wirft.
Es ist als ob er sie pausiert, wenn das AWT Frame aktiv ist.
Baue ich print anweisungen in das update, sehe ich jedoch, dass sich dort was tut.
 
Zuletzt bearbeitet:
Aktuell macht update nichts.
Dort sollen später die inputs von Tastatur & co und alle Berechnungen rein.

Edit: Danke, dass Canvas wurde noch nicht geaddet. Kein Wunder dass ich noch keine Bilder sehen konnte. Das löst zumindest schon mal ein Problem in der Zukunft 😉
 
Zuletzt bearbeitet:
Eine Endlosschleife ist das nicht.

[OT]Keine "echte" jedenfalls, aber zumindest eine unechte 😉

Ich zitiere dazu mal die Wikipedia:

"Der einfachste Fall einer Endlosschleife wird solange ausgeführt, wie 'true' wahr ist – also für immer. (Es sei denn, es befinden sich innerhalb der Schleife eine oder mehrere break-Anweisungen, dann ist es keine „echte“ Endlosschleife.)"[/OT]
 
Ich habe gerade eine print Anweisung("Running...") in meine update Methode geschrieben und voila. Das Programm beendet sich, wenn Global.scene = null ist.
Wunderlicherweise funktioniert das Ganze nicht mehr, wenn ich einfache Rechenanweisungen(int i = 2; int j = i*2; etc) reinschreibe.

Was ist ein KSKB?
Ich würde auch das Projekt selbst hochladen, hab ich erst gestern angefangen, daher ist es nicht sehr groß.
 
Darum ging es mir auch noch nicht.
Es geht um das Schließen des Frames, die Anwendung gibt der Konsole das "Closed." nicht aus.
-> Die Anwendung läuft noch.

Edit:
Die Bildanzeige funktioniert jetzt ohne Probleme. Das hält mich auch grad nicht auf.
 
Zuletzt bearbeitet:
Bei Nebenläufigkeit solltest du beachten, dass Global.scene ja genau in DEM Augenblick auf null gesetzt werden könnte, wo der Test auf null gerade passiert war -> Global.scene.update() -> NPE
 
Nein, das ist keine Problemlösung, das ist Unterdrückung der Symptome.
Problemlösung wäre z.B. solche Zugriffe richtig zu synchronisieren.

Allerdings ist ja noch nicht gesagt, wo genau die NPE auftritt.
 
ich würde den Zugriff
sychronized machen,
mit Thread.sleep()
etwas zeit für das
Window machen.
update würde ich dann
ziemlich kurz machen
um den EDT nicht zu
blockieren.

Oder eine bessere Idee:
die Scene nicht auf null
setzen sondern eine
boolean-Variable anlegen.

Oder noch besser die
Scene speichern.
 
Ich glaub ich lass das AWT Frame beim close Button einfach die System.exit machen, dann hab ich kein Problem mit der Synchronisation...^^'

Edit: Ausprobiert. Klappt wunderbar. Auch wenn mich interessieren würde, warum ich bei der Ausführung nicht auf die NPE treffe..
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben