Kollissionsabfrage Kreise

ML-Deluxe

Mitglied
Hallo,

für mein Spiel benötige ich eine Kollissionsabfrage für zwei Kreise. Dafür hab ich mir eine Methode geschrieben, doch irgendwie will das nicht so wie ich will. Ich berechne den Abstand zwischen den Mittelpunkten beider Kreise und schau dann ob dieser länger ist als beide Radien. Ist der Abstand kürzer sollten die eigentlichen x,y-Koordinaten nicht verändert werden. Allerdings "verhaken" sich die Kreise bei mir, sprich der der Abstand ist kürzer als die Radien, und der Kreis kann deswegen nicht mehr bewegt werden. Ich hoffe das Problem wird bei folgendem Code Ausschnitt klarer.

Die Methode zur Bestimmung ob sich die Kreise schneiden:
Java:
public boolean intersection2Ovals(Ellipse2D.Double oval1, Ellipse2D.Double oval2) {
		double r1 = oval1.getWidth() / 2.0;
		double r2 = oval2.getWidth() / 2.0;
		
		double x1 = oval1.getCenterX();
		double y1 = oval1.getCenterY();
		double x2 = oval2.getCenterX();
		double y2 = oval2.getCenterY();
		
		double a;
		if (x1 < x2) 
			a = x2 - x1;
		else 
			a = x1 - x2;
		
		double b;
		if (y1 < y2) 
			b = y2 - y1;
		else 
			b = y1 - y2;
		
		double c = Math.sqrt(a * a + b * b);
		double diff = c - (r1 + r2);
		Test.mess = "" + diff;
		//System.out.println(diff + "/" + x + "/" + y);
		
		if (diff <= 0.0) 
			return true;
		
		return false;
	}

Die Methode, die die Koordinaten updatet:
Java:
public void update(long timePassed) {
		float xTemp = x, yTemp = y;
		xTemp += vx * timePassed;
		yTemp += vy * timePassed;
		
		if (!intersection2Ovals(Test.tree.getOval(), this.getOval())) {
			x = xTemp;
			y = yTemp;
		}
		a.update(timePassed);
	}

Ich hoffe das Problem ist verständlich dargestellt. Vielleicht sitz ich ja auch nur auf dem Schlauch, aber ich verstehe einfach nicht, wieso "diff" negativ wird.
Bin für alle Anregungen und Kritik dankbar.
 

Marco13

Top Contributor
Was sind denn x und y bei 'update'?

Und nebenbei:
Java:
        ....
        double dx = x1-x2;
        double dy = y1-y2;
        double c = Math.sqrt(dx*dx+dy*dy);
        double diff = c - (r1 + r2);
        Test.mess = "" + diff;
        //System.out.println(diff + "/" + x + "/" + y);
        
        return (diff <= 0.0);
}
 

ML-Deluxe

Mitglied
Was sind denn x und y bei 'update'?

x und y sind die Koordinaten des Sprites, der dazugehörige kreis bewegt sich natürlich immer relativ dazu. Es sollte also so sein, dass wenn sich die Kreise (nach meiner eigenen Methode) schneiden, die x und y werte nicht ändern sollten. Mit Rectangles hat es zumindest funktioniert.




Und nebenbei:
Java:
        ....
        double dx = x1-x2;
        double dy = y1-y2;
        double c = Math.sqrt(dx*dx+dy*dy);
        double diff = c - (r1 + r2);
        Test.mess = "" + diff;
        //System.out.println(diff + "/" + x + "/" + y);
        
        return (diff <= 0.0);
}

Danke :D
 
Zuletzt bearbeitet:

Marco13

Top Contributor
xTemp und yTemp sind lokal definiert. x und y sind anscheinend Instanzvariablen. In der update-Methode werden xTemp und yTemp verändert und danach nicht weiter verwendet. Das macht keinen Sinn. Und bei einer Kollision werden x und y auf den Wert gesetzt, den sie ursprünglich hatten. Und wo sie dann wie verwendet werden ist (mir) nicht klar.
 

ML-Deluxe

Mitglied
Diese Klasse stellt praktisch die steuerbare Figur dar. x und y sind dabei die Koordinaten nach welchen das Sprite der Figur gezeichnet wird und damit auch mein Kreis. In der update Methode passiert sinngemäß folgendes: Es werden die neuen x und y aufgrund von Geschwindigkeit und Zeit berechnet. Diese werden aber erstmal nur in xtemp und ytemp gespeichert. Dann wird geschaut, ob mit diesen neuen Koordinaten eine Kollission stattfindet. Findet keine Kollission statt, so können x und y geändert werden. (Beachte das "!" vor der Bedingung).
Mache ich das gleiche mit einem Kreis und einem Rectangle mittels der gegebenen intersects Methode so funktioniert das einwandfrei, ist aber für meine Zwecke nicht ausreichend.

Mein Problem dabei nochmal: Die beiden Kreise schneiden sich trotzdem und deshalb können sich die xy koordinaten dann nicht mehr ändern.
 

ML-Deluxe

Mitglied
Hier ein etwas dirty kskb. Mit den Richtungstasten wird der kleine Kreis bewegt und verhakt sick im großen.
Ma gucken ob dir das was bringt ;D

Java:
package kskb;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Main extends JPanel implements KeyListener {

	public static void main(String[] args) {
		new Main();
	}

	private static final long serialVersionUID = 1L;
	JFrame frame;
	
	static Ding baum;
	Ding figur;
	
	public Main() {
		this.setBounds(0, 0, 500, 500);
		
		
		baum = new Ding(200, 100, 50);
		figur = new Ding(100, 50, 20);
		
		frame = new JFrame("Kreiseyupheidi");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(500, 300);
		frame.setLocation(50, 50);
		frame.setLayout(null);	
		frame.add(this);
		frame.addKeyListener(this);
		frame.setVisible(true);
		
		gameLoop();
	}
	
	public void gameLoop() {
		long startTime = System.currentTimeMillis();
		long cumTime = startTime;
		
		while (true) {
			long timePassed = System.currentTimeMillis() - cumTime;
			cumTime += timePassed;
			
			figur.update(timePassed);
			
			
			frame.repaint();
			
			try {
				Thread.sleep(20);
			} catch (Exception ex) {}
		}
	}

	public void paintComponent(Graphics g) {
		
		g.drawOval((int)baum.getOval().getX(), (int)baum.getOval().getY(), (int)baum.d, (int)baum.d);
		
		g.drawOval((int)figur.getOval().getX(), (int)figur.getOval().getY(), (int)figur.d, (int)figur.d);
		
	}
	

	@Override
	public void keyPressed(KeyEvent e) {
		int keyCode = e.getKeyCode();
		if (keyCode == KeyEvent.VK_LEFT) figur.vx = -0.3f;
		if (keyCode == KeyEvent.VK_RIGHT) figur.vx = 0.3f;
		if (keyCode == KeyEvent.VK_UP) figur.vy = -0.3f;
		if (keyCode == KeyEvent.VK_DOWN) figur.vy = 0.3f;
		
	}

	@Override
	public void keyReleased(KeyEvent e) {
		int keyCode = e.getKeyCode();
		if (keyCode == KeyEvent.VK_LEFT) figur.vx = 0f;
		if (keyCode == KeyEvent.VK_RIGHT) figur.vx = 0f;
		if (keyCode == KeyEvent.VK_UP) figur.vy = 0f;
		if (keyCode == KeyEvent.VK_DOWN) figur.vy = 0f;
		
	}

	@Override
	public void keyTyped(KeyEvent arg0) {
				
	}
}

Java:
package kskb;

import java.awt.geom.Ellipse2D;

public class Ding {
	float x, y, d;
	float vx, vy;
	
	public Ding(int x, int y, int d) {
		this.x = x;
		this.y = y;
		this.d = d;
		vx = 0;
		vy = 0;
	}
	
	public Ellipse2D.Double getOval() {
		return new Ellipse2D.Double(x + 10.0, y + 30.0, d, d);
	}

	public void update(long timePassed) {
		float xTemp = x, yTemp = y;
		xTemp += vx * timePassed;
		yTemp += vy * timePassed;
		
		if (!intersection2Ovals(Main.baum.getOval(), this.getOval())) {
			x = xTemp;
			y = yTemp;
		}
	}
	
	public boolean intersection2Ovals(Ellipse2D.Double oval1, Ellipse2D.Double oval2) {
		double r1 = oval1.getWidth() / 2.0;
		double r2 = oval2.getWidth() / 2.0;
		
		double x1 = oval1.getCenterX();
		double y1 = oval1.getCenterY();
		double x2 = oval2.getCenterX();
		double y2 = oval2.getCenterY();
		
		double a;
		if (x1 < x2) 
			a = x2 - x1;
		else 
			a = x1 - x2;
		
		double b;
		if (y1 < y2) 
			b = y2 - y1;
		else 
			b = y1 - y2;
		
		double c = Math.sqrt(a * a + b * b);
		double diff = c - (r1 + r2);
		
		if (diff <= 0.0) 
			return true;
		
		return false;
	}
}
 

Marco13

Top Contributor
Ja, bringt was. Irgendwie hatte ich die update-Methode nicht ganz verstanden (was vielleicht auch mit dem übersehenen "!" zusammenhing :oops: ) aber... im Moment macht sie ja folgendes:

WENN es an der alten Position keine Überschneidung gab
DANN bewege dich an die neue Position
....
(... egal, ob es DORT eine Überschneidung gibt oder nicht...)

Eigentlich sollte sie aber sowas machen wie

WENN es an der neuen Position eine Überschneidung gibt
DANN beweg' dich gar nicht erst dort hin :D weil Überschneidungen sind bäh..

Also etwa so
Java:
    public void update(long timePassed) {
        float xTemp = x, yTemp = y;
        x += vx * timePassed;
        y += vy * timePassed;
        if (intersection2Ovals(MainCircles.baum.getOval(), this.getOval())) // Kein Ausrufezeichen ;-)
        {
            x = xTemp; // Wieder zurück zur alten Position
            y = yTemp;
        }
    }
 

Neue Themen


Oben