Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

17.02.2018, 10:19

sichtbaren bereich einer isometrischen karte zeichnen-java

Hallo,

die Überschrift sagt eigentlich schon alles.

Orthogonal geht's.

Quellcode

1
2
3
4
5
6
7
8
9
10
                int sx = (int) Math.max(0,xoffset/32);
        int ex = (int) Math.min(mapwidth,(xoffset+getWidth())/32+1);
        int sy = (int) Math.max(0,yoffset/32);
        int ey = (int) Math.min(mapheight,(yoffset+getHeight())/32+1);
        
        for(int i = sx;i<ex;i++) {
            for(int j = sy;j<ey;j++) {
                tiles[i][j].render(g,xoffset,yoffset);
            }
        }


Aber isometrisch nicht.

Wäre für Hilfe sehr dankbar.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

17.02.2018, 10:32

Ein paar mehr Infos wären praktisch.
- Was heißt „geht nicht“? Gibt's Bilder dazu?
- Was bedeuten die ganzen Variablen? Ich kann's mir zwar denken, aber eigentlich solltest du uns das mitteilen.

Genereller Tipp: Überleg dir mal, wie der sichtbare Bereich in der Map aussieht. Ein Rechteck ist das nicht, darum kann dein Ansatz so nicht funktionieren.

Wirago

Alter Hase

Beiträge: 1 193

Wohnort: Stockerau

Beruf: CRM Application Manager

  • Private Nachricht senden

3

17.02.2018, 11:49

Ich denke, dass dir das hier weiter helfen sollte:
http://clintbellanger.net/articles/isometric_math/

4

18.02.2018, 07:47

Ok,

ich versuche mit den Variablen das Rechteck zu beschreiben, welches den sichtbaren Bereich der Karte darstellt.
Dabei steht sx für startx etc. . Mein Spielfeld ist so aufgebaut, dass die Kachel 0,0 in der Mitte oben liegt. Nach rechts wird x und nach links wird y abgetragen. Das Problem dabei ist nur, dass zum einen der Offset negativ werden kann, was wiederum zu einer häßlichen OutOfBoundsException führt und zum anderen, dass ich nicht weiß wo man den startx-wert setzt, also ob man den ganz links setzten sollte und damit die Karte dreht oder nicht.

Desweiteren stelle ich mir das Ganze so vor, dass wenn sich der Offset verschiebt, die Kachel darunter( jeweils in den verschiedenen Richtungen ) um die halbe Breite sowie die halbe Höhe angezeigt wird.

Mehr weiss ich nicht.

Wirago

Alter Hase

Beiträge: 1 193

Wohnort: Stockerau

Beruf: CRM Application Manager

  • Private Nachricht senden

5

18.02.2018, 10:56

Dein Offset kann nicht negativ werden. Du zeichnest ja die erste Kachel immer bei 0,0. Wie würdest du da auf -1,-1 oder so kommen?

6

18.02.2018, 12:45

Mein Offset richtet sich nach der aktuellen Position der Kachel. Im Grunde genommen ist mein Offset blos ein Wert, der auch negativ werden kann, den ich der gezeichneten Kachel subtrahiere ( oder addiere). Ich denke mal das sich die vier Eckpunkte des gesuchten Rechteckes nach dem Offset richten, denn das ist der einzige Variable Wert beim Verschieben der Karte. Und deshalb werden bei mir negative Werte angezeigt.

Ich habe momentan das hier:

Quellcode

1
2
3
4
5
6
7
8
9
10
                  for(int i = 0;i < map_width;i++) {
            for(int j = 0;j < map_height;j++) {
                int screenx = (i-j);
                int screeny = (i+j)/2;
                sx = screenx+yoffset/32;
                ex = sy+((1280+xoffset)/32)+4;
                sy = map_height-1-screeny+yoffset/32;
                ey = sx+(map_height-screeny-xoffset/32);
            }
        }


Es wird halt nur ein Isometrischer Abschnitt gezeichnet und es existieren noch sichtbare Bereiche die nicht gezeichnet werden.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

7

18.02.2018, 13:11

An sich sind deine Grafiken doch Rechtecke. Davon wird zwar nur ein Teil gezeichnet, an der Form der Grafiken ändert sich dadurch aber nichts. Diese werden jetzt nicht nebeneinander, sondern mit Versatz gezeichnet. Anstatt von Links nach Rechts zu gehen wird jede zweite Grafik halt mit einem kleinen Versatz nach unten/oben gezeichnet. Das ganze ist also an sich nicht viel komplizierter als bei normalen Tilemaps. Fang bei der Sache erst mal simpel an. Keine Offsets, keine Kamera oder Scrolling. Zeichne einfach erst mal ein paar Tiles. Danach arbeitest du dich dann langsam und Stück für Stück zu deinem eigentlichen Ziel.
„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.“

8

18.02.2018, 13:27

So dumm es klingen mag, aber ich hab einen A* auf einem zur Laufzeit unsichtbaren Grids mit verschiedenen Einheiten korrekt animiert und berechnet am laufen inklusive Hindernisse und einfacher Kollisionserkennung der Einheiten untereinander. Sowie eine komplette isometrische Karte mit Flüssen, Gras etc. .

Ich habe das Ganze auch orthogonal auch mit Zeichenbereich hinbekommen inklusive Menüs und PiPaPo.

Also entweder ich bin völlig neben der Kappe oder ich bin überarbeitet.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

9

18.02.2018, 14:24

Dein Problem ist, dass du über ein achsenausgerichtetes Rechteck im Map-Space "iterierst". Das ist dann natürlich eine Raute im Screen-Space. Die ist entweder zu klein oder zu groß, aber niemals genau passend.
Du willst ein achsenausgerichtetes Rechteck im Screen-Space abdecken (nämlich den sichtbaren Bereich). Also solltest du über den Screen-Space iterieren und jeweils ermitteln, welches Tile im Map-Space dort zu sehen ist.
Du brauchst also eine Funktion, um vom Screen-Space in den Map-Space umzurechnen (und umgekehrt).

Sinngemäß (im Detail sicher nicht korrekt/optimal, aber um die Idee zu verdeutlichen):

Java-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
boolean evenY = true;
for (int y = 0; y < screenHeight; y += stepY)
{
    for (int x = evenY ? 0 : -stepX / 2; x < screenWidth; x += stepX)
    {
        // Wo sind wir hier im Map-Space?
        Point mapCoords = screenToMap(new Point(x, y));
        
        // Sind wir hier im gültigen Bereich der Map? Wenn ja, dann Tile zeichnen.
        if (mapCoords.x >= 0 && mapCoords.x < map.numTilesX &&
            mapCoords.y >= 0 && mapCoords.y < map.numTilesY)
        {
            // Exakte Bildschirmkoordinaten des Tiles berechnen.
            Point screenCoords = mapToScreen(mapCoords);
            drawTile(screenCoords, map.getTileAt(mapCoords));
        }
    }
    
    evenY = !evenY;
}

Wie gesagt, im Detail sicher nicht korrekt/optimal!
Aber die Idee ist: Du fängst links oben auf dem Bildschirm an und fragst: Welche Map-Koordinaten haben wir an dieser Stelle? Ist das innerhalb der Map? Wenn ja, dann zeichne das entsprechende Tile. Dann machst du weiter mit dem nächsten Punkt. Die Schrittweite in Bildschirmkoordinaten muss so sein, dass du jedes Tile genau einmal triffst. Darum musst du, je nach dem ob es eine gerade oder ungerade Zeile ist, mit einem x-Offset der halben x-Schrittweite starten. Und die y-Schrittweite ist normalerweise kleiner als die x-Schrittweite, wegen der Perspektive.
Das kann man garantiert noch optimieren, so dass man nur sehr wenig rechnen muss, aber Optimierungen kannst du später einbauen.

10

21.02.2018, 15:13

Danke. Habe es jetzt.

Werbeanzeige