# Kollisionserkennung in Slick2D... Mal wieder



## Sessiolog (8. Dez 2014)

Moin Leute! Ich habe eine Frage zum Thema Kollisionserkennung zwischen Spieler und Map im 2D-Raum. Zurzeit arbeite ich mit Slick2D an einen kleinen Sidescroller und komme nicht mehr weiter. Also:
Zuerst wird mit einer zweifachen for(...)-Schleife die extern erstellte Map nach blockierenden Tiles abgesucht. Diese blockierenden Tiles werden dann als Rectangles in einer ArrayList gespeichert.
Das sieht dann so aus:

```
blocks = new ArrayList<Rectangle>();
for (int row = 0; row < tilemap.getWidth(); row++) {
	for (int col = 0; col < tilemap.getHeight(); col++) {
		line = tilemap.getTileProperty(tilemap.getTileId(row,col,0),"blocked", "false");
		if (line.equals("true") {
			blocks.add(new Rectangle(row * TILESIZE, col * TILESIZE, TILESIZE, TILESIZE));
		}
	}
}
```

In der update() Methode wird dann abgefragt, ob der Spieler-Sprite mit einem der blockierenden Tiles kollidieren würde.

```
public void update(GameContainer arg0, int delta)
	if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
		if (!isBlocked()) { y -= delta * 0.1;} 
	}
		
	if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
		if (!isBlocked()) { y += delta * 0.1;}
	}
			
	if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
		if (!isBlocked()) { x -= delta * 0.1;}
	}
				
	if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
		if (!isBlocked()) {x += delta * 0.1;}
	}
}

boolean isBlocked() {
        for (int a = 0; a < blocks.size(); a++) {
               if (hitbox.intersects(blocks.get(a))) { //hitbox ist das Rectangle welches den Sprite umgibt
			return true;
		}
	}
	return false;
}
```

Das Problem: Sobald man mit einer blockierenden Tile kollidiert, ist man als Spieler völlig unfähig, sich überhaupt zu bewegen. Der Spieler steckt fest. Das Problem ließe sich natürlich beheben indem man im Falle einer Kollision, den Sprite ein bisschen zurück-bewegt, nur leider entsteht dadurch ein unangenehmes Flackern, weil der Sprite ständig um einen Pixel vor-und-zurück geschoben wird.. So als ob der Sprite "zittern" würde. Der hier demonstrierte Code, wird von vielen Online-Tutorials empfohlen. Scheinbar funktioniert das jedem nur nicht bei mir. Was habe ich falsch gemacht?
Über Hilfe in jeglicher Form wäre ich sehr dankbar.


----------



## Androbin (8. Dez 2014)

Das kannst du ganz einfach folgendermaßen lösen:
1. Du speicherst die aktuelle Position nochmal in einer lokalen Variable
2. Du bewegst den Spieler gemäß ...
3. Du prüfst, ob der Spieler kollidiert
3.1 Falls ja, setzte die Position auf das in 1. erstellte "Backup" zurück
3.2 Falls nein, bist du fertig

PS. Das ganze solltest du allerdings einmal für jede Koordinate machen,
sonst kannst du nicht an einem Hindernis "entlanggehen"!


----------



## Sessiolog (8. Dez 2014)

Danke schon mal für die Antwort. Leider funktioniert dein Vorschlag nicht so ganz, vielleicht habe ich es auch einfach nur falsch gemacht. Was die "Backup"-Variablen betrifft: Warum müssen die denn Lokal sein? Global würde hier doch mehr Sinn machen.

```
public void update(GameContainer arg0, int delta) throws SlickException {
		if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
			if (!isBlocked()) {
				y -= delta * 0.1;
				yC = y;     //"Backup"-Variable für den Y-Wert. Global.
			} 
			else y = yC;
		}
		
		if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
			if (!isBlocked()) {
				y += delta * 0.1;
				yC = y;		
			}
			else y  = yC;
		}
			
		if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
			if (!isBlocked()) {
				x -= delta * 0.1;
				xC = x;     //"Backup"-Variable für den X-Wert. Global.
			}
			else x = xC;
		}
				
		if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
			if (!isBlocked()) {
				x += delta * 0.1;
				xC = x;
			}
			else x = xC;
		}
	}
```

Leider existiert der Fehler weiterhin. Sobald ich als Spieler mit der Map kollidiere stecke ich fest. hilfe?


----------



## Androbin (8. Dez 2014)

Sessiolog hat gesagt.:


> Danke schon mal für die Antwort. Leider funktioniert dein Vorschlag nicht so ganz, vielleicht habe ich es auch einfach nur falsch gemacht. Was die "Backup"-Variablen betrifft: Warum müssen die denn Lokal sein? Global würde hier doch mehr Sinn machen.
> ...
> Leider existiert der Fehler weiterhin. Sobald ich als Spieler mit der Map kollidiere stecke ich fest. hilfe?


Nochmal von vorne! Was macht die Methode isBlocked() und müsstest das dann nicht so aussehen?:

```
...

if ( Keyboard.isKeyDown( Keyboard.KEY_W ) ) {
    
    yC = y;
    y -= delta * 0.1;
    
    if ( isBlocked() )
    	 y = yC;
    
}

...
```


----------



## Sessiolog (8. Dez 2014)

Wunderschön! Jetzt funktioniert es, Vielen Dank!
PS: Was die isBlocked() Methode betrifft: Die wurde schon in meinem ersten Post erwähnt. Sieht nach wie vor so aus:

```
boolean isBlocked() {
	for (int a = 0; a < blocks.size(); a++) {
		if (hitbox.intersects(blocks.get(a))) { //"hitbox" ist das Rechteck, welches den Sprite umgibt
			return true;
		}
	}
		
	return false;
}
```


----------

