# Spielemap erstellen



## altair (5. Aug 2014)

Hallo,

ich habe folgendes problem, nur leider komme ich null dahinter was ich tun soll..

ich soll ein pacmanspiel erstellen, was nicht so schwer ist, nur das problem ist, dass ich eine vorgefertigte textdatei habe, die, die map/karte repräsentierne soll (ICH ARBEITE MIT SLICK2D)

so sieht die textdatei ungefähr aus :

XXXXXXXXXXXXXXXXX
XP TXT PX
X XX XXXXXXX XX X
X X X X X
X XXX X XXX X
XXX XUX X XUX XXX
X X X
X XXXXXXXXXXXXX X

die X sollen die wände sein, P sollen die respawnorte des pacman sein
(der rest ist vorerst irrelevant)

Nun weiß ich aber nicht wie ich das machen soll
man sagte mir was vom parsen... nur weiß ich leider null wie ich das hier anstellen soll


----------



## altair (5. Aug 2014)

```
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class Main {

	public static void main(String[] args) {
		Reader reader = null;
		try
		{
		  reader = new FileReader( "Minimal.txt" );

		  for ( int c; ( c = reader.read() ) != (1*-1); )
		    System.out.print( (char) c );
		}
		catch ( IOException e ) {
		  System.err.println( "Fehler beim Lesen der Datei!" );
		}
		finally {
		  try { reader.close(); } catch ( Exception e ) { e.printStackTrace(); }
		}
	}
}
```


bistjetzt kam ich so weit, dass ich eine textdatei richtig lesen und ausgeben kann
aber was nun?


----------



## altair (6. Aug 2014)

```
public void init(GameContainer container, StateBasedGame game)
			throws SlickException {

		// Hintergrund laden

		Entity background = new Entity("background"); // Entitaet fuer
														// Hintergrund
		
		background.setPosition(new Vector2f(400, 300)); // Startposition des
														// Hintergrunds
		
		background.addComponent(new ImageRenderComponent(new Image(
				"/gfx/blackscreen.JPG"))); // Bildkomponente

		// Hintergrund-Entitaet an StateBasedEntityManager uebergeben
		StateBasedEntityManager.getInstance().addEntity(stateID, background);

		// Bei Drücken der ESC-Taste zurueck ins Hauptmenue wechseln
		Entity esc_Listener = new Entity("ESC_Listener");
		KeyPressedEvent esc_pressed = new KeyPressedEvent(Input.KEY_ESCAPE);
		esc_pressed.addAction(new ChangeStateAction(Pacman.MAINMENU_STATE));
		esc_Listener.addComponent(esc_pressed);
		entityManager.addEntity(stateID, esc_Listener);

		in = container.getInput();
		x = 10;
		y = 10;
		playerImg = new Image("/gfx/Pacman.jpg");
	}
```

und das ist meine mainmenu, sie erstellt ein blackscreen auf dem dann ein gelbes pacmen am oberen rand zu sehen ist
nun will ich aber auf diesem blackscreen eine map haben, die ausgehend von einer textdatei erstellt werden soll.. siehe oben 

ich würde mich über eure hilfe sehr freuen


----------



## lord239123 (6. Aug 2014)

Wird denn schon dein Spieler auf der leeren Map gezeichnet?

Wie bereits gesagt, solltest du ein 2dimensionales Array erstellen, welches du mit den Infos aus der Textdatei fütterst.
Das Array ist deshalb notwendig, da du nicht bei jedem repainten des Bildschirmes die Textdatei neu einlesen möchtest.
Nachdem du die Informationen im Array gespeichert hast, kannst du dich daran machen, das erste mal eine Map zu zeichnen.
Dafür musst du erst einmal definieren, wie groß die einzelnen Felder sein sollen.
In meinem Beispiel nehme ich jetzt einfach einmal 20*20 Pixel.

Dies ist nur ein kleines Codebeispiel, welches du noch in deinen Code einbauen musst.
Ich gehe hier auch davon aus, dass bereits ein Array namens map bereits existiert und mit Infos gefüttert wurde.


```
for (int y = 0; y < map.length; y++) 
		{
			for (int x = 0; x < map[y].length; x++) 
			{
				//zeichne Feld map[y][x] an Poisition x*20, y*20
			}
		}
```

Hoffentlich kann dir dieses kleine Beispiel helfen, allerdings musst du den Rest selber noch implementieren.
Am besten versuchst du das ganze erst einmal ohne Slick mit Swing.


----------



## kaoZ (6. Aug 2014)

Hier mal eine einfache Konsolenversion mit Integern ,


```
import java.io.BufferedReader;
import java.io.InputStreamReader;


public class Map{

	private int[][] map;
	private int rows;
	private int cols;
	
	public Map(){}
	
	public void readMap(String path){
		
		InputStreamReader in;
		BufferedReader reader;
	
		try {
			in = new InputStreamReader(getClass().getResourceAsStream(path));
			reader = new BufferedReader(in);
			
			// read size
			
			rows = Integer.parseInt(reader.readLine());
			cols = Integer.parseInt(reader.readLine());
			
			// init map
			map = new int[rows][cols];
			
			// read lines
			
			for (int row = 0; row < rows; row++) {
				String line = reader.readLine();
				String[] tokens = line.split("\\s+");
				for (int col = 0; col < cols; col++) {
					map[row][col] = Integer.parseInt(tokens[col]);
				}
			}
			
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	
	public void printMap(){
		for (int row = 0; row < map.length; row++) {
			for (int col = 0; col < map[0].length; col++) {
				
				if(map[row][col] == 0) {
					System.out.print("X");
				}
				if(map[row][col] == 1) {
					System.out.print("O");
				}
				
			}
			System.out.println();
		}
	}
	
	public static void main(String[] args){
		
		Map map = new Map();
		
		map.readMap("/dev/eflow/test/samplemap.map");
		map.printMap();
		
	}
	
}
```

Das hier ist die map Datei dazu 


```
5
5
1 1 1 1 1
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1
1 1 1 1 1
```

dementsprechend führt es zu folgender Ausgabe :


```
OOOOO
OXXXO
OXXXO
OXXXO
OOOOO
```

Wie du das ganze letzten endes umsetzt / zeichnen lässt, bleibt ja ganz dir überlassen 

Denk aber daran das spätestens wenn du zum zeichnen in swing kommst, ein Array so aufgebaut ist int[y achse][x achse], während das koordinatensystem im Grafikkontext genau umgekehrt ist , also x und dann y koordinaten verwendet, sonst geht es dir wie mir und du suchst dir nen wolf warum die map nun spiegelverkehrt gezeichnet wird :applaus:


----------



## altair (6. Aug 2014)

erstmal vielen dank für deine Antwort!
mein aktueller stand sieht zurzeit so aus:


```
package de.tu_darmstadt.gdi1.pacman.view;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Vector2f;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;

import eea.engine.action.basicactions.ChangeStateAction;
import eea.engine.component.render.ImageRenderComponent;
import eea.engine.entity.Entity;
import eea.engine.entity.StateBasedEntityManager;
import eea.engine.event.basicevents.KeyPressedEvent;

/**
 * @author
 * 
 *         Diese Klasse repraesentiert das Spielfenster eines pacmans
 * 
 */
public class GameplayState extends BasicGameState {

	public static Input in; // variable für die key events
	public static int x; // repräsentiert die position auf der x achse
	public static int y; // repräsentiert die position auf der y achse
	public Image playerImg; // stellt das pacman ding da
	public Image lab;
	protected int stateID; // stellt ein state da
	protected StateBasedEntityManager entityManager; // nimmt die entitäten auf

	// spielemodus state
	GameplayState(int sid) {
		stateID = sid;
		entityManager = StateBasedEntityManager.getInstance();
	}

	/**
	 * Wird vor dem (erstmaligen) Starten dieses States ausgefuehrt
	 */
	public void init(GameContainer container, StateBasedGame game)
			throws SlickException {

		// Hintergrund laden

		Entity background = new Entity("background"); // Entitaet fuer
														// Hintergrund

		background.setPosition(new Vector2f(400, 300)); // Startposition des
														// Hintergrunds

		background.addComponent(new ImageRenderComponent(new Image(
				"/res/pictures/menu/blackscreen.JPG"))); // Bildkomponente

		// Hintergrund-Entitaet an StateBasedEntityManager uebergeben
		StateBasedEntityManager.getInstance().addEntity(stateID, background);

		// Bei Drücken der ESC-Taste zurueck ins Hauptmenue wechseln
		Entity esc_Listener = new Entity("ESC_Listener");
		
		KeyPressedEvent esc_pressed = new KeyPressedEvent(Input.KEY_ESCAPE);
		esc_pressed.addAction(new ChangeStateAction(Pacman.MAINMENU_STATE));
		
		esc_Listener.addComponent(esc_pressed);
		entityManager.addEntity(stateID, esc_Listener);

		// nötig für die Keyevents
		in = container.getInput();
		// startpunkte des Pacmans
		x = 10;
		y = 10;
		// bild des pacmans
		playerImg = new Image("/res/pictures/menu/Pacman.jpg");
		lab = new Image("/res/pictures/menu/X0.png");
	}

	/**
	 * Wird vor dem Frame ausgefuehrt/ updatet die ganze zeit
	 */
	public void update(GameContainer container, StateBasedGame game, int delta)
			throws SlickException {

		// Keyevents werden hier aufgeführt
		
		entityManager.updateEntities(container, game, delta);
		
		if (in.isKeyDown(Input.KEY_UP) || in.isKeyDown(Input.KEY_W)) {
			playerImg = new Image("/res/pictures/menu/Pacman2.jpg");
			y -= 3;
		}
		if (in.isKeyDown(Input.KEY_DOWN) || in.isKeyDown(Input.KEY_S)) {
			playerImg = new Image("/res/pictures/menu/Pacman1.jpg");
			y += 3;
		}
		if (in.isKeyDown(Input.KEY_LEFT) || in.isKeyDown(Input.KEY_A)) {
			playerImg = new Image("/res/pictures/menu/Pacman3.jpg");
			x -= 3;
		}
		if (in.isKeyDown(Input.KEY_RIGHT) || in.isKeyDown(Input.KEY_D)) {
			playerImg = new Image("/res/pictures/menu/Pacman.jpg");
			x += 3;
		}
	}

	/**
	 * Wird mit dem Frame ausgefuehrt
	 */

	public void render(GameContainer container, StateBasedGame game, Graphics g)
			throws SlickException {

		Reader reader=null;
		int x1 = 100*4;
		int y1 = 100*4;
		try {
			reader = new FileReader("res/levels/Minimal.txt");
			for (int c; (c = reader.read()) != (1 * -1);) {
				x1 = x1 - 30;
				y1 = y1 - 30;
				if (c == 'X')
					g.drawImage(lab, x1, y1);
			}
		} catch (IOException e) {
			System.err.println("Fehler beim Lesen der Datei!");
		} finally {
			try {
				reader.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		// StatedBasedEntityManager soll alle Entities rendern
		entityManager.renderEntities(container, game, g);

		// pacman wird an den X und Y koordianten gespawnt und gezeichnet
		g.drawImage(playerImg, x, y);
	}

	@Override
	public int getID() {
		return stateID;
	}
}
```

Hier ist es wichtig zu wissen, dass das image lab ein teil des labyrinths im pacman darstellen soll
mein problem ist es nun, dass ich es nicht hinkriege, dass dieses image richtig auf dem spielefenster dargestellt wird

meine funktion liest zwar die textdatei und kann einzelne zeichen lesen, aber irgendwie klappt es nicht ganz, dass das bild gezeichnet wird :/


----------



## Androbin (6. Aug 2014)

Könntest du uns bitte einen Screenshot schicken?


----------



## altair (6. Aug 2014)

also so sieht mein hauptmenü aus:







und so sieht mein gameplay aus:
(ich habe mit einem pfeil versucht zu zeigen, dass dort an der ecke einen teil des labyrinths zu sehen ist, also meine lab.img)


----------



## Androbin (7. Aug 2014)

So wie es aussieht, gibt es ein Problem bei der Skalierung!
Wo/Wie legst du denn fest, wie groß ein Feld ist/gezeichnet werden soll?


----------



## altair (7. Aug 2014)

Das lege ich bei meiner Mainklasse fest, jedoch aber muss ich eins sagen, egal wie ich die positon meines lab einsetze, ständig sehe ich nur einen kleinen teil an einer ecke ( das heißt ich kriege es nicht hin dass das labyrinth mitten auf dem display zusehen ist

hier meine main :


```
package de.tu_darmstadt.gdi1.pacman.main;

import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.SlickException;

import de.tu_darmstadt.gdi1.pacman.view.Pacman;

public class Main
{
	
	
    public static void main(String[] args) throws SlickException
	{	 
		// standardpfade initialisieren
		setPaths();

		// engine starten
		Pacman game = new Pacman();
		AppGameContainer app = new AppGameContainer(game);

		// konfiguration festlegen
		app.setDisplayMode(800, 600, false);
		app.setShowFPS(false);
		app.setTargetFrameRate(60);
		app.start();
	}

	private static void setPaths()
	{
		String osName = System.getProperty("os.name").toLowerCase();
    	// Setze den library Pfad abhaengig vom Betriebssystem
    	if (osName.contains("windows")) {
    		System.setProperty("org.lwjgl.librarypath",System.getProperty("user.dir") + "/lib/lwjgl-2.9.0/native/windows");
    	} else if (osName.equals("mac os x")) {
    		System.setProperty("org.lwjgl.librarypath", System.getProperty("user.dir") + "/lib/lwjgl-2.9.0/native/macosx");
    	} else {
    		System.setProperty("org.lwjgl.librarypath", System.getProperty("user.dir") + "/lib/lwjgl-2.9.0/native/" +System.getProperty("os.name").toLowerCase() +'"');
    	}
		
		System.err.println(System.getProperty("org.lwjgl.librarypath"));
        System.err.println(System.getProperty("java.library.path"));
	}
}
```


----------



## altair (7. Aug 2014)

ich bin mal auf deinem vorschlag eingegangen und habe die bildschirm größe von 800,600  auf 1000,800
verändert.. dabei kam das raus :




anscheinend liegt es tatsächlich dran, nur weiß ich leider nicht wie ich das problem nun lösen kann


----------



## kaoZ (7. Aug 2014)

Das wird daran liegen wie du deine map zeichnest, 


```
public void render(GameContainer container, StateBasedGame game, Graphics g)
            throws SlickException {
 
        Reader reader=null;
        int x1 = 100*4;
        int y1 = 100*4;
        try {
            reader = new FileReader("res/levels/Minimal.txt");
            for (int c; (c = reader.read()) != (1 * -1);) {
                x1 = x1 - 30;
                y1 = y1 - 30;
                if (c == 'X')
                    g.drawImage(lab, x1, y1);
            }
```

du zeichnest einfach ein dein Bild immer an den stellen x1 und x2 dessen werte sich immer nur um je 30 pixel in die jeweilige richtung ändern.

Du möchtest aber das deine map auf den jeweiligen screen und dessen größe angepasst und gezeichnet wird, dann musst du diese werte eben auch mit einbeziehen.


----------



## Androbin (8. Aug 2014)

kaoZ hat gesagt.:
			
		

> Das wird daran liegen wie du deine map zeichnest,
> 
> 
> ```
> ...



Und außerdem:
Ist es wirklich nötig, die Map in jedem Frame neu einzulesen?:


> ```
> ...
> reader = new FileReader("res/levels/Minimal.txt");
> ...
> ```


----------



## kaoZ (8. Aug 2014)

Da hat er wohl vollkommen Recht, habe ich beim überfliegen direkt übersehen ^^


----------

