# Java 2D Spiel



## Kenan89 (4. Mai 2012)

Hallo und guten Tag,
ich habe mir vorgenommen, das komplexe Thema anzugehen, ein eigenes Java 2D Spiel zu erstellen. Im Stil wie Pokemon. Das heisst man läuft auf einer Karte und kann mit den non-player-characters quatschen und es können auch Kämpfe stattfinden, wenn man zum Beispiel in einem Wald ist und einen Gegner berührt.
In diesem Thread stelle ich dann verschiedenste Java-Fragen falls ich nicht weiterkomme und halte euch auch auf dem laufenden mit aktuellen Screenshots. 
Am Ende wird das Spiel kostenfrei der Java-Community zur Verfügung gestellt.

Hiermit eröffne ich nur den Thread, die Fragen kommen bestimmt bald.


----------



## Kenan89 (4. Mai 2012)

Meine erste Frage:
Wieso kann ich in diesem Code nicht auf die Variable text zugreifen?

Der String befindet sich in Klasse "Frame" und soll in der Klasse "Menubar" ausgegeben werden.

Klasse Exe

```
package exe;

public class Exe {

	public static frame.Frame frame;
	
	public static void main(String[] args){
		frame = new frame.Frame();
	}
	
}
```

Klasse Frame

```
package frame;

import java.awt.BorderLayout;
import java.awt.event.ActionListener;

import javax.swing.JFrame;

public class Frame extends JFrame{
	
	private int framewidth = 500;
	private int frameheight = 500;
	
	private String text = "Hallo";
	private panels.Menubar menubar  = new panels.Menubar();
	private listeners.ListenerAction actionlis = new listeners.ListenerAction();;
	
	public Frame(){
		build();
	}

	private void build(){
				
		add(menubar, BorderLayout.NORTH);
		
		setTitle("Adventurer");
		setSize(framewidth, frameheight);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
	
	public panels.Menubar getMenu(){
		return menubar;
	}
	
	public ActionListener getActionLis(){
		return actionlis;
	}
	
	public String getIt(){return text;}
}
```

Klasse Menubar

```
package panels;

import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

public class Menubar extends JMenuBar{
	
	private JMenu options = new JMenu("Optionen");
	
	private JMenuItem newGame = new JMenuItem("Neu");
	private JMenuItem loadGame = new JMenuItem("Laden");
	private JMenuItem close = new JMenuItem("Ende");
	
	public Menubar(){
		build();
		addListeners();
	}
	
	private void build(){
	
		add(options);
		options.add(newGame);
		options.add(loadGame);
		options.addSeparator();
		options.add(close);
		
		
	}
	
	private void addListeners(){
		try{
			System.out.println(exe.Exe.frame.getIt());
		}
		catch(Exception e){
			System.out.println("Hää");
		}
	}
	
	public JMenuItem getJItemNewgame(){
		return newGame;
	}
	
	public JMenuItem getJItemLoadgame(){
		return loadGame;
	}
	
	public JMenuItem getJItemClose(){
		return close;
	}

}
```

Klasse Listener

```
package listeners;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class ListenerAction implements ActionListener{
	
	public void actionPerformed(ActionEvent e){
		Object obj = e.getSource();
		
		if(obj.equals(exe.Exe.frame.getMenu().getJItemClose())){
			System.exit(0);
		}
	}

}
```


----------



## Final_Striker (4. Mai 2012)

Kenan89 hat gesagt.:


> Hallo und guten Tag,
> ich habe mir vorgenommen, das komplexe Thema anzugehen, ein eigenes Java 2D Spiel zu erstellen.



Ich würde dir empfehlen, dir ein weniger komplexes Thema vorzunehmen, wie OOP Grundlagen und danach Swing Grundlagen. Wenn du das beherrscht, dann kannst du dich an so ein Spiel ranwagen.


----------



## Kenan89 (4. Mai 2012)

Was ist denn OOP-mäßg falsch am Code? ^^
Es soll ja nichts komplexes werden. Einfach Figuren, die sich auf der Karte bewegen und mit denen der Held sprechen kann vorerst.


----------



## Fu3L (4. Mai 2012)

```
exe.Exe.frame.getMenu()
```

Sowas ist falsch^^ Wenn du eine öffentliche statische Instanz von irgendwas brauchst und von da aus irgendwie auf alles zugreifst baumstrukturmäßig, dann ist das anti-OOP, wo doch information-hiding ein großer Grundsatz ist.

Du kannst einer Klasse die Referenz auf ihre Erzeugerklasse übergen, indem du bei der Erzeugung this im Konstruktor übergibst. Das dürfte den Zugriff auf eine Getter Methode für text erlauben und macht deinen ganzen statischen Zugriffsbaum überflüssig.


----------



## Kenan89 (5. Mai 2012)

Aha... Jo, das hilft mir schonmal weiter... Ich probiere es gleich aus 

Du meinst quasi so:

```
package exe;

public class Exe {
	
	public static void main(String[] args){
		new frame.Frame();
	}
	
}
```


```
package frame;

import java.awt.BorderLayout;
import java.awt.event.ActionListener;

import javax.swing.JFrame;

public class Frame extends JFrame{
	
	private int framewidth = 500;
	private int frameheight = 500;
	
	private listeners.ListenerAction actionlis = new listeners.ListenerAction(this);//mit this gebe ich Referenz auf diese Klasse weiter
	
	private panels.Menubar menubar  = new panels.Menubar(this);//hier das gleiche
	
	public Frame(){
		build();
	}

	private void build(){
				
		add(menubar, BorderLayout.NORTH);
		
		setTitle("Adventurer");
		setSize(framewidth, frameheight);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
	}
	
	public panels.Menubar getMenu(){
		return menubar;
	}
	
	public ActionListener getActionLis(){
		return actionlis;
	}

}
```


```
package panels;

import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

public class Menubar extends JMenuBar{
	
	private frame.Frame frame;//diesen frame erhält den übergebenen Frame...
	
	private JMenu options = new JMenu("Optionen");
	
	private JMenuItem newGame = new JMenuItem("Neu");
	private JMenuItem loadGame = new JMenuItem("Laden");
	private JMenuItem close = new JMenuItem("Ende");
	
	public Menubar(frame.Frame frame){
		this.frame = frame; //...hier
		build();
		addListeners();
	}
	
	private void build(){
		
		
		add(options);
		options.add(newGame);
		options.add(loadGame);
		options.addSeparator();
		options.add(close);
		
		
	}
	
	private void addListeners(){
		close.addActionListener(frame.getActionLis());
	}
	
	public JMenuItem getJItemNewgame(){
		return newGame;
	}
	
	public JMenuItem getJItemLoadgame(){
		return loadGame;
	}
	
	public JMenuItem getJItemClose(){
		return close;
	}

}
```


```
package listeners;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class ListenerAction implements ActionListener{
	
	private frame.Frame frame;//hier das gleiche! Dieser Frame erhält den übergebenen frame...
	
	public ListenerAction(frame.Frame frame){
		this.frame = frame;//...hier
	}
	
	public void actionPerformed(ActionEvent e){
		Object obj = e.getSource();
		
		if(obj.equals(frame.getMenu().getJItemClose())){
			System.exit(0);
		}
	}

}
```


----------



## Kenan89 (5. Mai 2012)

Das ganze hat mittlerweile an Komplexität gewonnen...
Wieso funktioniert dieses Casten nicht?
(Ab jetzt füge ich nur Code ein, der unbedingt benötigt wird)


```
package frame;

public class Frame extends JFrame{
	
	private panels.Menubar menubar  = new panels.Menubar(this);
	private panels.GamePanel gamepanel = new panels.GamePanel(this);
	
	public Frame(){
		build();
	}

	private void build(){
				
		add(menubar, BorderLayout.NORTH);
		add(gamepanel, BorderLayout.CENTER);
		
	}
	
	public panels.Menubar getMenu(){
		return menubar;
	}
	
	public ActionListener getActionLis(){
		return actionlis;
	}
	
	public KeyListener getKeyLis(){
		return keylis;
	}
}
```


```
package panels;

public class GamePanel extends JPanel {
	
	private frame.Frame frame;
	private Object[] objectslist;	
	private Object[] objects;		
	
	public GamePanel(frame.Frame frame){
		this.frame = frame;
		
		build();
		addkeylistener();
		
		objects.InitObjects initObjects = new objects.InitObjects();
		objectslist = initObjects.getObjects();
		objects = new Object[objectslist.length];
		createObjects();
	}
	
	private void build(){
		setBackground(Color.WHITE);
		setBorder(new LineBorder(Color.BLACK));
	}
	
	private void addkeylistener(){
		setFocusable(true);
		requestFocus();
		addKeyListener(frame.getKeyLis());
	}
	
	private void createObjects(){
		HashMap<String, Object> objectmap = new HashMap<String, Object>();
		
		for(int i=0; i<objects.length; i++){
			objectmap = (HashMap<String, Object>) objectslist[i];
			objects[i] = new objects.Objects();
                        (objects.Objects) objects[i]; //!!!!!!Hier ist das Problem! Ich würde gerne auf die Setter und Getter Methoden der Klasse Objects zugreifen
//Das Problem ist nur, dass sich objects[i] nicht casten lässt, bzw. ich es falsch mache. Die id, x,y
//in Klasse Objects, wird den Werten aus der InitObjects Klasse gleichgesetzt, da wie gesagt,
//initObjects ja eigentlich nur so etwa wie eine JSON Datei ist.
			
		}
	}

}
```


```
package objects;

public class InitObjects {//Das ist quasi so etwas wie die JSON Datei, worin alle nötigen Informationen zu jedem Object aufgelistet sind

	private HashMap<String, Object> objectMap;
	private Object[] objects = new Object[2];
	
	public InitObjects(){
		init();
	}
	
	private void init(){
		objectMap = new HashMap<String, Object>();
		objectMap.put("id", 0);
		objectMap.put("url", "pics/bg/stones.png");
		objectMap.put("x", 1);
		objectMap.put("y", 1);
		objectMap.put("type", "background-image");
		objects[0] = objectMap;
		
		objectMap = new HashMap<String, Object>();
		objectMap.put("id", 1);
		objectMap.put("url", "pics/chars/obj1.png");
		objectMap.put("x", 10);
		objectMap.put("y", 40);
		objectMap.put("type", "human");
		objects[1] = objectMap;
	}
	
	public Object[] getObjects(){
		return objects;
	}
	
}
```


```
package objects;

public class Objects {//jedes Object auf dem GamePanel, wird mithilfe dieser Klasse gezeichnet. Bewegt sich die Figur, soll mit dem setter die x,y Koordinaten bestimmt werden. Also jede Figut auf der Map ist ein Object dieser Klasse
	
	private int id;
	private String url;
	private int x;
	private int y;
	
	public Objects(){
		
	}
	
	//getter
	public int getID(){
		return id;
	}
	public String getURL(){
		return url;
	}
	public int getX(){
		return x;
	}
	public int getY(){
		return y;
	}
	//getter
	public void setID(int id){
		this.id = id;
	}
	public void setURL(String url){
		this.url = url;
	}
	public void setX(int x){
		this.x = x;
	}
	public void setY(int y){
		this.y = y;
	}

}
```


----------



## Final_Striker (5. Mai 2012)

Du solltest versuchen am Besten keine Klassennamen zu verwenden, die schon in der Java API vorhanden sind, wie Frame, Object, Objects uws...


----------



## Kenan89 (5. Mai 2012)

Leider liegt das Problem nicht daran...
Die Fehlermeldung im Code 
	
	
	
	





```
(obj.Obj) objArr[i];
```
(habe jetzt packages und klassen umbenannt) sagt,
dass obj.Obj nichts zugeordnet werden kann.

Ausserdem wie kann ich überprüfen ob ein Begriff in der API existiert? Muss in der API suchen oder gibt es einen schnelleren Weg?

EDIT: Ich habe das jetzt folgendermaßen gemacht:


```
obj.Obj.class.cast(objArr[i]).setX(i+1);
System.out.println(obj.Obj.class.cast(objArr[i].getX());
//mein Programm geht 2x in die for-schleife und als Ergebnis, wird mir in der Konsole angezeigt: 1 und 2,
//d.h. die privaten int in der Klasse Obj im package obj werden für jedes Obj in dem objArr geändert
```

Gibt es eine elegantere Lösung, bzw. ist diese Lösung schlecht?


----------



## Kenan89 (5. Mai 2012)

So, dieses Problem hat sich erledigt.

Jetzt wollte ich mal das Projekt exportieren, um es einem Freund zu zeigen.

Leider werden die Images nicht mitexportiert.

Ich habe gelesen, dass man das mit getClass.getClassLoader.getResource("...") machen sollte, was bei
mir aber nicht klappt.

```
//Klasse GamePanel im package panels
				img = ImageIO.read(
						new File(
								getClass().getClassLoader().getResource("pics/stones.png")
						)
				);
```

Hier meine Ordnerstruktur:


----------



## Fu3L (5. Mai 2012)

Die Bilder müssen mit im src Ordner liegen. Zumidnest funktioniert es bei mir dann^^


```
obj.Obj.class.cast(objArr[i]).setX(i+1);
```

Sowas ist nicht schön^^ (Oder aber ich verstehe es nicht, wobei das wiederrum heißen könnte, dass es unnötig unverständlich ist und das wäre auch wieder nicht schön )

Zudem verstehe ich nicht, wieso du keine imports verwendest für deine Klassen, das wäre doch viel einfacher. Außerdem mag es für dich vllt schöner sein, dass deine Klassen allesamt so heißen wie Klassen der Java API, aber es ist doch so, dass du von uns Hilfe willst. Für uns ist 
	
	
	
	





```
Frame fenster;
```
 ein AWT Frame und kein eigenes Fenster, das von JFrame erbt. Du willst Hilfe, also mach es uns leicht dir zu helfen


----------



## c2delegate (5. Mai 2012)

wtf ist das 
	
	
	
	





```
obj.Obj.class.cast(objArr[i]).setX(i+1);
```
 und das 
	
	
	
	





```
new objects.Objects();
```
 und das 
	
	
	
	





```
public class Frame extends JFrame
```
 und noch so vieles mehr! Das wird nur total unleserlich und sau mies, kein Schwein wird dir helfen wollen/können und du wirst nicht wissen wo hinten und vorne ist! Geh die OO-Grundlagen durch, ehrlich! Versuche aussagekräftige Namen zu verwenden usw. !!!


----------



## Landei (5. Mai 2012)

Bevor du dich völlig verrennst, solltest du vielleicht mal einen Blick auf Slick2D werfen...


----------



## Kenan89 (5. Mai 2012)

Slick2D schaue ich mir auf jeden Fall an, aber für den Anfang möchte ich alles "zu Fuß" erledigen.

Ich habe jetzt eure Vorschläge umgesetzt, und es funktioniert schonmal, dass man seine Fiigur bewegt und er nicht den Panel verlässt.

Würde es sehr nett finden, wenn jemand Zeit und Lust hat, sich den Quellcode anzusehen, um eventuell Probleme aufzudecken. Vielleicht möchte ja auch jemand an dem Projekt mitmachen? Es ist viel zu tun, auch wenn das Projekt nur ein einfaches Spiel sein soll, wo man rumläuft und Leute anspricht(Sprechboxen, Kollosionserkennung,...)


----------



## Kenan89 (7. Mai 2012)

Was genau bietet den Slick2D für Vorteile?


----------



## Apo (7. Mai 2012)

Um Leute für dein Projekt gewinnen zu können, solltest du schon was zum Vorzeigen haben oder eine Projektidee, die die Leute anspricht / vom Hocker haut. Deshalb rate ich dir erstmal zu Quaxlis Tutorial aus diesem Forum. Arbeite es durch und bastle erstmal kleine Spiele wie ein Pong-Klon, ein Snake-Klone etc. Wenn du das dann drauf hast, kann man weiter schauen.

Slick2D hat viele Vorteile, aber das kannst du auch selber lesen. Größter Vorteil in meinen Augen ist die Tatsache, dass es auf LWJGL setzt und damit um Faktor X beim Zeichnen performanter ist als reiner Java-Code. Außerdem wurde darauf geachtet, die API so zu gestalten, dass man eine sehr ähnliche Syntax zu normalen AWT/SWING Code hat.


----------



## Kenan89 (8. Mai 2012)

Hallo,
wie ihr meinem Quellcode entnehmen könnt, werden bei mir alle Objekte in ein Panel nacheinander gezeichnet. Den Helden bewegt man mit den Pfeiltasten und die NPC werden computergesteuert bewegt. Jetzt ist es ja so, dass das zuletzt gezeichnete Bild den höchsten z-Wert hat, d.h. über allen anderen Bildern steht. 

Gibt es eine Möglichkeit in Java z-Werte für BufferedImg zu setzen?


----------



## Kenan89 (8. Mai 2012)

Da fast 3 Stunden vergangen sind, pusche ich mal dieses Thema... Gibt es eine Möglichkeit Java Bildern(Image, oder BufferedImage) einen Index zugeben, der bestimmt, welches Bild über dem anderen liegt?
So etwas wie z-Index in css oder setComponentZOrdner für Componenten in Java.


----------



## Luk10 (8. Mai 2012)

Ohne jetzt deinen Code angeschaut zu haben:

Soweit ich weiß wird durch Swing / Graphics2d kein 2.5D oder 3D (spricht Tiefe) unterstützt. Du kannst aber die Reihenfolge manuell bestimmen indem du die Images in der gewünschte Reihenfolge auf den Screen zeichnest, bzw. sie in einer sortierten Reihenfolge in deiner Liste hast.

Würde dir auch empfehlen vernünftige Klassen und Paketnamen zu finde. Erleichtert das lesen.


----------



## Kenan89 (8. Mai 2012)

Das ist jetzt nämlich das Problem. Momentan sind alle meine Bilder als BufferedImages auf der Spielfläche und sie werden so gezeichnet, wie sie in der InitObjects(so etwas wie ein JSON Datei) eingespeichert sind. Das heisst erst der Hintergrund, dann der Held und dann alle anderen Objekte.

Na gut wenn Graphics keine Tiefe unterstützt mus ich wohl auf JLabel oder eine andere Alternative suchen.


----------



## Landei (8. Mai 2012)

Jetzt kennst du schon einen Vorteil von Slick2D


----------



## Fu3L (8. Mai 2012)

Bevor du irgendwie mit GUI Elementen rumhantierst:
Entweder selbst die Objekte in einer TreeMap<Integer, List<GameObject>> speichern und dann die Liste von oben nach unten Malen (der key ist dann der z-index) oder aber auf irgendwas mit OpenGL umstellen (wie etwa Slick2D)


----------



## Kenan89 (9. Mai 2012)

TreeMap könnte die Lösung sein, denn es sortiert ja alle seine Objekte(in meinem Fall nach einem integer, also z-Wert), dann kann tatsächlich in der richtigen Reihenfolge gezeichnet werden.


----------



## Kenan89 (24. Mai 2012)

So, jetzt ist es soweit.
Jetzt muss ich mich um den z-Index kümmern. Ich würde, wie Fu3l gesagt hat, eine TreeMap nehmen und nach y Wert der Objekte sortieren lassen und anschließen nicht die objListe Graphics übergeben, sondern die sortierte Kopie davon, also den TreeMap.

Aber eine spezielle Lösung bezüglich z-index gibt es nicht in Java, oder? Das mit TreeMap ist ja eigentlich eine umständliche Lösung.

EDIT: Ich arbeite mit Slick. Hat er eine Lösung für so ein Problem parat?


----------



## Kenan89 (24. Mai 2012)

Ich programmiere schon seit einigen Tagen an meinem Spiel und wollte schon mal ein Screenshot zeigen.







Die 2 Objekte bewegen sich und Kollisionen werden entdeckt, sodass sich die Objekte nicht überschneiden. Ausserdem sind die 2 Figuren animiert. 

Nachdem ich auch den z-Index problem gelöst habe, geht es weiter mit den Funktionen des Hauptmenüs(Neu, Speichern, Laden,...). Danach ist Map-Wechsel dran. 

Aber wie gesagt vorerst muss ich das mit dem z-index lösen. Ich würde mit einer TreeMap arbeiten, ausser Slick bietet eine Lösung.


----------



## Fu3L (24. Mai 2012)

Slick sollte sowas auf jeden Fall anbieten^^ Der TreeMap Vorschlag war für reines Java 2D.

Einfach mal Google "Slick 2D z-index"


----------



## Kenan89 (25. Mai 2012)

Ob du  es glaubst oder nicht, ich fand nichts zum Thema Slick und z-index. Nur ein Forum Eintrag worin stand, dass so etwas nicht existiert in Slick. 

Dann werde ich es mal mit TreeMap versuchen.


----------



## Kenan89 (25. Mai 2012)

Der Versuch mit der TreeMap:


```
public class Exe {

	public static void main(String[] args){
		new Exe();
	}
	
	public Exe(){
		ArrayList<Object> objList = new ArrayList<Object>();
		objList.add(new Obj(37,	15,	"t1"));
		objList.add(new Obj(5,	10,	"t2"));
		objList.add(new Obj(7,	15,	"t3"));
		objList.add(new Obj(1,	11,	"t4"));
		objList.add(new Obj(3,	2,	"t5"));
		
                //unsortierte Liste
 		for(int z=0; z<objList.size(); z++){
			System.out.println(
						((Obj)objList.get(z)).getY()
					);
		}
		
		TreeMap<Integer, Obj> tmap = new TreeMap<Integer, Obj>();
		
		for(int i=0; i<objList.size(); i++){
			tmap.put(
					((Obj)objList.get(i)).getY(),
					((Obj)objList.get(i))
				);
		}
		
		for(int z=0; z<tmap.size(); z++){//hier komm ich nicht weiter
			System.out.println(	
						tmap.get(15).getY()
					);
		}
	}
	
	public class Obj{
		
		private int x;
		private int y;
		private String name;
		
		public Obj(int x, int y, String name){
			this.x = x;
			this.y = y;
			this.name = name;
		}
		
		public int getX(){
			return x;
		}
		public int getY(){
			return y;
		}
		public String getName(){
			return name;
		}
	}
}
```

Die Frage ist, was kommt rein in die spitzen Klammern der TreeMap.
Als Key muss jedenfalls der y Wert des Objekts, denn daraus wird
die Reihenfolge bestimmt.
Die Frage ist jetzt ausserdem, wie ich die for Schleife so formuliere,
dass sie genau den im TreeMap gespeicherten Key anspricht, denn
diesen kenn ich ja nicht. 
Hoffe, ihr wisst, was ich meine.

EDIT: 

Ich kann ja nicht sagen:

for(int = 0; i<?; i++){
g.draw(tmap.get(i).getImg(),
g.draw(tmap.get(i).getx(),
g.draw(tmap.get(i).getY()
}

Denn ich kenne weder, die Keys(da sie Y-Koordinate sind), noch die
Grenze für i, noch um wie viel i erhöht werden muss, denn das erste Objekt hat vllt
y-Wert 50, das nächste 100. Ich kann ja nicht vom 50 bis 100 die for-Schleife durchgehen...


----------



## Kenan89 (25. Mai 2012)

So, habe es, etwas umständlich, lösen können:


```
public class Exe {
	
	public static void main(String[] args){
		new Exe();
	}
	
	public Exe(){
		ArrayList<Object> objList = new ArrayList<Object>();
		objList.add(new Obj(37,	15,	"t1"));
		objList.add(new Obj(5,	10,	"t2"));
		objList.add(new Obj(7,	15,	"t3"));
		objList.add(new Obj(1,	11,	"t4"));
		objList.add(new Obj(3,	2,	"t5"));
		
		Integer[] objArr = new Integer[objList.size()] ;
		
		for(int i=0; i<objList.size(); i++){
			objArr[i] = ((Obj)objList.get(i)).getY();
		}

		Arrays.sort(objArr);
		
		TreeMap<Integer, Obj> tmap = new TreeMap<Integer, Obj>();
		
		for(int x=0; x<objList.size(); x++){
			tmap.put(((Obj) objList.get(x)).getY(), ((Obj) objList.get(x)));
		}
		
		for(int z=0; z<objArr.length; z++){
			
			System.out.println("Name: "+tmap.get(objArr[z]).getName()+" / Y-Koordinate: "+tmap.get(objArr[z]).getY());
		}
	}
	
	public class Obj{
		
		private int x;
		private int y;
		private String name;
		
		public Obj(int x, int y, String name){
			this.x = x;
			this.y = y;
			this.name = name;
		}
		
		public int getX(){
			return x;
		}
		public int getY(){
			return y;
		}
		public String getName(){
			return name;
		}
		
	}
	
}
```

Was mache ich?

1. Ich füge der ArrayList objList alle nötigen Objekte hinzu.
2. dann erstelle ich ein Array mit der Länge von objList und füge in einer for-Schleife alle y Werte der Objekte in objList
3. ich lasse das Array objArray sortieren
4. In einer for-Schleife weise ich jede Position in objList der TreeMap tmap zu
5. In einer weiteren for Schleife wandere ich durch das Array objArr und da darin die sortierten Y-Werte in den Positionen gespeichert sind, lasse ich meine tmap nach diesen y-Koordinaten "getten"

So klappt es


----------



## Fu3L (25. Mai 2012)

Sowas muss in die spitzen Klammern:


```
private Map<Integer, List<Entity>> entities = new TreeMap<Integer, List<Entity>>();
```

Bei dir hall anscheinend Obj weil deine Spielobjekte Obj heißen...

Wenn du die TreeMap hast, brauchst du deine normale Liste der Spielobjekte nicht mehr. Und wie garantierst du, dass die Objekte immer dem richtigen z-index zugeordnet werden? Immer wenn du den y-Wert eines Spielobjektes änderst, musst du ihn in eine andere Liste packen. (Vorsicht, dass diese Liste auch existiert).
Beim Zeichnen ist es außerordentlich praktisch, dass eine Iteration über diese Map mit:


```
for(Integer i : entities.keySet()) {
	for(Entity e : entities.get(i)) {
```

direkt in der richtigen Reihenfolge ist. Kleine y-Werte kommen zuerst. Es köntne höchstens sein, dass es Probleme gibt in Slick wegen des verwendeten Koordinatensystems, dass nach hinten die Werte größer werden^^ Dann muss man eben immer -y als Key nutzen.


----------



## Kr0e (25. Mai 2012)

Jep, Integer + TreeMap. So hab ichs das neulich auch gemacht. Ist die beste Variante, wenn man keinen ZBuffer benutzt (Bei Java2D z.b.).

Nur eine Änderung:

Ich würde statt einer Liste ein LinkedHashSet nehmen.  O(1) für reinpacken und entfernen. Linked- weil man die Reihenfolge beim Einfügen vlt. beibehalten will...


----------



## Fu3L (25. Mai 2012)

Stimmt, danke für die Verbesserung 
Finds gut, dass meine Idee anscheinend gebräuchlich ist.. Hab mir das mitten in der Nacht unter Zeitdruck für mein erstes Ludum Dare Spiel ausgedacht^^


----------



## Kenan89 (25. Mai 2012)

Ich würde mir gerne ein Tile Editor programmieren.
Man bastelt sich seine map aus einer png datei, die tiles enthält und speichert sie ab.

Die Frage ist, wie ich es machen kann, dass ich in meinem TileEditor ein Tile auswähle und ihm quasi eine ID vergeben kann, die bestimmt, ob es betreten werden darf oder nicht. Und in welchem Format sollte man es abspeichern, damit auch beim Laden der Spielkarte, Java merkt, dass es Bereiche gibt, die nicht betretbar sind.

Ich weiss, komplexes Thema jetzt, aber einige Schlüsselwörter reichen mir. Ich les mich dann ein.


----------



## Fu3L (25. Mai 2012)

Da gibt es so viele Möglichkeiten, wie es Entwickler gibt, die sich damit beschäftigen^^
Eine Möglichkeit wären fest vergebene IDs: Irgendwo ist eine Tabelle 
1: stone.png; 1 (1 steht für "kann betreten werden")
2: water.png; 0
Im Levelfile steht dann einfach 
1;2;2;1
1;2;2;1

Das hat den Vorteil, dass du damit einen neuen Tiletypen anlegen könntest, ohne jedes Mal eine neue Klasse zu erstellen.


----------



## Network (25. Mai 2012)

Mein letzter TileEditor den ich erstellt hatte und gerade reingeschaut verwendet eine normale Bytecodierung, wobei jedes bit für einen anderen Zustand oder Bild stehen kann, je nachdem wie es interpretiert werden soll.
So steht bei mir, dass erste bit (10000000) für unbetretbar, die weiteren bits werden getrennt mit "&127" und mit diesem byte kann man ein Bild aus einer HashMap abrufen. Jedes Tile besteht bei mir also sowohl im Spiel als auch im Editor aus einem byte, der bei jedem Repaint, das zugehörige Bild abruft.

Ich habe ein paar mehr Zustände weshalb es sich bei mir eig. um 2bytes also um ein short handelt.

Ob eine Figur ein Tile betreten kann bevor sie darüberläuft wird dann an der ID überprüft:

```
if( tileID & 128 == 128 ) move();
```

Aber es handelt sich hier nur um meine persöhnliche Interpretation wie man soetwas handhaben kann. Es liegt alles in deiner Betrachtung wie du es am besten kannst und verstehst.

Gruß
Network


----------



## Kenan89 (25. Mai 2012)

Fu3L hat gesagt.:


> Da gibt es so viele Möglichkeiten, wie es Entwickler gibt, die sich damit beschäftigen^^
> Eine Möglichkeit wären fest vergebene IDs: Irgendwo ist eine Tabelle
> 1: stone.png; 1 (1 steht für "kann betreten werden")
> 2: water.png; 0
> ...



Oho, dieso Methode würde mich aber dazu zwingen, jedes Tile per hand in den Levelfile einzutippen.
Denn das Levelist ja an sich ein einziges großes "background image"
 und bei jedem Schritt des helden muss ich überprüfen, auf welchem Tiletyp er sich befindet(betretbar, nicht betretbar).

EDIT: Oder gibt es Programme, die das erledigen?


----------



## Fu3L (25. Mai 2012)

> Oho, dieso Methode würde mich aber dazu zwingen, jedes Tile per hand in den Levelfile einzutippen.
> Denn das Levelist ja an sich ein einziges großes "background image"
> und bei jedem Schritt des helden muss ich überprüfen, auf welchem Tiletyp er sich befindet(betretbar, nicht betretbar).
> 
> EDIT: Oder gibt es Programme, die das erledigen?



Ich möchte jetzt nicht gemein klingen, aber du sagst oft irgendwas und später genau das Gegenteil...



> Ich würde mir gerne ein Tile Editor programmieren.



Denk mal drüber nach.


----------



## Kenan89 (25. Mai 2012)

Haha... Naja selbst wenn es ein fertiges gibt, würde ich mir gerne eins programmieren, einfach zur Übung.


----------



## Network (26. Mai 2012)

Kenan89 hat gesagt.:


> Haha... Naja selbst wenn es ein fertiges gibt, würde ich mir gerne eins programmieren, einfach zur Übung.



Ich hätte Fu3Ls Antwort jetzt noch weiter interpretiert zu deiner Antwort "Oho, dieso Methode würde mich aber dazu zwingen, jedes Tile per hand in den Levelfile einzutippen.".

Genau deshalb programmierst du doch ein TileEditor der das für dich übernimmt. Die Idee dahinter war meinem Vorschlag sehr ähnlich, dass deine Levels schlussendlich aus Zahlen bestehen, bzw. deinen Tiles jeweils eine Zahl zugeordnet ist, die bestimmt ob es betretbar ist oder nicht und man während dem Spiel dann überprüft ob es sich um ein Einser(nicht betretbar) oder Nuller(betretbar)-Tile handelt. Was wiederum in einer Extradatei gespeichert wird.



> Die Frage ist, wie ich es machen kann, dass ich in meinem TileEditor ein Tile auswähle und ihm quasi eine ID vergeben kann, die bestimmt, ob es betreten werden darf oder nicht. Und in welchem Format sollte man es abspeichern, damit auch beim Laden der Spielkarte, Java merkt, dass es Bereiche gibt, die nicht betretbar sind.



Gruß
Network

PS: Deine Leveldateien bestehen schlussendlich nicht aus den Tilebildern selbst, sondern aus den Namen der Bilder sowie ob betretbar oder nicht.


----------



## GeorgA (29. Mai 2012)

Hallo,

bei:
ist (ob es noch Heute zu finden ist?) ein simplen TileEditor zu finden.
Lizenz -> kostenlos (mit >>open<< java source) 
Wobei simple werde ich (*für DICH*) als relativ bezeichnen.
Der Autor war Joe oder Juddy -> sorry Heute weis ich nicht mehr.
Warum ich mich hier (Forum) wieder >>reinquetsche<<? 
Es könnte eine gute Grundvorlage für deinen eigenen TileEditor sein. (zur Übung)

Gruß
Georg


----------

