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

Architekt

Community-Fossil

  • »Architekt« ist der Autor dieses Themas

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

1

24.01.2011, 23:32

TileMap : Zugriffsweise auf Textur

Ich stehe derzeit vor einem kleinen Dilemma, daher hoffe ich, dass ihr mir bei meiner Entscheidung helfen könnt.
Es geht im Grunde nur um die Kacheln einer Tile-Map.
Das ganze sieht so aus, dass ich eine Klasse TiledMap habe, welche die Tiles verwaltet. Ein Tile ist eine Struktur mit diesen Aufbau:

C-/C++-Quelltext

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
public struct Tile {
    bool walkable, destroyable;

    ubyte[2] size;

    string layer;
    ushort tid;

    Vector2 transit;
    Vector2 coord;

    this(in ubyte[2] size, in Vector2 coord, in ushort tid) {
        this.walkable = true;
        this.destroyable = false;

        this.transit = Vector2(-1, -1);
        this.coord   = coord;

        this.tid = tid;
    }

    @property float x() const {
        return this.coord.x;
    }

    @property float y() const {
        return this.coord.y;
    }
}

(D Programming Language)

Nur frage ich mich:
#1: Mache ich es mir einfach und lege die Textur/Grafik der Kachel ebenfalls in die Struktur und gewährleiste somit einen absolut leichten Zugang um z.B. ein bestimmtes Tile nochmals mit einem alpha Wert zu zeichnen?
#2: Oder mache ich einen kleinen Umweg, indem ich lediglich die Tile-ID in der Struktur speichere, nicht aber die Textur. Letztere würde in einem separaten Array gespeichert werden, mit der Tile-ID als Key.
Dann bräuchte ich eben eine Methode, die mir über die entsprechende Tile-ID die Grafik liefert.
Vorteil von #1 wäre es, dass ich einen einfach zugänglichen Weg auf die Textur habe, aber der Vorteil von #2 ist: die meisten Tiles ähneln sich ja, Wasser bleibt Wasser, Boden bleibt Boden.
Ich denke so könnte ich die Anzahl der verwendeten/gespeicherten Grafiken drastisch einschränken und hätte keine doppelt verwendeten.
Andererseits kann es ja aber auch durchaus vorkommen, dass ich nur für ein ganz bestimmtes Tile die Grafik ändern möchte oder nur dieses eine besondere Tile mit einem alpha Blending versehen möchte.
Das könnte ich natürlich aber auch durch das hinzufügen separate Eigenschaften in der Struktur lösen, wie ubyte alpha.
Was meint ihr dazu? #1 oder #2 oder gar nichts?
Bin für Kritik oder Anregungen offen.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

DerMark

Treue Seele

Beiträge: 324

Wohnort: Emsdetten

Beruf: Softwareentwickler

  • Private Nachricht senden

2

25.01.2011, 00:02

Hi,

ich würde zu folgendem tendieren: Die goldene Mitte von beidem. Und zwar so:

1. Die Klasse welche einer Textur entspricht würde ich Klonbar machen inklusive dazugehörigen Management kram (neue ID generieren und das mapping von ID zu Textur in den entsprechenden Manager einrichten).

2. Deine Tile Struct erweitern und zwar um die Möglichkeit per getter auf die aktuelle Textur zugreifen zu können (Suche der Textur im Texturmanager per ID) und einen Setter um die Tile ID anhand der zugewiesenen Textur zu setzen.

Um dann eine individuelle Version der Textur dem Tile zuzuweisen, würde ich dann versimpelt folgendes tun:

C-/C++-Quelltext

1
Texture tex = myTile.Texture.Clone();tex.Manipulate();myTile.Texture = tex;

(Ich kenne D leider nicht.)

Ich hoffe das ist so ungefähr das was du suchst. Wenn nicht habe ich womöglich dein Problem etwas falsch verstanden.

mfg Mark

Architekt

Community-Fossil

  • »Architekt« ist der Autor dieses Themas

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

3

25.01.2011, 00:13

Wenn ich dich richtig verstehe, würden dann die getter bzw. setter Methoden auf die Verwaltung (also in diesem simplen Beispiel auf das Textur Array, später dann auf eine Manager Klasse) zugreifen, und somit einen Besitz der Textur emulieren.
Dann müsste doch aber jede Struktur wiederum ein Objekt auf diese Manager Klassen besitzen, was auch nicht gerade redundant wäre, oder versteh' ich dich falsch?
Weil in diesem Fall wäre es meiner Meinung nach einfacher, gleich die Textur in das Struct zu packen.
Im Prinzip gings mir um die Speicherlastigkeit und die Design technische Frage. Man sagte mir bereits, dass die Textur in der Tile Struktur nichts verloren habe, weil es unschön aussehe oO
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

25.01.2011, 06:48

Ein paar Gedanken (ich gehe mal davon aus dass du Direct3D bzw. OpenGL verwendest):
Muss ein Tile wirklich seinen Layer speichern? Braucht ein Tile wirklich seine Position? Ein Tile ist normalerweise einfach eine Zelle in einem regelmäßigen Gitter. Auf das Tile wird ein kleiner Ausschnitt einer größeren Textur (Tileset) gespannt. Die TileMap hat ein Array aus Tiles, bzw. für jeden Layer ein solches, die Position eines Tile ergibt sich aus dessen Index in diesem Array. Grafikmäßig braucht ein Tile ein Sprite. Ich würde da auf der untersten Ebene einen Immediate Mode Ansatz verfolgen, d.h. einen Mechanismus bauen der es erstmal einfach erlaubt ein TileSet (ne Textur) zu laden. Ein Sprite Objekt repräsentiert dann nur einen Ausschnitt aus diesem TileSet. Das Sprite selbst hat keinen Zustand von wegen Position usw., man kann es einfach direkt irgendwo hinmalen (Sprite.Draw(x, y)). Jedes Tile hat dann ein solches Sprite. Wenn die Map gerendert werden soll dann wird erstmal der Ausschnitt der sichtbaren Tiles bestimmt und diese Tiles dann nacheinander gezeichnet (Tile.Draw(x, y) zeichnet einfach das interne Sprite)). Am Besten wäre es natürlich die Reihenfolge in der die Sprites gezeichnet werden z.B. nach Tileset und/oder Shader zu sortieren um die Anzahl der Texture und Shader switches möglichst gering zu halten. Den Zeichenmechanismus könnte man in eine SpriteRenderer Klasse verpacken die sich um so Dinge kümmert wie z.B. möglichst viele Sprites in einen großen dynamischen Buffer zu batchen, was die Performance üblicherweise um drei oder vier Ebenen nach oben befördert (zumindest wenn du mehr als 1000 Sprites/Frame malen willst).

DerMark

Treue Seele

Beiträge: 324

Wohnort: Emsdetten

Beruf: Softwareentwickler

  • Private Nachricht senden

5

25.01.2011, 07:32

Man sagte mir bereits, dass die Textur in der Tile Struktur nichts verloren habe, weil es unschön aussehe oO
Weils unschön aussehe? Wenns vom Architektonischen passt, spricht absolut nichts dagegen. Einen Pointer/Referemz auf die Textur zu speichern geht natürlich auch, ich dachte du hast irgendeinen speziellen Grund gehabt genau dies nicht zu tun (bis auf das es unschön wäre).

Was dot schreibt spricht natürlich auch für sich. Deine Struktur sollte nur die Eigenschaften des Tiles beschreiben, also Grösse, Position in der TileTextur, Physikalische Eigenschaften (welche man auch noch alles in separate Strukturen stecken sollte. Im Grunde schon so wie du es hast.

Das ein Tile den Layer speichert finde ich ansich schon nicht verkehrt, die Tile Struktur bildet ja eine Informationssammlung über ein einzelnes Feld/Tile ab, das gehört weder in die Tiletextur selber rein noch woanders. Das Höchste der Gefühle wäre hier die Tile Struct wirklich in unter Structs zu unterteilen, wie weit man dies allerdings treiben sollte ist eine andere Sache ;)

@Architekt: Von der Speicherlastigkeit würde es mich stark wundern wenn du bei der kleinen Struct überhaupt Probleme bekommen solltest, worüber genau machst du dir denn da Sorgen? Ob nun ID oder Texturreferenz/Pointer sollte hier kaum einen Unterschied machen (von x86 vs x64 mal abgesehen).

mfg Mark

Architekt

Community-Fossil

  • »Architekt« ist der Autor dieses Themas

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

6

25.01.2011, 11:20

@dot:
Ich benutze die SDL, in D ist es noch recht schwer, brauchbare Frameworks zu finden.
Und ja, das ist mir alles soweit bekannt. Aber layer bzw. Koordinaten machen für mich schon Sinn, immerhin kann ich so ganz leicht erkennen, auf welchem Layer ich mich befinde und brauche keine extra abfrage über die Tile-ID. Jedenfalls war so mein Gedankengang.

@DerMark:
Gut, ich hatte bereits nach ähnlichen Entwürfen für eine TileMap gesucht und sehr schnell auf drakons Seite ein kleines Tut gefunden welches auch wiederum eine interne Textur verwendet, statt den Umweg über die Tile-ID zu gehen. Das kam meinen eigenen Vorstellungen sehr nahe.
Ich zerbreche mir lediglich über das genaue Design den Kopf.
Auch ob ich alle Tiles je nach Sichtbarkeit zeichne oder diese intern schon beim anlegen der Tiles nochmals auf eine extra Textur blite, welche dann die gesamte Map darstellt und welche dann als eigentliche Map auf das Fenster gezeichnet und für's eigentliche Scrolling verwendet wird.
Dann müsste ich über die Koordinaten nur noch die einzelnen Tiles abfragen, ob sie begehbar sind etc. Aber dann lohnt sich m.E. keine Textur in der Tile Struktur. Aber ist das eine gute Idee?
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

DerMark

Treue Seele

Beiträge: 324

Wohnort: Emsdetten

Beruf: Softwareentwickler

  • Private Nachricht senden

7

25.01.2011, 12:48

Wenn du es nicht brauchst dann lass es weg. Wenn du später dazu kommst es doch noch zu brauchen kannst du es immer noch nachrüsten. Wenn du es nicht brauchst verschwende keine Zeit damit.

http://en.wikipedia.org/wiki/You_ain%27t_gonna_need_it

Architekt

Community-Fossil

  • »Architekt« ist der Autor dieses Themas

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

8

25.01.2011, 17:56

Jop, ich mache es jetzt einfach mit, hatte mir mehr Anregungen erhofft, aber seis drum.
Dir auf jedenfalls danke.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Werbeanzeige