# Kollisionsabfrage haut nicht hin



## Robokopp (23. Mrz 2012)

Sry dass ich deswegen jetzt nochmal einen Thread eröffne, aber ich finde den Fehler einfach nicht...
ich sehe da keinen Unterschied zwischen meiner Version und der des Quaxi Tutorials, abgesehen davon dass sich bei ihm die Raketenobjekte noch untereinander treffen können.
also ich hab eine GameLoop, in der die Logik für alle Elemente durchgeführt und gleichzeitig auf Kollision geprüft wird:


```
private void doLogic() {
		
		if(player.getY()<400){
			firstaction=true;
		}
		if(firstaction){
			
		for(ListIterator<Sprite> it = actors.listIterator();it.hasNext();){
			Sprite r = it.next();
			r.doLogic();
			player.collidedWith(r);
}
```

Da die Blöcke untereinander garnicht kollidieren können, habe ich dafür die Kollisionsprüfung weggelassen(mit geht es trotzdem nicht)

Die Klasse player beinhaltet die intersects() Methode:


```
@Override
	public boolean collidedWith(Sprite s){
		
		if(this.intersects(s)){
			
			System.out.println("Intersects");
			return true;
		}
		return false;
		
	}
```


Der Spielebildschirm stellt eine Art Tower dar, wo Blöcke von oben nach unten fallen und die Spielfigur soll darauf springen können.

Nur irgendwie ist intersects nie true...

Ich hatte anfangs eine eigene Kollisionsprüfung implementiert, die doch sehr waage war und nicht wirklich gut funktioniert hat.


----------



## Fu3L (23. Mrz 2012)

Ich denke dieser kleine Codeteil reicht dafür nicht...
Positionierung von Spieler und Blöcken könnte wichtig sein. Außerdem das Erstellen der Blöcke inklusive Konstruktor.


----------



## Robokopp (23. Mrz 2012)

echt?
ich dachte für intersects reichen einfach 2 Objekte. Na gut


```
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

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


public class Block extends Sprite implements Drawable{
	GamePanel panel;
	JFrame frame;
	BufferedImage block1;
	BufferedImage image;
	Player player;
	private double fallgeschwindigkeit=2;
	private int panelwidth;
	private boolean rightmovement;
	private boolean leftmovement;
	private int rightbound;
	private int leftbound;
	private int modulo;
	private int zufall;
	private double yRaw;
	private int width;
	private int height;
	private int x;
	
public void setPanelwidth(int panelwidth) {
		this.panelwidth = panelwidth;
	}
	
	public Block(int id,int x, int y, int width, int height,Color color,BufferedImage image) {
		super(id,x, y, width, height,color,image);
		// TODO Auto-generated constructor stub
		this.image=image;
		this.width=width;
		this.x=x;
		this.y=y;
		this.height=height;
	
		modulo=id % 10;
		if(modulo == 0){
			zufall =(int)(Math.random()*2);
			if(zufall==0){
				System.out.println("Block"+id+" is moving left");
			}
			else if(zufall==1){
				System.out.println("Block"+id+" is moving right");
			}
			
		}
	}

	private static final long	serialVersionUID	= 1L;

	@Override
	public void drawObjects(Graphics g){
		g.drawImage(image, x, (int)y,width,height, null);
	}	
	@Override
	public double getY() {
		return y;
	}
	
	@Override
	public void doLogic2(double player){
		
		int i=0;
		if(player>40){
//			System.out.println(">40");
			while(i<20){
				i++;
			yRaw=y+0.1;
			y=(int)yRaw;
			}
		
		}
		if(player<=40){
//			System.out.println("<40");
			while(i<20){
				i++;
			yRaw=y+0.1;
			y=(int)yRaw;
			}
			
		}
	}

	@Override
	public void doLogic(){
		

			if(y>0){
				
				if(!leftmovement&&!rightmovement){
				if(zufall==0&&modulo==0){
					leftmovement=true;
					rightmovement=false;
				}
				if(zufall==1){
					leftmovement=false;
					rightmovement=true;
				}}
				
				if(leftmovement){
					x--;
					if(x<45){
						rightmovement=true;
						leftmovement=false;
					}
				}
				if(rightmovement){
					x++;
					if(x>(panelwidth-panelwidth/4)-width){
						rightmovement=false;
						leftmovement=true;
					}
				}
			}
					
			y=(int)(y+fallgeschwindigkeit);
			
	}
	@Override
	public double getWidth(){
		return width;
	}
	@Override
	public boolean collidedWith(Sprite s){
		
		
		if(this.intersects(s)){
			System.out.println("Intersects");
			return true;
		}
		return false;
		
	}
	@Override
	public int getID(){
		return id;
	}


}
```


```
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ListIterator;
import java.util.Vector;

import javax.imageio.ImageIO;
import javax.swing.JFrame;


public class Player extends Sprite{
	GamePanel panel;
	JFrame frame;
	BufferedImage mewnormal;
	BufferedImage mewleft;
	BufferedImage mewright;
	BufferedImage mew;
	int time;
	private int jumpingtime=0;
	Vector<Sprite> actors= new Vector<Sprite>();
	Block block;
	private int y;
	private int x;
	private int width;
	private int height;
	private boolean jump=true;

	private Sprite r;
	private boolean isMoving;
	public Player(int id, int x, int y, int width, int height, Color color) {
		super(id, x, y, width, height, color, null);
		this.x=x;
		this.y=y;
		this.width=width;
		this.height=height;
		
		try {
			mewnormal = ImageIO.read(new File("Sources/mew.png"));
			mewleft = ImageIO.read(new File("Sources/mewleft.png"));
			mewright = ImageIO.read(new File("Sources/mewright.png"));
			mew=mewnormal;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	public boolean isJump() {
		return jump;
	}

	@Override
	public double getY() {
		return y;
	}


	public double getX() {
		return x;
	}


	public void setY(int y) {
		this.y = y;
	}

	public void setX(int x) {
		this.x = x;
	}
	public void setNormalPic(){
		mew=mewnormal;
	}
	@Override
	public void drawObjects(Graphics g){
		g.drawImage(mew, x, y,width,height, null);
	}
	public void timeReset(){
		time=0;
		jumpingtime=0;
	}
	

	@Override
	public void doLogic(){
	
		if(y<747-height){
			time=time+1;
			double yRaw=y+0.0007*time*time*9.81;
			y=(int)yRaw;
			
			
			
		}
		
	}

	@Override
	public boolean collidedWith(Sprite s){
		
//		System.out.println("Collidewith");
		if(this.intersects(s)){
			
			System.out.println("Intersects");
			return true;
		}
		return false;
		
	}
	@Override
	public void moveUp(){
		mew=mewnormal;
	}
	@Override
	public void moveDown(){
		mew=mewnormal;
	}
	@Override
	public void moveLeft(){
		mew=mewleft;
	}
	@Override
	public void moveRight(){
		mew=mewright;
	}




}
```

Und hier noch zwei relevante Methoden aus der MainKlasse:


```
private void checkKeys() {

		if(down){
			player.setY((int) (player.getY()+yvelocity));
		}
		if(left){
			player.setX((int) (player.getX()-xvelocity));
		}
		if(right){
			player.setX((int) (player.getX()+xvelocity));
		}
		if(jump){
			
			jumping();
		
	}}
	private void jumping(){
		
		jumpingtime=0;
		while(jumpingtime<jumpfactor){
//			player.setBlockcontact(false);
			jumpingtime++;
			double yRaw = player.getY()-jumpingspeed*0.000001*9.81*jumpingtime*jumpingtime;
			player.setY((int)yRaw);
		}
			if(player.getY()<120){
//				this.backgroundclass.doLogic2(player.getY());
				for(ListIterator<Sprite> it = actors.listIterator();it.hasNext();){
					Sprite r = it.next();
					r.doLogic2(player.getY());
					

				}
			}
			if(jumpingtime==jumpfactor){
				jump=false;
			
			}
	}
```


----------



## Marco13 (23. Mrz 2012)

Hab' die Sprite-Klasse nicht im Kopf - kann es sein, dass du getX()/getY() überschrieben hast?


----------



## Robokopp (23. Mrz 2012)

Hmm bin zwar Grad nicht zu hause aber ich glaube nicht....  Aber selbst wenn, macht das was aus?

Gesendet von meinem GT-I9100 mit Tapatalk


----------



## Marco13 (24. Mrz 2012)

Wenn die Sprite-Klasse schon z.B. von Rectangle2D erbt, dann wird für die "intersects"-Methode auch getX() verwendet. Wenn man die überschreibt, so dass "das falsche X" zurückgegeben wird, arbeitet auch die Methode nicht mehr richtig. Ist aber erstmal nur geraten.


----------



## Robokopp (24. Mrz 2012)

Okay ich raffs nicht. Hab jetzt mal die Getter für X und Y aus der Sprite Klasse gelöscht. In der Block und Playerklasse habich die @Override Anotation der Getter gelöscht und es funktioniert immer noch nicht.

Ich hänge hier mal das gesamte Projekt an.

JavaJumpAndRun.rar (5,75 MB) - uploaded.to


----------



## Marco13 (24. Mrz 2012)

In der Sprite-Klasse sind keine getX/getY, dafür aber in deiner Player-Klasse - und DIE könnte (!) das Problem sein.


```
class Rectangle2D.Double
{
    private double x; //-------------------- Das hier ist das "ECHTE" x!
    ...
    public double getX() { 
        return x;  //--------------------  getX liefert das "ECHTE" x!
    }
    ...

    public boolean intersects(Rectangle2D other)
    {
        if (getX() < other.getX()) ... //------------------------- Verwendet getX !!!
    }
}


class Sprite extends Rectangle2D.Double  // erbtgetX und getY und intersects
{
...
}


class Player extends Sprite
{
    private int x;  //-------------------- Das hier ist das "FALSCHE" x!

    public double getX() //-------------------- Überschreibt das getX() aus Rectangle2D!
    {
        return x;  //-------------------- Liefert das FALSCHE x zurück!
    }

}
```

Wenn man jetzt auf Player "intersects" aufruft, wird dort unter anderem getX aufgerufen, aber das gibt das falsche X zurück. Wozu hast du im Player überhaupt nochmal x,y,width und height gespeichert? Die hat es doch schon, wenn es von Sprite (also von Rectangle2D.Double) erbt!?


----------



## Robokopp (24. Mrz 2012)

Frag mich was leichteres  aber danke, werde ich morgen gleich mal ausprobieren 

Gesendet von meinem GT-I9100 mit Tapatalk


----------



## Robokopp (25. Mrz 2012)

Robokopp hat gesagt.:


> Frag mich was leichteres  aber danke, werde ich morgen gleich mal ausprobieren
> 
> Gesendet von meinem GT-I9100 mit Tapatalk



Okay, hab jetzt die Gettermethoden zu 

```
public double getYPos() {
		return y;
	}


	public double getXPos() {
		return x;
	}
```

geändert und alle Methodenzugriffe ebenfalls geändert auf player.getXPos/YPos und es funktioniert dennoch nicht...

EDIT:
ich hab nun mal mit 

```
System.out.println("Playerx "+this.getX()+" Playery "+this.getY()+" Sprite x "+s.getX()+ " Spritey "+s.getY());
```

in der CollidedWith() Methode die Koordinaten geprüft, wobei in allen Fällen 0 angezeigt wird, was ja nicht sein dürfte


----------



## Marco13 (25. Mrz 2012)

Was ist mit den Settern?


----------



## Robokopp (25. Mrz 2012)

die Setter hab ich jetzt auch alle umgeschrieben zu setXPos und YPos, funzt trotzdem nicht


----------



## Marco13 (25. Mrz 2012)

Hmja, hab' mir den Code nochmal angesehen. Das ist mal wieder so ein Fall, wo versucht wurde, ein ganz tolles Spiel zu schreiben indem ganz viel Quellcode hingeschrieben wurde, ... das geht halt immer erstaunlich lange gut, und wenn man merkt, dass irgendwas nicht stimmt, ist SO viel Code da, dass man es kaum noch in eine vernünftige Strukur bringt. Aber abgesehen von dieser Strukturfreiheit (die GamePanel  ist ein Monster mit etliche überflüssigen Fields - räum' das auf!) ist eines der Hauptprobleme, dass du überall x/y/width/height neu bzw. anders definierst. 

Sprite extends Rectangle2D.Double!!!!

Das heißt, jedes Sprite hat die Methoden getX(), getY(), getWidth() und getHeight() aus der Klasse Rectangle2D.Double. Und diese Methoden sollte man nicht überschreiben. (Ob die Sprite-Klasse wirklich von Rectangle2D.Double erben sollte, sei mal dahingestellt, aber das hatte Quaxli AFAIR gemacht, weil es einige Dinge - speziell das intersects usw. - vereinfachen KANN - FALLS man nicht sowas macht wie du jetzt...)


Nimm aus der Sprite-Klasse mal die
	int x;
	int y;
	int width;
	int height;
raus, und aus der Block-Klasse die
	int x;
	int width;
	int height;
und aus der Player-Klasse die
	int x;
	int y;
	int width;
	int height;

In der BackGround-Klasse lungern auch noch so ein paar Koordinaten rum, mit denen ich gerade nichts anzufangen weiß. Vermutlich sollte der Background gar kein Sprite sein, aber ... die Gesamtstruktur habe ich nicht wirklich nachvollziehen können.

In die Sprite-Klasse kann ein

```
public void setY(double y) {
		this.y = y;
	}

	public void setX(double x) {
		this.x = x;
	}
```
rein, aber allen anderen setX/getX/setY/getY-Methoden aus allen anderen Klassen (Player, Block, etc.) sollten WEG.

Er wird sich dann an einigen Stellen beschweren, weil er int's braucht, aber doubles bekommt, bzw. nicht auf x/y zugreifen kann. Diese Stellen, wie z.B. in Player
g.drawImage(mew, x, y,width,height, null);
kannst du nach diesem Muster ändern:
g.drawImage(mew, (int)getX(), (int)getY(),(int)getWidth(), (int)getHeight(), null);

Für alles weitere müßte man den Code nochmal genauer durchlesen und aufräumen... 

Jedenfalls düfte die intersects-Methode dann zumindest grundsätzlich funktionieren....


----------



## Robokopp (25. Mrz 2012)

Hey danke, das hat mir geholfen hab mal ausgemistet, da war doch einiges dabei was ich nicht mehr gebraucht habe^^


----------



## Marco13 (25. Mrz 2012)

Funktioniert denn die Kollisionserkennung jetzt so, wie du dir das vorgestellt hattest?


----------



## Robokopp (26. Mrz 2012)

Jap läuft alles optimal. Habs aber gestern nicht mehr geschafft dafür zu sorgen, dass nur gesprungen werden kann wenn er auf einem block sitzt. Zur zeit sind noch luftsprünge möglich 

Gesendet von meinem GT-I9100 mit Tapatalk


----------

