Asteroids Clone: Kollision zwischen Schuss und Feind

Status
Nicht offen für weitere Antworten.
M

Marco84

Gast
Hallo zusammen,
ich hab ein Problem. (ach nee, gell :cool: )

Und zwar will bei meinem Spielchen die Kollisionsabfrage zwischen Feind und Schuss nicht so recht klappen. Dazu berechne ich den Abstand zwischen Feind und Schuss und wenn der klein genug ist solls bumm machen.
Manchmal funktioniert das auch und zuerst dachte ich, mein Problem liegt daran, dass ich ja sowohl den neuen Punkt des Feinds als auch den Punkt des Schuss berechnen und deshalb der Abstand fast nie klein genug wird, da sich die beiden Partikel ja gegeneinander bewegen. Deshalb wird sowohl wenn jeder Feind sich bewegt als auch wenn jeder Schuss sich bewegt die Kollision überprüft (trefferPruefen();). Hat aber das Problem nicht komplett gelöst.
Nun hab ich zufällig bemerkt, dass keinesfalls eine Kollision zustande kommt wenn gerade ein neuer Schuss ausgelöst wird. Ich denk mal es liegt daran, dass ich ja in dem Moment in dem ein Schuss erzeugt wird dem Schuss die x- und y-Koordinate des Schiffs zuweise und er diese Punkte zur Berechnung verwendet. Ich hab nun den Treffer vor jedem Schuss-Erzeugen testen lassen, aber das hat nichts gebracht. Auch das Zwischenspeichern der alten Schusskoordinaten in Variablen und dass ich diese dann zur Abstandsberechnung verwendet habe hat leider nichts gebracht.

Inzwischen bin ich allmählich komplett betriebsblind und weiß allmählich nicht mehr weiter. Vieleicht kann mir ja einer von euch helfen oder nen Tip geben.

Im Anhang findet ihr das Applet, arbeiten tu ich mit Eclipse. Das Raumschiff wird mit HOCH/RUNTER-Pfeil hoch und runter gesteuert, gefeuert wird mit der Leertaste, Boni werden mit B abgefeuert.

Anhang hier downloaden
 

LoN_Nemesis

Bekanntes Mitglied
Ich habe die Methode mal geändert, so funktionieren alle Kollisionen. Du darfst sie jetzt allerdings nur noch einmal aufrufen, nachdem alle Bewegungen gemacht wurden, also z.B. nach
Code:
// Bonus abfeuern
if (bonusGefangen == true && bonusFired == true) {
...
}

trefferPruefen();

Hier die geänderte Methode:


Code:
public void trefferPruefen() {
		for (int i = 0; i<feinde.size(); i++)
			for (int j = 0; j<schuesse.size(); j++) {
				Partikel shot = (Partikel)schuesse.get(j);
				Partikel enemy = (Partikel)feinde.get(i);
				xAbstandschuss = enemy.px - shot.px;
				yAbstandschuss = enemy.py - shot.py;
				abstandschuss = Math.sqrt((xAbstandschuss * xAbstandschuss)
						+ (yAbstandschuss * yAbstandschuss));
				System.out.println("SchussAbstand: " + abstandschuss);
				if (abstandschuss < 15) {
					treffer++;
					kleineExplosion.play();
					explosion(enemy);
					enemy.px = 700;
					shot.px = -100;
					if (treffer == (bonusZaehler * 5)) {
						bonusTest = true;
					}
				}
			}
	}


Zudem habe ich noch die explosion() Methode leicht abgeändert, da manchmal Explosionspartikel an falscher Stelle dargestellt wurden (evtl. durch meine Änderung). Du übergibst der Methode also jetzt ein Partikel, welches sagt wo die Explosion stattfinden soll. Vorher musste man sich darauf verlassen, dass feind der letzte abgeschossene Feind war.

Code:
public void explosion(Partikel p) {
		for (int j = 0; j < 5; j++) {
			System.out.println("run(): Explosion");
			explosionspartikel = new Partikel();
			explosionspartikel.px = p.px;
			explosionspartikel.py = p.py;
			explosionspartikel.vx = zufall(-30, 30);
			explosionspartikel.vy = zufall(-30, 30);
			explosionspartikel.ax = 0;
			explosionspartikel.ay = (float) 9.81;
			explodiert.add(explosionspartikel);
		}
	}

In public void kollisionPruefen() musst du dann auch den Aufruf von explosion(); zu explosion(feind); ändern.

Ein letzter Hinweis noch:

Code:
if (((Partikel) feinde.get(feinde.size() - 1)).px > 400)

Die Zeile solltest du abändern, denn wenn keine Feinde da sind, wirft das eine Nullpointer Exception. Jetzt wo alle Schüsse treffen schafft man das locker mit dauerschiessen :p




P.S.: Das Spiel macht irgendwie Spass, obwohl es so einfach ist. Ich mag die Bonusschüsse ;)

P.S.2: Ich habe noch nie soviele Debuggausgaben gesehen, denk daran die alle zu löschen bevor du das Applet hochlädest, damit steigerst du die Performance sicher um 2000% :p
 
M

Marco84

Gast
Vielen Dank für die schnelle Antwort. Jetzt funktionierts wirklich ausgezeichnet!
Kannst du mir vieleicht noch erklären, was an meiner Version falsch war damit ichs beim nächsten mal selber weis?
 

LoN_Nemesis

Bekanntes Mitglied
Dein Fehler war die zu intensive Benutzung von globalen Variablen. Du hast jedesmal wenn du die "schuesse" Liste durchlaufen bist immer die globale Variable "schuss" für das aktuelle Element benutzt. Und dann wenn du die trefferPrüfen() Methode aufrufst, übergibst du "schuss" nicht, sondern verlässt dich beim Aufruf, dass "schuss" auf das richtige Objekt zeigt. Das geht eben dann schief, wenn du einen neuen Schuss erstellst, weil dann "schuss" auf einen anderen Partikel zeigte oder wenn "feind" plötzlich auf etwas anderes zeigt.

Zudem hast du die Methode jedesmal aufgerufen wenn du einen Schuss bewegt hast und jedesmal wenn du einen Feind bewegt hast. Ich habe die Abfrage so umgebaut, dass jeder Schuss mit jedem Feind gecheckt wird, deswegen musst du die Methode nur noch einmal aufrufen wenn alle Bewegungen gemacht wurden. So wie du es gemacht hast, wäre es auch gegangen, aber nur wenn "feind" und "schuss" jeweils auf das richtige Element zeigen, und das konnte man eben nicht sicherstellen. Wenn du am Ende einfach "jeden mit jedem" überprüfst, kannst du sicher sein, dass eine Kollision auch erkannt wird.

Allgemein könntest du den OOP Gedanken von Java mehr nutzen, du hast nur eine 10 Zeilen Miniklasse und der Rest vom Code ist in der Appletklasse. Falls du das Spiel noch ausbauen willst, kann es sehr schnell unübersichtlich werden. Zum Glück ist der Code vorbildlich kommentiert, weshalb man sich relativ schnell zurechtfindet.
 
M

Marco84

Gast
So, bin nun nach längerer Zeit mal wieder dazu gekommen, ein bisschen weiter zu Programmieren.
Ich hab jetzt mal versucht, ein bisschen mehr OOP in die Sache zu bringen und für jede Partikelart ne eigene Klasse angelegt. Die paint-Methoden hab ich auch schon ausgelagert. Allerdings musste ich feststellen, dass der Code in der Applet-Klasse deshalb nicht wirklich übersichtlicher oder kürzer wird. :(
Was für Methoden sollte ich am besten noch auslagern? Oder geh ich völlig falsch an die Sache ran?
Source gibts wie immer unter http://www.marco-huber.de/uni/oop/source/ die neuste Version zum ausprobieren gibts ein Verzeichnis drüber...
 

LoN_Nemesis

Bekanntes Mitglied
Nein du gehst richtig an die Sache ran, aber du musst das konsequenter machen ;)

Zum Beispiel könntest du eine Klasse SpielLogik erstellen, die alle deine Listen von Schüssen, Feinden und Boni verwaltet. Dann musst du in deiner Applet Klasse in der Hauptschleife quasi nur noch ein paar Methoden aufrufen, etwa in der Art

Code:
while(true) {
     SpielLogik.bewegeFeinde();
     SpielLogik.bewegeSchüsse();
     SpielLogik.bewegeBoni();

     SpielLogik.checkForCollision();

}

Falls dein Spiel dann noch weiter wächst, kannst du die Klasse (falls es Sinn macht) vielleicht auch noch aufsplitten.
 
M

Marco84

Gast
Vielen Dank für Deine Tips, hab mich mal drangesetzt und ne Logik-Klasse angelegt. Is eigentlich mehr ne Methodenklasse geworden. :)

Nun hab ich aber mal wider ein neues Problem. Wollt ein Highscore-System einbaun dass die Higscores in ner txt-datei speichert die im selben Verzeichnis wie das Applet liegt.
Hier mal der code:
Code:
// gibts nen neuen Highscore?
	File datei = new File("highscore.txt");
	public void alterHighscore() throws IOException {
		FileReader fr = new FileReader(datei);
		BufferedReader br = new BufferedReader(fr);
		while (br.ready()) {
			altesLevel = Integer.parseInt(br.readLine());
			alteTreffer = Integer.parseInt(br.readLine());
		}
		br.close();
	}

	public void neuerHighscore() throws IOException {
		if (level == altesLevel) {
			if (treffer > alteTreffer) {
				newHighscore = true;
			}
		}
		if (level > altesLevel) {
			newHighscore = true;
		}
		if (newHighscore == true) {
			FileWriter fw = new FileWriter(datei);
			BufferedWriter bw = new BufferedWriter(fw);
			bw.write((new Integer(level)).toString());
			bw.newLine();
			bw.write((new Integer(treffer)).toString());
			bw.flush();
			bw.close();
		}

	}
Mein Problem ist der Zugriff auf die Datei!
Mach ich das so wie oben im Code bekomm ich, wenn ich das Applet lokal ausführ keinen Fehler, wenn ich das Applet aber aufn Server hochlad und dann ausführ bekomm ich ne NullPointerException weil er die Datei nicht findet.
Ich hab mich schon ein paar mal umgeschaut und dabei eigentlich die richtige Methode gefunden, aber da schreibt mir Eclipse immer den Fehler an, dass der Konstructor File(URL) nicht definiert wäre, was ja laut API auch stimmt :):
Code:
 File datei = new File (new URL(getDocumentBase(), "highscore.txt"))
Nun, weiß ich nicht mehr weiter :( aber Ihr könnt mir ja sicher helfen :)
 
M

Marco84

Gast
Falls es wen interessiert, bzw für andere Programmieranfänger die vor dem gleichen Problem stehen: ich hab mein Problem gelöst! Hab das ganze jetzt mit Hilfe eines kleinen PHP-Skripts gelöst.

Hab im Internet (http://forum.developers-guide.net/showthread.php?t=3291) diese Klasse gefunden:
Code:
import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.URL;

import java.net.URLConnection;

/**
 * 
 * PhpPostConnect.java
 * 
 * This class can represant a connection to an PHP-Site
 * 
 * to send the side data via "POST" and get Data from
 * 
 * the side which will be written by side with "echo"
 * 
 * @author sparrow
 * 
 */

public class PhpPostConnect {

	/** Contains the URL to the PHP-Script */

	private URL sitepath;

	/** The Connection to the URL */

	private URLConnection con;

	/**
	 * 
	 * Empty construct, you must set the URL of the
	 * 
	 * target before you start to send and read data
	 * 
	 */

	public PhpPostConnect() {

	}

	/**
	 * 
	 * Construct which also define the targed URL
	 * 
	 * @param sitepath
	 *            The URL to the target PHP-Script
	 * 
	 */

	public PhpPostConnect(URL sitepath) {

		this.sitepath = sitepath;

	}

	/**
	 * 
	 * Set the URL to the target PHP-Script
	 * 
	 * @param sitepath
	 *            The URL to the target PHP-Script
	 * 
	 */

	public void setSitePath(URL sitepath) {

		this.sitepath = sitepath;

	}

	/**
	 * 
	 * To get the target-URL
	 * 
	 * @return The URL to the target PHP-Script
	 * 
	 */

	public URL getSitePath() {

		return this.sitepath;

	}

	/**
	 * 
	 * Sending data to the target-URL
	 * 
	 * @param data
	 *            The data which should be send
	 * 
	 * @throws IOException
	 * 
	 */

	public void send(String data) throws IOException {

		if (con == null) {

			con = sitepath.openConnection();

		}

		if (con.getDoOutput() == false) {

			con.setDoOutput(true);

		}

		OutputStream out = con.getOutputStream();

		out.write(data.getBytes());

		out.flush();

	}

	/**
	 * 
	 * Reading incoming data from the target-URL
	 * 
	 * @return The incoming data
	 * 
	 * @throws IOException
	 * 
	 */

	public String read() throws IOException {

		if (con == null) {

			con = sitepath.openConnection();

		}

		InputStream in = con.getInputStream();

		int c = 0;

		StringBuffer incoming = new StringBuffer();

		while (c >= 0) {

			c = in.read();

			incoming.append((char) c);

		}

		return incoming.toString();

	}

}
dazu dann noch diese Methoden:
Code:
int altesLevel;

	int alteTreffer;

	String alterString;

	String[] alterString2;

	boolean newHighscore = false;
	public void alterHighscore() throws IOException {
		try {
			URL url = new URL("http://www.XXX.de/XXX/highscorelesen.php");
			PhpPostConnect con2 = new PhpPostConnect(url);
			try {
				con2.send("los=gehts");
				alterString = con2.read();
				// System.out.println(alterString+"!");
			} catch (IOException e) {
				e.printStackTrace();
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		alterString2 = alterString.split("a\r\n");
		// System.out.println(alterString2[0]+": 0! "+alterString2[1]+": 1! ");
		altesLevel = Integer.parseInt(alterString2[0]);
		alteTreffer = Integer.parseInt(alterString2[1]);
	}

	public void neuerHighscore() throws IOException {
		if (level == altesLevel) {
			if (treffer > alteTreffer) {
				newHighscore = true;
			}
		}
		if (level > altesLevel) {
			newHighscore = true;
		}
		if (newHighscore == true) {
			// System.out.println("neuer Highscore: true");
			try {
				URL url = new URL("http://www.XXX.de/XXX/highscoreschreiben.php");
				PhpPostConnect con = new PhpPostConnect(url);
				// System.out.println("neuer Highscore: verbindung geöffnet");
				try {
					con.send("level=" + level + "&treffer=" + treffer);
					// System.out.println("neuer Highscore: level"+level+" und treffer"+treffer+" gesendet");
					con.read();
				} catch (IOException e) {
					e.printStackTrace();
				}
			} catch (MalformedURLException e) {
				e.printStackTrace();
			}
                        newHighscore = false;
		}

	}
dieses PHP-Skript:
highscorelesen.php
Code:
<?php
    if(strtolower($_SERVER['REQUEST_METHOD']) == 'post') {
		$dateilesen = fopen("/home/httpd/htdocs/marco-huber.de/uni/oop/highscore.txt", "r");
		$zeile = fgets($dateilesen,100);
		echo $zeile;
		$zeile2 = fgets($dateilesen,100);
		echo $zeile2;
        fclose($dateilesen);
    }
?>
highscoreschreiben.php
Code:
<?php
    if(strtolower($_SERVER['REQUEST_METHOD']) == 'post') {
    	$dateischreiben = fopen("/home/httpd/htdocs/marco-huber.de/uni/oop/highscore.txt", "r+");
        foreach($_POST as $key => $value) {
			$schreiben = $value."a\r\n";
			fwrite($dateischreiben, $schreiben);
        }
        fclose($dateischreiben);
    }
?>
und einer highscore.txt die so aussieht:
Code:
1a
0a
wenn jemand fragen dazu hat, kann er mich gerne fragen, die genaue erklärung wie und warum das ganze funktioniert erspar ich mir jetzt mal.

die funktionierende Version gibts wie immer auf www.marco-huber.de/uni/oop, da gibts auch nen link zum quelltext.[/code]
 

Illuvatar

Top Contributor
Ich kriege grade einige NoClassDefFoundErrors.

-- Opera Java Console --

Java vendor: Sun Microsystems Inc.
Java version: 1.5.0_06

type 'h' for help

--
Exception in thread "AWT-EventQueue-4" java.lang.NullPointerException
at Spiel7.paint(Spiel7.java:288)
at Spiel7.update(Spiel7.java:362)
at sun.awt.RepaintArea.updateComponent(Unknown Source)
at sun.awt.RepaintArea.paint(Unknown Source)
at sun.awt.windows.WComponentPeer.handleEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Exception in thread "Thread-24" java.lang.NoClassDefFoundError: Explosionspartikel
at Logik.explosionspartikelErzeugen(Logik.java:141)
at Logik.trefferPruefen(Logik.java:289)
at Spiel7.run(Spiel7.java:122)
at java.lang.Thread.run(Unknown Source)

Das Spiel hängt sich bei dem ersten Treffer auf.
 
M

Marco84

Gast
Hmm, also die erste, die NullPointerException bekomm ich auch, auch wenn ich noch keine Ursache oder gar Lösung dafür weiß.

Aber die NoClassDefFoundError konnt ich leider nicht reproduzieren. Hast Du vieleicht ne Idee woher das kommt?

Was ich allerdings sagen, ist dass der Fehler erst auftritt, seit ich das Highscore-System eingebaut hat. Und wenn ich die Highscore-Methoden nicht aufrufe, dann tritt auch der Fehler nicht mehr auf. Allerdings machen/ändern/beeinflussen die Highscore-Funktionen doch gar nichts an den anderen Funktionen, oder?
 
M

Marco84

Gast
und bei mir kam grad gar kein fehler mehr.... ????

Schön wenn sich solche Probleme von allein lösen:)
 
M

Marco84

Gast
So, hab den Fehler gefunde, hatte einfach ein repaint zu viel. Falls ihr noch Fehler findet, dann schreibt bitte!
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
K javax.sound.sampled.Clip clone() Spiele- und Multimedia-Programmierung 2
X Geometry Wars Clone Problem Spiele- und Multimedia-Programmierung 4
D Problem Mit Miensweeper Clone & rekursive Methode Spiele- und Multimedia-Programmierung 4
L Pacman-Clone Spiele- und Multimedia-Programmierung 77
M Fragen zu meinem Pong-Clone Spiele- und Multimedia-Programmierung 6
M MineSweeper Clone Spiele- und Multimedia-Programmierung 18
M Sokoban Clone Spiele- und Multimedia-Programmierung 9
B Kollision Spiele- und Multimedia-Programmierung 5
A Kollision funktioniert nicht richtig bei zu schneller Geschwindigkeit des Spielers Spiele- und Multimedia-Programmierung 0
N Kollision von zwei ImageIcons Spiele- und Multimedia-Programmierung 8
D Kollision funktioniert unten aber nicht oben Spiele- und Multimedia-Programmierung 4
J Kollision (libgdx) Spiele- und Multimedia-Programmierung 2
S Kollision Spiele- und Multimedia-Programmierung 2
J Kollision genau erkennen mit intersects Spiele- und Multimedia-Programmierung 27
K a* kollision der einheiten Spiele- und Multimedia-Programmierung 3
S Probleme bei Breakout - Brick kollision Spiele- und Multimedia-Programmierung 2
F Rechteck Kollision Spiele- und Multimedia-Programmierung 10
H 2- D Kollision Spiele- und Multimedia-Programmierung 14
C Zeldaklon Problem mit Wand-Kollision Spiele- und Multimedia-Programmierung 8
O Kollision Polygon und Rechteck Spiele- und Multimedia-Programmierung 2
S Pacman Kollision von Münzen und Mauern Spiele- und Multimedia-Programmierung 11
P Gridpane Kollision Spiele- und Multimedia-Programmierung 3
Androbin Kollision zwischen Raster und Nicht-Raster Spiele- und Multimedia-Programmierung 2
L Kollision soll nur an oberer Seite (Breite) möglich sein Spiele- und Multimedia-Programmierung 6
Hercules Kisten Kollision Spiele- und Multimedia-Programmierung 2
S 3D-Kollision mit zwei ArrayLists Spiele- und Multimedia-Programmierung 7
T Pixelgenaue Kollision Spiele- und Multimedia-Programmierung 5
A LWJGL 3D Objekte Kollision Spiele- und Multimedia-Programmierung 3
S Kollision tile-based 2D Plattformer Spiele- und Multimedia-Programmierung 2
D Greenfoot Kollision Spiele- und Multimedia-Programmierung 5
D Kollision verhindern Spiele- und Multimedia-Programmierung 2
R Frage zur Kollision Spiele- und Multimedia-Programmierung 5
Maxim6394 [Java3D] Probleme bei Kollision Spiele- und Multimedia-Programmierung 7
Kr0e Kollision zweier Kugeln... Wo ist Newton ?? Spiele- und Multimedia-Programmierung 9
C Kollision zwischen 2 Kreisen Spiele- und Multimedia-Programmierung 3
Helgon Kollision von jeder Seite des Blocks Spiele- und Multimedia-Programmierung 3
Fab1 Kollision die 100ste Spiele- und Multimedia-Programmierung 5
D Jump'n'run Kollision bei Blöcken Spiele- und Multimedia-Programmierung 10
P PingPong Spiel - Kollision Spiele- und Multimedia-Programmierung 2
C Bitmaske und Kollision Spiele- und Multimedia-Programmierung 2
J Spielprogrammierung mit bewegung und kollision Spiele- und Multimedia-Programmierung 24
S Kollision Kreis Rechteck Spiele- und Multimedia-Programmierung 8
aze Java3D: Gegenstände aufeinander zubewegen ohne Kollision Spiele- und Multimedia-Programmierung 4
baddestpoet pixelgenaue Kollision Spiele- und Multimedia-Programmierung 4
S Kollision in 2D Spiele- und Multimedia-Programmierung 12
B Gedrehte Rechtecke Kollision Spiele- und Multimedia-Programmierung 4
J Kollision mit Block (Wand) Spiele- und Multimedia-Programmierung 11
C Kollision in Java3D Spiele- und Multimedia-Programmierung 4
J Kollision von Objekten Spiele- und Multimedia-Programmierung 7
F Bewegung/Kollision von Objekten auf Tastendruck Spiele- und Multimedia-Programmierung 6
Z Kollision Spiele- und Multimedia-Programmierung 3
F Kollision für Arkanoid Spiele- und Multimedia-Programmierung 2
N Kollision abfragen Spiele- und Multimedia-Programmierung 3
K Sprites / Kollision Spiele- und Multimedia-Programmierung 3
S Jump'n'Run: Probleme mit Kollision Spiele- und Multimedia-Programmierung 13

Ähnliche Java Themen


Oben