# 2D Menü für 3D Spiel



## tdc (18. Jul 2011)

Hi,

Ich habe versucht ein 2D-Menü für mein 3D-Spiel zu programmieren. Einzeln funktioniert das auch jeweils perfekt, aber sobald ich das Spiel über das Menü starte, sieht man nur einen schwarzen Bildschirm. Daraufhin habe ich den Code des Menüs "auseinandergenommen" und herausgefunden, dass es an der Funktion "loadTexture" liegt.

Diese Methode sieht so aus:

```
public Texture loadTexture(String name, String datatype)
	{
		Texture texture = null;
		try
		{
			texture = TextureLoader.getTexture(datatype, new FileInputStream(new File("").getAbsolutePath()+"/src/ressources/images/font/"+name));
		}
		catch (FileNotFoundException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		return texture;
    }
```

Ich benutze lwjgl uns slick zum Laden der Textur. Woran könnte das denn liegen? Die Texturen werden nur für das Menü geladen, das Spiel hat damit gar nichts zu tun.


----------



## Kr0e (18. Jul 2011)

Sicher, dass der Fehler beim Laden liegt ? Ich vermute eher, dass das Problem beim ERSTEN Zeichnen der Textur ist. Was benutzt du denn, für das 3D Spiel ? Reines LWJGL ? Ich kenee ähnlcihe Phänomene wenn gerade per glBindTexture bereits ne TExture bebunden ist und wenn man dann selber dazwischen funkt, ohne die ursprüngliche Texture erneut zu binden, können soclhe Probleme auftreten. Kann bei dir aber auch was anderes sein.

- Ist ohne weitere Infos schwer zu sagen. Generell ist das Laden mit der Funktion aber vollkommen ok.


----------



## tdc (18. Jul 2011)

Danke für die Antwort.

Also ich beschreibe mal, wie ich darauf gekommen bin, dass es an dieser Methode Liegt:
Ich hab das ganze etwas umständlich gestaltet, da ich nicht wollte, dass beim starten des Spiels ein neues Fenster geöffnet wird. Der Anfang des Codes für die Klasse Window sieht so aus:

```
public class Window
{
	long lastFrame;
	int fps;
	long lastFPS;
	
	boolean fullscreen = false;
	
	WindowContent content;
	boolean contentChanged = false;
	
	public void createWindow()
	{
		try
		{
			Display.setDisplayMode(new DisplayMode(800, 600));
			Display.create();
			Display.setLocation(100, 100);
		}
		catch (LWJGLException e)
		{
			e.printStackTrace();
			System.exit(0);
		}
		
		//setContent(new MainMenu(this));
		
		Game game = new Game();
		setContent(game);
		game.initGame();
		

		while (!Display.isCloseRequested())
		{
			int delta = getDelta();
			update(delta);
			content.update(delta);
			if(!contentChanged)
			{
				updateFPS();
				content.drawOpenGL();
				Display.update();
				Display.sync(200); // cap fps to 60fps
			}
			else
			{
				contentChanged = false;
			}
		}
	}
	
	public void setContent(WindowContent c)
	{
		content = c;
		content.initOpenGL();
		lastFPS = getTime();
		getDelta();
		contentChanged = true;
	}
        ...
```


Eigentlich steht an der Stelle:

```
//setContent(new MainMenu(this));
		
		Game game = new Game();
		setContent(game);
		game.initGame();
```
nur

```
setContent(new MainMenu(this));
```
aber zum testen habe ich das mal so geändert.

Also mit der Methode "setContent(WindowContent c)" kann man den Inhalt des Fensters verändern und auch nur der derzeitige content wird geupdated, gezeichnet, etc. .

Der Code (ganz oben) funktioniert so, aber sobald ich die Kommentarschrägstriche vor "setContent(new MainMenu(this))" entferne, geht es nicht mehr. Genau das kommt mir merkwürdig vor, denn das MainMenu wird noch nichtmal gezeichnet.

Die Klasse MainMenu wiederrum sieht so aus:

```
public class MainMenu
	extends WindowContent
{
	Window window;
	Vector<MenuButton> labels;
	
	public MainMenu(Window w)
	{
		window = w;
		loadTexture("Singleplayer.png", "PNG");
		
		// liegt es an loadTexture ???
		
		/*
		labels = new Vector<MenuButton>();
		labels.addElement(new MenuButton(loadTexture("Singleplayer.png", "PNG"), 100, 100));
		labels.addElement(new MenuButton(loadTexture("Multiplayer.png", "PNG"), 100, 180));
		labels.addElement(new MenuButton(loadTexture("Options.png", "PNG"), 100, 260));
		labels.addElement(new MenuButton(loadTexture("Credits.png", "PNG"), 100, 340));
		labels.addElement(new MenuButton(loadTexture("Quit.png", "PNG"), 100, 420));
		*/
	}

	public void initOpenGL()
	{
		int width = Display.getDisplayMode().getWidth();
		int height = Display.getDisplayMode().getHeight();
		
		glEnable(GL_TEXTURE_2D);               
        
		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);          
        
        	// enable alpha blending
        	glEnable(GL_BLEND);
        	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        
        	glViewport(0,0,width,height);
		glMatrixMode(GL_MODELVIEW);

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(0, width, height, 0, 1, -1);
		glMatrixMode(GL_MODELVIEW);
	}
	
	public void drawOpenGL()
	{
		...
		//unwichtig wird beim Test eh nicht ausgeführt
		...
	}

	public void update(int delta)
	{
		...
		//unwichtig wird beim Test eh nicht ausgeführt
		...
	}
	
	public Texture loadTexture(String name, String datatype)
	{
		Texture texture = null;
		try
		{
			texture = TextureLoader.getTexture(datatype, new FileInputStream(new File("").getAbsolutePath()+"/src/ressources/images/font/"+name));
		}
		catch (FileNotFoundException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		return texture;
    }
```

Erst habe ich gedacht, es könnte an initOpenGL() liegen, aber durch ausprobieren hab ich rausgefunden, dass es nur an loadTexture() liegen kann.

Endergebnis: Statt dem Spiel nur ein schwarzer Bildschirm, FPS-Counter zeigt konstant 200 FPS an.

Ausserdem: Im Spiel verwende ich bisher KEINE Texturen, sondern nur Farbe und Striche, an fehlerhaft geladenen Texturen sollte es also nicht liegen.


Hoffentlich kann mir jemand helfen, ich weiß nämlich nicht mehr weiter. Vielleicht habe ich auch nur etwas einfaches übersehen. Jedenfalls brauche ich loadTexture() eigentlich nur zum Laden von Bildern für das 2D-Menü.


----------



## Evil-Devil (19. Jul 2011)

Erste Frage: Wieso willst du unbedingt verhindern das ein Fenster geöffnet wird? Das will mir irgendwie nicht in den Sinn.

Zweitens: Die Grundstruktur deiner LWJGL App sieht irgendwie wirr aus. Hast du dir im Wiki bzw. Util/Src Jar die Beispiele angeschaut? Die sind imho wesentlich besser strukturiert.

Wenn ich das richtig interpretiere versuchst du jeweils den Fensterinhalt zu ersetzen. Dann verliere ich den Faden. IMHO wird deine Zeichenlogik einfach nicht mehr aufgerufen.

Anbei nen Game-Beispiel: Space Invaders Example Game - LWJGL


----------



## Kr0e (19. Jul 2011)

Ich bin leider nicht mehr so fit in pure OpenGl. Das sind die ganzen fiesen Engines schuld... 

Aber rein von der Logig her: Wenn es nach deinem Texture-Load-Aufruf nciht mehr läuft, dann kann es ja eigentlich nur noch eins sein: Deine Texture ist schwarz(warum auch immer) und verdeckt alles.

Vlt. das glMatrixMode(GL_MODELVIEW); bevor du glEnable(GL_BLEND) aufrufst. Aber ich rate hier grad wirklich rum, also keine Garantie...

Vlt. mal zum Testen das BLEND rauslassen. Ansonsten: Rufst du denn iwo auch glBindTexture auf ? Ohne die Texture zu binden, dürfte das Darstellen auch nciht funzen.

Oder das glViewport mal innnerhalb von:

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        -> glViewPort....
        glOrtho(0, width, height, 0, 1, - 1);

Vlt als generelle Lösung für so einen Fall: Versuch das einfacshte Szenario ans Laufen zu bekommen, also ohne blending usw. einfach simpel gerenderte Texturen.

Es können ja auch die Texture-Koordinaten nicht stimmen, die du mit glTexCoords beim rendern übergibst.

Könnet viele Ursachen haben. 

Ich hoffe, dass vlt einer meiner total dahin-gewürfelten Ansätze dich weiterbringen 

Gruß,

Chris


----------



## tdc (19. Jul 2011)

An den ganzen OpenGL-Befehlen bei initOpenGL() kann es auch nicht liegen, da, auch wenn ich diese Befehle beim Menü komplett rausnehme, beim Spiel alles schwarz ist.

Naja, dann werde ich es wohl mal mit 2 Fenstern versuchen, auch wenn ich mir nicht sicher bin, ob das die beste Lösung ist.

Edit: Ja, mit der 2-Fenster-Lösung geht es.


----------

