Java Spezielles Problem: Slick 2D sampleTexture.draw() in Sokoban-Klon tut nichts

Chillosoph

Ensign
Registriert
Juli 2010
Beiträge
139
Hi @all!

Ich hoffe, dass mein Problem nicht zu speziell für dieses Forum ist, ich habe bereits in das Entwicklerforum gepostet aber leider keine Antwort erhalten.

Ich versuche einen Sokoban Klon in Java zu schreiben und verwende dafür das Slick 2D Plugin. Da Spieleprogrammierung für mich Neuland ist hangel ich mich mehr oder weniger an einem Tetristutorial entlang.

Probleme habe ich nun beim rendern des Levels bekommen. Die Levelstruktur ist in einem 2-Dimensionalen Array hinterlegt. Jedes Zeichen steht für ein Element, z.B. '#' für ein Stück Mauer. Dieses Array wird dann durchlaufen und je nach Zeichen das entsprechende Stück Textur gerendert. Soweit die Theorie. Leider funktioniert das rendern nicht, die Funktion sampleTexture.draw() macht einfach nichts. Nun bin ich mit meinem Latein am Ende. Habt ihr vielleicht eine Idee woran das liegen könnte? Falls noch Fragen auftauchen, nur zu!

Nachstehend noch der Code:

Variablen:
renderX: Startpunkt der x-Koordinate
renderY: Startpunkt der y-Koordinate
renderOffsetX: #Pixel, um die das nächste Stück Textur in der Horizontalen versetzt wird
renderOffsetY: #Pixel, um die das nächste Stück Textur in der Vertikalen versetzt wird

'#' = Mauer, ' ' = freie Fläche, '$' = Kiste, '@' = Startposition der Spielfigur

Code:
@Override
public void render(GameContainer gamecontainer, StateBasedGame sbg, Graphics gc) throws SlickException {
        
        ingameBackground.draw(0, 0);
      
        int i, j;
        for (i = 0; i < lvlLoader.lvlSize; i++) {           
            for (j = 0; j < lvlLoader.lvlSize; j++) {
                char tempChar = lvlLoader.lvlArray[i][j];
                        
                if (tempChar == '#') {
                    lvlTextureWall.draw(renderX + renderOffsetX, renderY + renderOffsetY);
                } 
                if (tempChar == ' ') {
                    lvlTextureGras.draw(renderX + renderOffsetX, renderY + renderOffsetY);
                }
                if (tempChar == '$') {
                    lvlTextureBox.draw(renderX + renderOffsetX, renderY + renderOffsetY);
                }
                if (tempChar == '@') {
                    lvlTextureGras.draw(renderX + renderOffsetX, renderY + renderOffsetY);
                    //Spielfigur rendern, fehlt noch in textures.png
                }             
                renderOffsetX += 50;                   
            }
            renderOffsetY += 50;
            renderOffsetX = 0;
        }
    }
 
Die Images könnten leer oder deine Berechnungen falsch sein, mach doch mal testweise am Anfang der render:
PHP:
ingameBackground.draw(0, 0);
lvlTextureWall.draw(0, 0);

Oder poste mal wo/wie die lvl-Images erstellt werden.
 
Hey, danke für deine Antwort!

Was in der Tat funktioniert ist folgendes:

lvlTextureGras.draw(renderX, renderY);

außerhalb und innerhalb der for-Schleife als auch innerhalb der if-Anweisung.
Was also nicht richtig funktioniert ist die Berechnung der Koordinaten:

lvlTextureGras.draw(renderX + renderOffsetX, renderY + renderOffsetY);

In der Hauptmenüklasse funktioniert ein ähnliches Konstrukt allerdings ohne Probleme:
(exitGameScale beschreibt die Vergrößerung der Textur, wird angepasst wenn man mit der Maus drüberfährt. Dadurch entsteht ein "highlight"-Effekt.)

exitGameOption.draw(menuX, menuY + 130, exitGameScale);

Wie könnte ich denn die Koordinaten trotzdem zur Laufzeit berechnen lassen?
Leider ist es wenig praktikabel bei einer Levelgröße von 6x6 Felder schon 36 Koordinaten vorzuberechnen.

Vielen Dank für deine Hilfe!

Die Variablen renderX, renderY, renderOffsetX und renderOffsetY sind übrigens alle private static int.
Nachstehend noch der Code für die Imagezuweisung:

Code:
    Image ingameBackground = null;
    Image textures = null;
    Image lvlTextureWall = null;
    Image lvlTextureGras = null;
    Image lvlTextureBox = null;
    Image lvlTextureIndy = null;

Code:
   ingameBackground = new Image("/data/img/ingameBackground.jpg");
   textures = new Image("/data/img/textures.png");
   lvlTextureWall = textures.getSubImage(0, 0, 46, 46);
   lvlTextureGras = textures.getSubImage(55, 0, 46, 46);
   lvlTextureBox = textures.getSubImage(116, 0, 46, 46);


edit: Habe den Code jetzt erstmal umgeschrieben, sodass innerhalb des Methodenaufrufs keine Addition vorkommt:

Code:
@Override
    public void render(GameContainer gamecontainer, StateBasedGame sbg, Graphics gc) throws SlickException {
        ingameBackground.draw(0, 0);
        int i, j;
        for (i = 0; i < lvlLoader.lvlSize; i++) {           
            for (j = 0; j < lvlLoader.lvlSize; j++) {
                char tempChar = lvlLoader.lvlArray[i][j];
                               
                if (tempChar == '#') {
                    lvlTextureWall.draw(renderX, renderY);
                }
                
                if (tempChar == ' ') {
                    lvlTextureGras.draw(renderX, renderY);
                }
                if (tempChar == '$') {
                    lvlTextureBox.draw(renderX, renderY);
                }
                if (tempChar == '@') {
                    lvlTextureGras.draw(renderX, renderY);
                    //Spielfigur rendern, fehlt noch in textures.png
                }        
                renderX += 50;                
            }
            renderX = 250;
            renderY += 50;
        }
    }

Allerdings funktioniert jetzt nichtmal mehr
lvlTextureGras.draw(renderX, renderY);
Wenn ich die Koordinaten per Hand eintrage wird die Textur weiterhin gerendert, aber das kann ja nicht im Sinne des Erfinders sein. Hat vielleicht noch jemand eine Idee?

Danke im vorraus!
 
Zuletzt bearbeitet:
renderX & Y werden am Anfang der render() nicht initialisert, ich nehme an das der Framework diese Funktion regelmässig aufruft, dann werden renderX & Y "explodieren", weil sie immer größer werden.

So müsste es funktionieren:
PHP:
@Override
    public void render(GameContainer gamecontainer, StateBasedGame sbg, Graphics gc) throws SlickException {
        ingameBackground.draw(0, 0);
        int lvlSize = lvlLoader.lvlSize;
        int tileSize = 50;
        int yCord = renderOffsetY;
        for (int i = 0; i < lvlSize; i++) {
            int xCord = renderOffsetX;
            for (int j = 0; j < lvlSize; j++) {
                char tempChar = lvlLoader.lvlArray[i][j];
                             
                if (tempChar == '#') {
                    lvlTextureWall.draw(xCord, yCord);
                }
              
                if (tempChar == ' ') {
                    lvlTextureGras.draw(xCord, yCord);
                }
                if (tempChar == '$') {
                    lvlTextureBox.draw(xCord, yCord);
                }
                if (tempChar == '@') {
                    lvlTextureGras.draw(xCord, yCord);
                    //Spielfigur rendern, fehlt noch in textures.png
                }      
                xCord += tileSize;
            }
            yCord += tileSize;
        }
    }
 
Awesome! Ist das erstemal das es klappt. Allerdings muss ich zugeben, dass ich die Begründung nicht ganz verstanden habe. Wärst du so nett mir das Problem nochmal etwas genauer zu erklären?
Danke erstmal für die kompetente Hilfe!
Peace
 
Chillosoph schrieb:
Wärst du so nett mir das Problem nochmal etwas genauer zu erklären?
So wie die Paint()-Methode in Java/C# wird die render() regelmässig von der GameEngine aufgerufen um ein neues Bild darzustellen. Wenn man dann aber mit statischen Variablen arbeitet die nur irgendwann mal initialisiert worden sind (z.B: renderY = 0) und von der render() ständig erhöht werden (lvlLoader.lvlSize mal wird 'renderY += 50' ausgeführt), so wird der Wert von renderY immer größer und "läuft" aus dem sichtbaren Bereich hinaus.
Also nach dem ersten mal render() ist renderY dann schon lvlLoader.lvlSize*50, beim zweiten mal 2*lvlLoader.lvlSize*50 und so weiter ..
 
Hi lynxx,

vielen Dank für deine Erklärung und die schnelle Hilfe!
Ich denke ich habe das Problem nun besser verstanden.
Peace!
 
Zurück
Oben