# Tower-Def. KonzeptFrage



## vanny (18. Dez 2011)

Ich würde gerne zur Auflockerung ein TD-Projekt starten.
Beim Brainstorming bin ich nun an der Stelle angelangt, wie ich die Map aufbauen sollte.
Der Übersicht halber genügen mir 90° Kurven und direkte Vogelperspektive.
Nun muss ich ja dafür sorgen, dass sich die Mobs gleichmäßig von Start nach Ziel bewegen.
Ich plane auch einen MapEditor zu erstellen, daher wollte ich Horizontal-, Vertikal- und die 4 Bogenklassen erstellen, die man aneinander snappen kann.

Frage:
Wie berechne ich am besten den Weg für die Mobs?
-rekrusiv von jedem Mob suchen lassen(rechenintensiv)
-Mapelemente rastern, Weg berechnen und in die Map abspeichern(speicherintensiv)
-anhand von Ankerpunkten interpolierte Funktionen errechnen und dann die Mobs procedual ablaufen lassen?(vanny!=Mathegenie:autsch
- oder bessere Idee?

Danke schonmal für´s Kopfzerbrechen

Gruß Vanny


----------



## Marco13 (18. Dez 2011)

AUF einer Kachel ist's ja klar, bzw. durch die Kurve vorgegeben - für den Weg von Kachel zu Kachel würde mir jetzt spontan einfallen: Graph bauen, Dijkstra laufen lassen und los.... :bahnhof:


----------



## vanny (18. Dez 2011)

Dijkstra sieht schon mal interessant aus und war mir bisher nicht bekannt 
Ich hab´s grad mal im Wiki überflogen und leider noch nicht ganz inhaliert.

Ich werd mich mal im wachen Zustand ranwagen und mich nochmal durchmelden

Gruß Vanny


----------



## Apo (18. Dez 2011)

Ich habe irgendwie nicht ganz rausgelesen, ob es wie bei Desktop Tower Defence nur einen Anfangpunkt und einen Endpunkt gibt und die Einheiten sich ihren Weg selber suchen, oder wie bei meinem ApoDefence es einen festgelegten Weg gibt.

Variante 1: Nur Start und Zielpunkt bekannt (wie bei Dektop Tower Defence).
- Würde ich einen A*-Algorithmus am Anfang laufen lassen und mir die Wegpunkte merken, die die Einheiten dann ablaufen. Wenn der Spieler einen Turm löscht oder baut, wieder für alle Einheiten A* drüberlaufen lassen. So rechenintensiv ist es gar nicht.

Variante 2: Fester Weg vorgegeben und es gibt nur einen Weg
- Ganz einfach im Editor die Wegpunkte setzen und abspeichern. So speicherintensiv ist es nicht. Bei ApoDefence war es so gelöst, dass von Startpunkt der erste Punkt erreicht werden musste. Wenn er erreicht wurde, dann wurde sich Punkt 2 genommen und der anvisiert. Hatte den Vorteil, dass die Einheiten nicht nur im 90° Winkel bewegen konnten. Einfach nur geschaut: aktuelle x-Position der Einheit und x-Position des Zielpunktes. Falls ungleich, dann laufe entweder nach links oder rechts und das gleiche halt für die y-Position auch.

Variante 3: Fester Weg vorgegeben, aber es gibt mehrere Wege zum Ziel
- Würde ich wieder einen A* drüber laufen lassen, aber nur einmal am Anfang und die Kanten so bewerten, wie die Einheiten Schaden nehmen würden, wenn sie da lang laufen. Der Weg mit den geringsten Schaden für die Einheiten würde genommen werden. Das kann man noch komplexer gestalten, wenn man fliegende Einheiten hat oder Türme die gegen unterschiedliche Gegner unterschiedlich stark sind. Aber das würde sich ja nur die Bewertung der Kante oder des Knotens auswirken


Natürlich kann jede der Varianten nochmal anders gelöst werden, aber so würde ich es lösen. =)


----------



## vanny (18. Dez 2011)

Apo hat gesagt.:


> Ich habe irgendwie nicht ganz rausgelesen ob es nur einen Anfangpunkt und einen Endpunkt gibt und die Einheiten sich ihren Weg selber suchen oder ... es einen festgelegten Weg gibt.



Ich hatte das auch nicht erwähnt, weil die Entscheidung noch nicht gefällt wurde. 
Ich denke aber ich werde mir T-Stücke mit rein nehmen und so dann vorgegebene Wege mit mehreren Optionen machen. (man munkelt aber noch)

Zum abspeichern der Wegpunkte/Graphen innerhalb einer Kachel, könnte man ja vielleicht einfach ein Image erstellen und dort den Pfad per Gradient setzen der halt immer dunkler wird, dann können die Mobs daran entlang hangeln und ich hätte gleich mal ne Richtungsangabe.
Im Mapeditor müsste man dann keine wegpunkte setzen, weil die sich aus der Richtungsangabe der Kacheln ergeben würde.
Der Editor könnte dann beim Speichern der Map einfach ein Pfadbild speichern, an dem sich jeder Mob in Bezug auf seine Position und der Pixelfarbe, auf der er steht orientieren kann. Ich spare mir irgendwelche Bogenberechnungen und Knotenpunkte, weil jeder Einstieg in ein neues Kachelelement mit Weiss beginnt und das hat halt immer Vorrang.


```
if(irgendwo == weiss){
dahinGehen();
}
else{
geheEinenDunkler();
}
```

Über das selbe Bild könnte ich auch bestimmen, wo Türme stehen dürfen und wo nicht.

Dijkstra würde ich dann nicht mehr benötigen, behalte ich aber im Hinterkopf.

Wäre jetzt mal meine Idee, die sich mit Hilfe eurer Vorschläge in meinem Schädel breit macht.
Wenn das Quarq ist, sagt es mir bitte, damit ich des löschen kann. 

Gruß Vanny


----------



## vanny (20. Dez 2011)

So, keiner sagt, es sei Quatsch also hier mal mein TestBild.
der Einstiegspunkt ist komplett weiss, dann springt er auf (250,255,255) und dann immer einen weiter bis (210,255,255).
Damit sollte ich eigentlich Richtung und Ausrichtung steuern können.

Werd mich die Tage dann mal mit erstem Code melden.

Gruß Vanny


----------



## Evil-Devil (21. Dez 2011)

Mach doch für den Anfang einfach eckige Wege. Bzw. überhaupt die gesamte Bewegung basierend auf einem Grid. Das müsste doch um ein vielfaches weniger Aufwand bedeuten.


----------



## vanny (21. Dez 2011)

Ok ich hab mir das mal alles noch mal durchgelesen und festgestellt, dass ich nun mal klarstellen sollte, es geht hier um den Editor im Moment.
Der läuft beim Speichern/Prüfen der Map den/die Gradienten ab und erstellt die Points und die Ausrichtung für die Mobs.
Wie ich diese dann Speichere, will ich mal ausprobieren und die Kacheln zu zeichnen war jetzt nich der Hit, die hab ich alle schon fertig ca. 40 min. Pixelschubsen.

Wenn ich das komplett per Grid löse, hab ich für den Editor erheblich mehr gefummel denke ich.
Wie gesagt ich probier das einfach mal aus und halte euch auf dem laufenden.
Fragen werden garantiert auch noch genug kommen.

Gruß Vanny


----------



## Marco13 (21. Dez 2011)

So ganz hab' ich's nicht kapiert, aber den Weg der Figuren auf Basis des Farbverlaufs eines Bildes zu berechnen klingt SEHR gewagt. (An sich vielleicht gar nicht mal so - im Endeffekt macht A* sogar was ganz ähnliches! - aber dieser ""Farbverlauf"" wird, wie eine Art "Potentialfeld", "on the fly" berechnet - das irgendwo speichern und in einem Editor zusammensetzen zu wollen, stelle ich mir schwierig vor ???:L)


----------



## vanny (27. Dez 2011)

So,

nachdem genau am 24.12. um 14.00 Uhr (der letzte PC-Handel schließt genau dann seine Pforten) ein großer Knall, Netzteil und Board meines Rechners entschärfte, konnte ich heute nach einer kleinen 180,-€ Investition wieder proggen 

Ich habe heute den Editor so weit gebracht, dass er mir anhand der Pixelanalyse in der Liste "Weg", Wegpunkte zusammenstellt, welche wiederum eine WrapperKlasse sind, die x, y und die Ausrichtung halten.

@ Marco
Es ist vielleicht gewagt aber möglich.

Vielleicht kurz zur Vorgehensweise:

in findStart();
suche ich mir innerhalb des Registrierten startTiles mein weisses Pixel. (ja ich weiss, nur red hätte auch gelangt ).
Diese Startposition wird gespeichert.
Danach zeichne ich die komplette Map in ein BufferedImage (map).

Dann starte ich den Scann, so wie geplant und laufe die umliegenden Pixel der jeweils aktuellen Position ab.

Wenn ich keins mehr finde is Sabbat.

hier mal der Code des ScannThreads.


So looong Vanny

PS: keine Frage aber mal ein WIP-Stand


```
package threads;

import gui.TilesPanel;

import java.awt.Color;
import java.awt.Point;
import java.awt.image.BufferedImage;
import modell.Weg;
import dataTypes.ImgListe;
import dataTypes.Richtung;
import dataTypes.WegPunkt;

public class TestThread extends Thread {

	private TilesPanel tp;
	private boolean isRunnig = true;
	private ImgListe images;
	private int startX, startY;
	private BufferedImage map;
	private Weg weg;
	private int currentClrRed = 250;
	private int[] scanns = { 0, 1, -1 };
	private Point lastWhite;
	private boolean weiss, dunkel;

	public TestThread(TilesPanel tp, ImgListe images, Weg weg) {
		this.tp = tp;
		this.images = images;
		this.weg = weg;
	}

	public void run() {
		findStart();
		while (isRunnig) {
			scannStep();
			try {
				sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	private void findStart() {
		if (tp.getStartTile() != null) {
			System.out.println("suche StartPixel");
			BufferedImage img = images.get(tp.getStartTile().getImgValue());
			for (int i = 0; i < tp.getStartTile().getCoords().getWidth(); i++) {
				for (int j = 0; j < tp.getStartTile().getCoords().getHeight(); j++) {
					int clr = img.getRGB(i, j);
					int red = (clr & 0x00ff0000) >> 16;
					int green = (clr & 0x0000ff00) >> 8;
					int blue = clr & 0x000000ff;
					Color col = new Color(red, green, blue);
					if (col.equals(Color.WHITE)) {
						startX = (int) tp.getStartTile().getCoords().getX() + i;
						startY = (int) tp.getStartTile().getCoords().getY() + j;
						System.out.println("start bei : " + startX + ", "
								+ startY);
						lastWhite = new Point(startX, startY);
						map = tp.paintMap();
					}
				}
			}
		}
	}

	private void scannStep() {
		weiss = false;
		dunkel = false;
		for (int i = 0; i < scanns.length; i++) {
			for (int j = 0; j < scanns.length; j++) {
				nextStep(scanns[i], scanns[j]);
			}

		}
		if(!weiss && !dunkel){
			endScann();
		}

	}

	private void nextStep(int difX, int difY) {
		int x = startX + difX;
		int y = startY + difY;
		if (weissTest(x, y)) {
			System.out.println("neuer Wegpunkt (weiss)");
			weg.add(new WegPunkt(x, y, new Richtung(difX, difY).getRichtung()));
			startX = x;
			startY = y;
			weiss = true;
		} else if (einDunklerTest(x, y)) {
			System.out.println("neuer Wegpunkt (step)");
			weg.add(new WegPunkt(x, y, new Richtung(difX, difY).getRichtung()));
			startX = x;
			startY = y;
			dunkel = true;
		}
	}

	private boolean weissTest(int x, int y) {
		Point currentPoint = new Point(x, y);
		boolean isOldPoint = false;
		if (!(lastWhite.equals(currentPoint))) {
			int clr = map.getRGB(x, y);
			int red = (clr & 0x00ff0000) >> 16;
			if (red == 255 && !isOldPoint) {
				currentClrRed = 250;
				startX = x;
				startY = y;
				lastWhite.setLocation(x, y);
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	private boolean einDunklerTest(int x, int y) {
		int clr = map.getRGB(x, y);
		int red = (clr & 0x00ff0000) >> 16;
		System.out.println("red = " + red + "@ " + x + ", " + y);
		if (red == currentClrRed) {
			currentClrRed--;
			System.out.println("hat einen Dunkler");
			return true;
		} else {
			return false;
		}
	}

	private void endScann() {
		System.out.println("beende scanns");
		isRunnig = false;
	}

}
```


----------

