Ratlos^10

Aloha.

Also, ich hab da ein Problemchen. Aber erstmal zu meinem System:

Ubuntu 9.10 64bit mit jdk6_0_0 64bit aus den Repos.
Eclipse 64bit.

So, ich programmierte ein Spiel, lief bei mir auch mehr oder weniger gut. Öfters ein paar Freezes, aber damit kann man als Anfänger ja Leben :slight_smile:

Nun, das eigentlich große Problem ist, das mein Spiel ein Projekt für die Schule ist, das morgen abgegeben wird.

Ich schickte es also zu mehreren Leuten, damit die testen können, wie es so läuft. Die Systeme + Problem:

Windows XP 32bit: Frame öffnet sich, Close-Button und Catch_it Label werden gezeichnet, sonst nichts jre6-?.

Windows Vista 32bit: Spiel läuft so wie bei mir ohne Probleme - jre6-?

Windows 7 64bit: Bei mir, jdk6-18 läuft es wie auf Ubuntu, also ohne Probleme. Bei einem Kumpel wird die Main-Class nicht gefunden - jre6-14.

Ubuntu 9.10 64bit: Spiel läuft so wie es soll.

So, nun weiß ich einfach nicht an was es liegen könnte. Anfangs dachte ich, dass, weil ich es auf einem 64bit System kompilierte, es unter 32bit Systemen nicht funkionieren kann. Dann hab ichs auf meinem Schulrechner kompiliert (32bit) und es trat der gleiche Fehler auf. Also Frame gezeichnet, sonst nichts.

Ich bin total ratlos…kann mir jemand helfen? :frowning:

Hier der Code (ist einigermaßen „viel“ (für mich zumindes^^) , und nicht gerade das Beste was man so rauskramen kann. Aber was nicht ist kann ja noch werden :slight_smile: )

GUI

Control

Data

Hmja, der Klassiker: Man sollte NIE auf einer Component ‘getGraphics’ aufrufen (wenn man nicht ganz genau weiß, was man da tut).

Dazu kommen noch einige … Schwierigkeiten was Threads angeht. (Swing-Components sollten NUR auf dem Event-Dispatch-Thread verändert werden). Und wenn eine Methode wie

    private void delay(int pDelay)  //Erzeugt eine Verz?gerung.
    {
        long time = System.currentTimeMillis();         //Gibt die vergange Zeit seit 1970 in ms zur?ck.
        long timeDelta = System.currentTimeMillis();

        while(timeDelta != (time + pDelay))         //Solange das Zeit-Delta ungleich pDelay ist-
        {
            timeDelta = System.currentTimeMillis(); //wird das Zeit-Delta neu bestimmt.
        }
    }

funktioniert, dann ist das Glück. Das setzt nämlich voraus, dass genau die richtige Millisekunde getroffen wird. Wenn im gleichen Moment eine E-Mail ankommt, und der Computer meint, dieses kleine Info-Fenster da unten rechts einzublenden wäre wichtiger, als
timeDelta = System.currentTimeMillis();
auszuführen, läuft die Schleife in ewig weiter. (Oder zumindest sehr lange ;))

ETWAS abschwächen könnte man dieses Problem zwar durch
while(timeDelta < (time + pDelay)) statt
while(timeDelta != (time + pDelay))
aber diese delay-Methode sollte wohl ohnehin bestenfalls aus einem

    private void delay(int pDelay)  //Erzeugt eine Verz?gerung.
    {
        try
        {
            Thread.sleep(pDelay);
        }
        catch (InterrupedException e)
        {
            System.err.println("Thread was interrupted");
            Thread.currentThread().interrupt();
        }
    }

bestehen.

Das taucht noch an anderes Stellen auf. Auch so eine Schleife wie

    private void itemFall_X() //Bestimmt die neue x-Position des Items auf bestimmter Bahn.
    {
        while(  (item_X != 50) &&   //Solange xItem nicht eine dieser Zahlen ist-
                (item_X != 150) &&
                (item_X != 250) &&
                (item_X != 350) &&
                (item_X != 450))
        {
            item_X = r.nextInt(450); //wird xItem erneut per Random bestimmt.
        }
    }

kann potentiell ewig laufen. Besser wäre ein

    private void itemFall_X() //Bestimmt die neue x-Position des Items auf bestimmter Bahn.
    {
        itemX = 50 + r.nextInt(5) * 100;
    }

Aber das ist auch eher eine Kleinigkeit.

Wenn das möglichst schnell zum laufen gebracht werden muss, solltest du vermutlich eine Klasse erstellen wie

public class PaintPanel extends JPanel
{
    private Data data = ... im Konstruktor übergeben...

    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        
        // Male hier ALLES, d.h. das Spielfeld 
        // wie bei "paintField" aber OHNE die Animation!!!
        // und den Catcher und das Item auf Basis
        // der Daten, die in "data" stehen
    }
}

Erstelle so ein Panel (übergib’ ihm das Data-Objekt) und lege dieses Panel in den JFrame.

Nach jedem Spielschritt kann man dann (auf diesem Panel oder dem Frame) “repaint()” aufrufen, um den neuen Zustand zu zeichnen.

Die hübsche Animation beim Malen des Spielfeldes da jetzt einzubauen wäre etwas frickelig, und in Anbetracht der knappen Zeit wenig ratsam.

Vielleicht gibt’s noch ein paar Stolpersteine, ich schau’ heut abend vielleicht nochmal hier rein.

Danke. Das

while(timeDelta < (time + pDelay))

hat schonmal eine signifikante Verbesserung gebracht! :smiley:

Das ich da nicht alleine drauf gekommen bin…Naja.

Um die anderen Sachen werde ich mich heute noch kümmern. Aber das wichtigste ist das es läuft.

Vielen, vielen Dank!

Ich werde trotzdem noch an dem Spiel weiterarbeiten. Lässt sich ja noch viel aus meinen Fehlern lernen :smiley:

€dit: Ist mir gerade noch eingefallen:

Ich hatte meine alte Version damals per repaint() zeichnen lassen. also in einer while(true) schleife eines neuen Threads. Das Resultat war ein mächtiges flimmern des Bildes. War kaum spielbar.

€dit2:

Ich werde den Quelltext erstmal morgen so abgeben wie er ist. Natürlich mit der Verbesserung die das Spiel jetzt „funktionsfähig“ macht.

Der Grund:

Mir ging es nur das Spiel zum laufen zu bekommen. Mir ist es wichtig das erstmal so viel wie möglich von mir kommt. Also Quelltextmäßig. Ich muss den Text ja noch der Klasse präsentieren, und wenn ich da schnell was verbesser von dem ich keine Ahnung hab, dann steh ich ja doof da :slight_smile:

Danke nochmal!
Ich mach mich dann morgen/übermorgen an das Verbessern.

Falls du/ihr noch tipps haben solltet, ich nehm sie gerne an, aber dann bitte mit Erklärung. Es reicht auch ein Link, oder nur die Aufforderung zur Suche :slight_smile:

€dit3:

Ok, ich hab mich dazu umentschieden alle deine Verbesserungen umzusetzen. Außer die Letzte, mir der neuen Klasse.

PS:

	{				
		while(	(item_X != 50) &&	//Solange xItem nicht eine dieser Zahlen ist-
				(item_X != 150) &&
				(item_X != 250) &&
				(item_X != 350) &&
				(item_X != 450))	
		{			
			item_X = 50 + r.nextInt(50) * 100; //wird xItem erneut per Random bestimmt.			
		}
	}```

Hab ich so gelöst. Da, wenn keine Bedingungen angegeben wird, item_X bei einem aufruf immer ein neuer Wert gegeben wird, und das item dann nicht auf einer Bahn "fällt".

Außerdem hab ich mir gedacht das ich die ganzen Positionen ja auch per Array bestimmen könnte.

Das Flackern kann gut durch das getGraphics gekommen sein.

Wenn’s so reicht, OK, aber für alles weitere mal einen Blick in
http://java.sun.com/products/jfc/tsc/articles/painting/ und
http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html
werfen :slight_smile:

Das letzte war vor dem letzen edit - also, die Begründung für die while-Schleife leuchtet mir jetzt noch nicht ein. Es soll doch wenn diese funktion aufgerufen wird, zufällig 50, 150 … oder 450 zurückgegeben werden, oder? :confused:

Ich habe getGraphics() aus meinem jetzigen Code entfernt. Und ändern tut sich dadurch eigentlich…nichts.

Das flackern war auf das repaint() bezogen :slight_smile:

Die while-Schleife wir in Control durchgehen aufgerufen. Naja, eig. müsste es ja keine while-Schleife sein, reicht ja auch ein if-Abfrage. Aber eine Abfrage muss drinn sein, da sonst item_X jedes mal wenn itemFall_X aufgerufen wird, einen neuen Wert bekommt. Wenn die Abfrage drinn ist, wird kein neuer Wert zugewiesen. Ist ein wenig verwirrend, und nicht ganz sinnvoll, ich weiß :smiley:

Ändern tut sich dadurch spätestens dann was, wenn du den Frame MIT getGraphics mal nicht auf undecorated setzt, und dann die Größe änderst: Das schon gemalte verschwindet. Das passiert auch, wenn man den Frame minimiert und wieder vergrößert, oder ein anderes Fenster vor den Frame zieht und wieder wegnimmt.

Glaub’ mir: getGraphics auf einer Component ist nicht gut :wink:

Das mit der while-Schleife… joa, wenn das funktioniert klingt das erstmal nach Zufall. Ich müßte es jetzt nochmal genau nachvollziehen, aber eigentlich muss (oder sollte) ja NUR ein neuer, zufälliger X-Wert verwendet werden, wenn auch ein neuer Block entsteht. Also, eigentlich sollte die Funktion vermutlich nicht bei jedem Schritt aufgerufen werden, sondern immer nur, wenn ein neuer Block eingefügt werden soll…

Hm, das mit dem verschwinden ist mir nicht sonderlich aufgefallen, da das Spielvergnügen entweder so kurz ist das kein anderen Fenster drüber kommt, oder es erst garnicht gestartet wird :slight_smile:

Ja, die Methode ist etwas ungünstig platziert und verwendet. Ich ändere das noch um, keine Sorge :smiley:

€dit:

Änderung:

itemFall_X() hat nurnoch eine Zeile.

itemFall_X() wird nurnoch in charge() aufgerufen.

Somit hat sich das Problem erledigt :slight_smile:

Was mir aufgefallen ist bei meinem Spiel:

Das Item welches runterfällt flackert auf meinem Rechner ziemlich stark.
Auf dem Schulrechner flackert es garnicht bis sehr schwach.

An was könnte das liegen? :-/

PS: Das Programm + Vortrag ergaben 15 Punkte. Danke nochmal für die schnelle Hilfe :smiley:

[QUOTE=TRiBLy]
PS: Das Programm + Vortrag ergaben 15 Punkte. Danke nochmal für die schnelle Hilfe :D[/QUOTE]

Hausaufgabe? Dann verschieb ich das mal in das entprechende Forum.
In Zukunft gleich in die richtige Kategorie posten.:wink:

Naja…es ist eine GFS gewesen. Aber da ich ja eh noch weiter daran arbeite ist es ja auch keine Hausaufgabe. So ein Zwischending eher :slight_smile:

Kannst ja ggf. nochmal die letzte version posten, vielleicht findet man dann auch noch den Grund für das Flackern raus…