Du bist nicht angemeldet.

Werbeanzeige

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 524

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

1

27.06.2017, 22:06

[LibGDX] Fehler beim Zeichnen von Objekten in einer ArrayList

Hallo,

das Zeil des Programms soll es erstmal sein, eine 200x200 große TileMap darzustellen und in die Mitte jedes Tiles eine Textur zu platzieren. Danach sollen diese Texturen noch verbunden werden, jedoch ist dies nicht das Thema des Threads.

Hier erstmal der relevante Code:

Play.java:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public class Play implements Screen {
    
    private SpriteBatch batch;
    
    private TiledMap map;
    private OrthogonalTiledMapRenderer renderer;
    private OrthographicCamera camera;
    private ArrayList<Tile> tileList;

    @Override
    public void show() {
        // TODO Auto-generated method stub
        
        batch = new SpriteBatch();
        
        map = new TmxMapLoader().load("map.tmx");
        
        renderer = new OrthogonalTiledMapRenderer(map);
        
        // After "show", "resize" will be called anyway, so we have not to give the size here
        camera = new OrthographicCamera();
        
        TiledMapTileLayer tileLayer = (TiledMapTileLayer)map.getLayers().get(0);
        
        tileList = new ArrayList<Tile>();

        // Go through all tiles
        for (int x = 0; x < tileLayer.getWidth(); x++) {
            for (int y = 0; y < tileLayer.getHeight(); y++) {
                //Cell cell = tileLayer.getCell(x, y);
                
                // Create a new "tile"
                Tile tile = new Tile();
                tile.setPosition((15 * x) / 2 - tile.getWidth() / 2, (15 * y) / 2 - tile.getHeight());
                
                // Add the tile to the list
                tileList.add(tile);
            }
        }
    }

    @Override
    public void render(float delta) {
        // TODO Auto-generated method stub

        // Handle the user's input
        handleInput();
        
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        
        renderer.setView(camera);
        renderer.render();
        
        batch.begin();      
        for (int i = 0; i < tileList.size(); i++) {
                        // EDIT: HIER IST DAS HAUPTPROBLEM! //
            //tileList.get(i).draw(batch);
        }       
        batch.end();
    }


Tile.java:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class Tile extends Sprite {

    private Vector2 position;

    private Sprite sprite;
    private Texture texture;

    public Tile() {
        position = new Vector2(0,0);

        texture = new Texture(Gdx.files.internal("tile2.png"));
        sprite = new Sprite(texture);
        
// DEBUG OUTPUT
        System.out.println("TILE");
    }

    //********//
    // SETTER //
    //********//
    public void setPosition(float x, float y) {
        position.set(x, y);
        sprite.setPosition(position.x, position.y);
    }
    public void setPosition(Vector2 pos) {
        position.set(pos);
        sprite.setPosition(position.x, position.y);
    }

    //********//
    // GETTER //
    //********//
    public Vector2 getPosition() { return position; }
    public float getPosition_X() { return position.x; }
    public float getPosition_Y() { return position.y; }

    public Sprite getSprite() { return sprite; }
}


Starte ich das Programm, bekomme ich nach einer kleinen Wartezeit diese Fehler:
Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.badlogic.gdx.graphics.g2d.SpriteBatch.flush(SpriteBatch.java:961)
at com.badlogic.gdx.graphics.g2d.SpriteBatch.draw(SpriteBatch.java:568)
at com.badlogic.gdx.graphics.g2d.Sprite.draw(Sprite.java:515)
at de.conrad.screens.Play.render(Play.java:75)
at com.badlogic.gdx.Game.render(Game.java:46)
at de.conrad.Main.render(Main.java:16)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:223)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:124)

Kommentiere ich Zeile 57 in Play.java (oberer Code) aus, bekomme ich diese Fehler nicht mehr. Da es auch eine NullPointerException ist, denke ich, dass an einer Stelle Informationen verloren gehen, welche nicht verloren gehen sollten. Aber wie bekomme ich das Problem gelöst?

Vielen Dank im Voraus :)

BlueCobold

Community-Fossil

Beiträge: 10 859

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

27.06.2017, 22:13

Mal was ganz anderes: Du solltest nicht für jedes Tile die Textur immer und immer wieder laden. Lade sie irgendwo zentral und lass dir die geladene Textur zurückgeben. Ich würde dir außerdem empfehlen nicht von Sprite abzuleiten. Ein Tile ist kein Sprite, es wird durch ein Sprite dargestellt.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Schorsch

Supermoderator

Beiträge: 5 198

Wohnort: Wickede

Beruf: Student

  • Private Nachricht senden

3

27.06.2017, 22:15

Hast du mal mit dem Debugger geguckt?
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 524

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

4

27.06.2017, 22:30

Mal was ganz anderes: Du solltest nicht für jedes Tile die Textur immer und immer wieder laden. Lade sie irgendwo zentral und lass dir die geladene Textur zurückgeben. Ich würde dir außerdem empfehlen nicht von Sprite abzuleiten. Ein Tile ist kein Sprite, es wird durch ein Sprite dargestellt.


Dass der Code extrem unperformant ist, kann man einfach nicht leugnen. Dies zu verbessern ist erstmal Sekundär.
Tile ist nun kein Sprite mehr. Um es zu zeichnen, lasse ich mir wie folgt das Sprite zurückgeben und zeichne es anschließend:

Quellcode

1
tileList.get(i).getSprite().draw(batch);


Das nächste Problem ist allerdings, dass die Positionen der Tiles nicht exakt gesetzt werden (siehe Anhang). Wird die Position falsch übergeben, sobald es in die Liste "gepusht" wird? Liegt es daran, dass die Positionen absolut gesetzt werden und nicht dynamisch in er Zelle? Müsste ich dann nicht bei jeder Kamera Bewegung die Position der Tiles an die Zellen anpassen?
»cojo2015« hat folgendes Bild angehängt:
  • Unbenannt.PNG

Schorsch

Supermoderator

Beiträge: 5 198

Wohnort: Wickede

Beruf: Student

  • Private Nachricht senden

5

27.06.2017, 22:43

Wie soll das Ergebnis denn aussehen?
Wird die Position falsch übergeben, sobald es in die Liste "gepusht" wird?

Das sollte sich mit dem Debugger checken lassen. Setz an der Stelle einen Breakpoint und guck ob die Werte passen.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 524

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

6

27.06.2017, 22:49

Wie soll das Ergebnis denn aussehen?

Am Ende soll jede Zelle ein Tile "in sich haben". Was auch ein Problem ist, dass ich nicht genau weiß, wo Tiled die Position 0|0 setzt. Bei LibGDX ist das unten links. Da frage ich mich, warum der Ursprung der Map in der Screenmitte gezeichnet wird (sieht man bei dem Bild nicht, da die Kamera bereits bewegt wurde).

Schorsch

Supermoderator

Beiträge: 5 198

Wohnort: Wickede

Beruf: Student

  • Private Nachricht senden

7

27.06.2017, 22:53


Am Ende soll jede Zelle ein Tile "in sich haben". Was auch ein Problem ist, dass ich nicht genau weiß, wo Tiled die Position 0|0 setzt. Bei LibGDX ist das unten links. Da frage ich mich, warum der Ursprung der Map in der Screenmitte gezeichnet wird (sieht man bei dem Bild nicht, da die Kamera bereits bewegt wurde).

Mir ist grad tatsächlich nicht klar welchen Ausschnitt ein Tile einnimmt. Kannst du das vielleicht mal markieren? In deinem Screenshot gibt es ja einerseits die weißen Umrisse und andererseits die roten Punkte.
Das mit der Mitte des Bildschirms liegt vielleicht an der Kamera. Ich habe ewig nicht mit LibGDX gearbeitet aber möglicherweise ist das einfach der Punkt. Wie sieht das ganze denn aus wenn du die Kamera nicht bewegst? Wie sieht das ganze aus wenn du überhaupt keine Kamera nutzt? Zusätzlich noch mal, wie soll es denn aussehen ;) Entweder beschreibst du wie es sein soll oder machst vielleicht ein kleines Beispiel mit Gimp oder Paint.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 524

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

8

27.06.2017, 23:04


Am Ende soll jede Zelle ein Tile "in sich haben". Was auch ein Problem ist, dass ich nicht genau weiß, wo Tiled die Position 0|0 setzt. Bei LibGDX ist das unten links. Da frage ich mich, warum der Ursprung der Map in der Screenmitte gezeichnet wird (sieht man bei dem Bild nicht, da die Kamera bereits bewegt wurde).

Mir ist grad tatsächlich nicht klar welchen Ausschnitt ein Tile einnimmt. Kannst du das vielleicht mal markieren? In deinem Screenshot gibt es ja einerseits die weißen Umrisse und andererseits die roten Punkte.
Das mit der Mitte des Bildschirms liegt vielleicht an der Kamera. Ich habe ewig nicht mit LibGDX gearbeitet aber möglicherweise ist das einfach der Punkt. Wie sieht das ganze denn aus wenn du die Kamera nicht bewegst? Wie sieht das ganze aus wenn du überhaupt keine Kamera nutzt? Zusätzlich noch mal, wie soll es denn aussehen ;) Entweder beschreibst du wie es sein soll oder machst vielleicht ein kleines Beispiel mit Gimp oder Paint.


Die TileMap besteht aus 15x15 Pixel großen Texturen, welche nur am Rand weiß sind, ansonsten in der Mitte komplett schwarz. Das ist eine Zelle. Ein Tile ist ein 3x3 Pixel großer roter "Punkt". Dieser soll mittig in eine Zelle platziert werden. Das sieht ungefähr so aus: (siehe Anhang). Mehr soll erstmal nicht passieren. Soweit alles klar?

Ohne Kamera bekomme ich nur rote Punkte zu sehen.
»cojo2015« hat folgendes Bild angehängt:
  • Unbenannt2.PNG

Schorsch

Supermoderator

Beiträge: 5 198

Wohnort: Wickede

Beruf: Student

  • Private Nachricht senden

9

27.06.2017, 23:12

Deine Zellen werden also weiß umrandet und sollen am Ende die roten Punkte in ihrer Mitte haben? Ok, check soweit. Kannst du mal einen Screenshot machen der zeigt wie das ganze aussieht wenn du die Kamera nicht bewegst?
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

BlueCobold

Community-Fossil

Beiträge: 10 859

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

10

28.06.2017, 07:08

tileList.get(i).getSprite().draw(batch);
Das war jetzt ehrlich gesagt auch nicht ganz die Verbesserung, die ich im Kopf hatte. Damit greifst du auf die Interna eines Tiles zu. Warum gibst du einem Tile nicht eine Draw-Funktion und lässt es das Sprite selbst zeichnen? Da muss der Aufrufer überhaupt nicht wissen, wie ein Tile intern funktioniert.

Die TileMap besteht aus 15x15 Pixel großen Texturen, welche nur am Rand weiß sind, ansonsten in der Mitte komplett schwarz. Das ist eine Zelle. Ein Tile ist ein 3x3 Pixel großer roter "Punkt". Dieser soll mittig in eine Zelle platziert werden. Das sieht ungefähr so aus: (siehe Anhang). Mehr soll erstmal nicht passieren. Soweit alles klar?
Eigentlich bin ich jetzt mehr verwirrt als vorher. Eine TileMap besteht üblich ja aus Tiles. Die sind bei dir aber angeblich nur 3x3 Pixel groß, was extrem winzig ist. Oder sind sie 15x15 groß? Dann verstehe ich aber nicht, was eine Zelle sein soll und wieso die TileMap aus Zellen und nicht aus Tiles besteht. Sollte das dann nicht eine Zellmap sein?
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Werbeanzeige