Kollisionskontrolle optimieren

Ortwin1st

Mitglied
Hallo,
habe vor einiger Zeit ein kleines Jump'n'Run bzw. Think'n'Run Spiel geschrieben. Ein Eichhörnchen läuft durch den Wald, kann auf Bäume klettern und wie ein Maulwurf in Tunneln laufen. Über meine Map aus tiles habe ich eine durchsichtige Kollisionsmap aus unterschiedlichen Farben gelegt. Vor jeder Bewegung prüfe ich, auf welches Farbfeld das Eichhörnchen tritt und je nach Ergebnis entscheidet sich was passiert.

Die Kodierung:
- schwarz: Bewegung vertikal nach unten (Schwerkraft)
- weiß: Massiv, kann nicht auf weiße Felder laufen
- grün: Kann horizontal und vertikal nach oben und unten laufen
- rot: Tot, beendet level
- pink: Nur passierbar mit Schlüssel (verschlossene Tür)

Dabei messe ich insgesamt 6 Kollionspunkte: links und rechts, je oben, mitte, unten

Meine Kollisionsmethode:
Code:
	public void move(long delta) {
		// Berücksichtigung der Durchlaufzeit (Framerate) garantiert gleichmäßige Bewegung
		int newX = (int) (x + dx*(delta/1e9));
		int newY = (int) (y + dy*(delta/1e9));
		int offsetX = (int) (getWidth() * 0.3);
		int offsetY = 20;
		
		// Wenn Koordinaten außerhalb der Map, nimm alten Wert
		if(newX<0 || newX+getWidth()>parent.getWidth() || 
				newY<0 || newY+getHeight()>parent.getHeight()) 
			return;
		
		Color colLT = parent.getMap().getColorForPoint(new Point(newX+offsetX,newY+offsetY));
		Color colRT = parent.getMap().getColorForPoint(new Point((int)(newX+getWidth()-offsetX),newY+offsetY));
		Color colLM = parent.getMap().getColorForPoint(new Point(newX+offsetX,(int) (newY+(getHeight()/2))));
		Color colRM = parent.getMap().getColorForPoint(new Point((int)(newX+getWidth()-offsetX),(int) (newY+(getHeight()/2))));
		Color colLB = parent.getMap().getColorForPoint(new Point(newX+offsetX,(int)(newY+getHeight()-10)));
		Color colRB = parent.getMap().getColorForPoint(new Point((int)(newX+getWidth()-offsetX),(int)(newY+getHeight()-10)));
		Color colLB2 = parent.getMap().getColorForPoint(new Point(newX+offsetX,(int)(newY+getHeight()-5)));
		Color colRB2 = parent.getMap().getColorForPoint(new Point((int)(newX+getWidth()-offsetX),(int)(newY+getHeight()-5)));
		
		// Wenn Luft unter den Füßen und kein Boden unter den Füßen und oben nichts zum festhalten (hängen bleiben)
		if(colLB.equals(Color.black) && colRB.equals(Color.black) 
				&& !(colLB2.equals(Color.white) || colRB2.equals(Color.white))
				/*&& !(colLT.equals(Color.green) && colRT.equals(Color.green))*/) {
			controlable = false;
			setPics(bImgNorm);
		} else {
			controlable = true; 
		}
		
		// Wenn Player sich nicht bewegt
		if(dx==0 && dy ==0) {
			setPics(bImgNorm);
		}
		
		if(dy>0) { // Kollisionskontrolle vertikal nach unten
			// Wenn neue Koordinate über unterem Rand und nicht über weißen Pixeln
			if(newY+getHeight()<parent.getHeight() && !(colLB.equals(Color.white) || colRB.equals(Color.white))) {
				y = newY;
				if(bImgUpDown!=null) setPics(bImgUpDown);
			}
		} else if (dy<0) { // Kollisionskontrolle vertikal nach oben // TODO: Bug, Player springt nach oben
			if(newY>0 && !(colLT.equals(Color.white) || colRT.equals(Color.white))
					&& !(colLB.equals(Color.black) || colRB.equals(Color.black)) 
					&& (colLB.equals(Color.green) && colRB.equals(Color.green)
					|| colLT.equals(Color.blue) || colRT.equals(Color.blue))) {
				y = newY;
				if(bImgUpDown!=null) setPics(bImgUpDown);
			}
		} 
		
		// Wenn X nicht über horizontale Ränder geht
		if(dx>0 && !(colRB.equals(Color.white) || colRM.equals(Color.white))
				&& (key || !colRB.equals(Color.magenta))) {
			x = newX;
			if(bImgRight!=null) setPics(bImgRight);
			
			// Geschlossene Tür öffenen
			if(colLB.equals(Color.magenta)&&key) 
				parent.changeTile(new Point((int) x, (int)y+offsetY), TILE_OPEN_WOODDOOR);
			
			// Wenn Kopf rechts oben anstößt, setze automatisch nach unten
			if(colRT.equals(Color.white)) y += offsetY*0.3;
		} else if (dx<0 && !(colLB.equals(Color.white) || colLM.equals(Color.white)) 
				&& (key || !colLB.equals(Color.magenta))) {
			x = newX;
			if (bImgLeft!=null) setPics(bImgLeft);
			
			// Geschlossene Tür öffenen
			if(colLB.equals(Color.magenta)&&key) 
				parent.changeTile(new Point((int) x, (int)y+offsetY), TILE_OPEN_WOODDOOR);
			
			// Wenn Kopf links oben anstößt, setze automatisch nach unten
			if(colLT.equals(Color.white)) y += offsetY*0.3;
		}				

			// Wenn Player auf Rot tritt, GameOver
		if(colLB.equals(Color.red) || colRB.equals(Color.red)) { // && !colLT.equals(Color.green) && !colRT.equals(Color.green)) {
			parent.endGame(false, "Aua******");
		} 
	}

Finde die Kollisionskontrolle insgesamt sehr hackelig. Meine Betatester hatten schon bemängelt, das es schwierig ist in horizontale Tunnels zu gehen. Deshalb habe ich nachträglich ein Funktionalität eingebaut, wenn der Kopf oben anstößt, das Eichhörnchen nach unten zu versetzen.

Aber wie kann ich die Funktion insgesamt optimieren?
 

Neue Beiträge

Zurück