Tilemaps mal objektorientiert...
Übersicht BlitzMax, BlitzMax NG Allgemein
bruZardBetreff: Tilemaps mal objektorientiert... |
Mo, Feb 06, 2006 21:09 Antworten mit Zitat |
|
---|---|---|
Hallo Folks, ich habe hier mal wieder ein Problem welches nicht wirklich problematisch ist, also das Projekt nicht aufhält, mir aber auf den Nägeln brennt da ich derzeit glaube zuviel Code für zuwenig Action zu schreiben.
Es geht um das verwalten von Tilemaps mit einer definierten Anzahl von Layern innerhalb von Klassen. Bei mir sieht es derzeit so aus dass ich 5 Layer verwende:
Nun ist es so dass nur die Layer ground und overlay an das Mapraster gebunden sind, alle anderen Layer beziehen sich nur auf dieses Raster. Beispiel: Der Player befindet sich in Spalte 5, Zeile 10 und hat dazu einen X-Offset von 12 Pixeln und einen Y-Offset von 8 Pixeln. Sein Handle ist Top-Left. Alle Decals und Entities werden so behandelt. Mein Ansatz derzeit dafür ist folgender: Alles was ins Mapraster passt (ground, overlay) wird in einer Bank gesichert: 1 Integer für die ID des Tilesets, 1 Integer für die Framenummer des Tiles. Beim auslesen gehe ich alle Instanzen der Klasse TTileset durch um die ID zu finden die in der Bank gesichert ist. Allerdings finde ich diese Geschichte schon extrem lame. Alle Objekte die relativ zu einem Tile stehen sind in einer Linked List gesichert welche an eine Klasse gebunden ist. Das bedeutet dass ich bei jedem Tile die komplette Liste der Decals und Entities durchgehen muss um zu gucken ob sich bei der aktuellen Mapzelle ein Objekt befindet. Auch das ist nicht nur lame sondern auch lahm. Was soll dieser Post bezwecken? Ich bräuchte mal einen Schlag gegen den Hinterkopf und eine Idee wie man das einfacher und schneller lösen kann. Für jede Idee bin ich dankbar |
||
PIV 2,4GHz - 1GB DDR 333 - ATI Radeon9600 - WinXP - DX9.0c - BMax 1.14 - B3D 1.91 - 1280x1024x32
User posted image |
rema |
Mo, Feb 06, 2006 21:53 Antworten mit Zitat |
|
---|---|---|
Kannst du mal Codefragmente zeigen, also nur als Beispiel. Hatte auch schon so ändliches Problem, wie ich die Daten optimal handhaben kann. Den die Suche von in TypeList sind lahm. Den lieber parent/child und so mehr Speicher abverlangen... | ||
AvaGast |
Di, Feb 07, 2006 10:14 Antworten mit Zitat |
|
---|---|---|
Hallo Bruzard,
mal schauen, ob ich Dir helfen kann, ich habe schon einige objektorientierte Tilemaps in BMax geschrieben. Ich würde Tiles prinzipiell nicht als Integer-Werte in einer Bank speichern. Einen Pointer-Array, der direkt auf das Tile-Objekt oder die Grafik zeigt (ich hatte mir dafür immer extra einen Type angelegt), fand ich da sehr praktisch. Wenn Du die Tiles als Objekte verwaltetst, hat das den Vorteil, dass Du denen sehr einfach viele schöne Eigenschaften einstellen kannst (zb. für Animationen, Einfluss auf die Geschwindigkeit von Charakteren, event. Schaden bei Betreten / Bewegen auf dem Tile und und und). Meine Map-Layer hatte ich auch immer als Objekte angelegt, so das ich dann immer eine völlig belebige Anzahl von ihnen einstellen konnte. Dabei hatte ich unterschiedle Typen von Layern (Tile-Layer, Object-Layer, Fill-Layer für Tiles oder Farben). So wie ich es aus Deinem Post herauslese, zeichnest Du deine Map, indem Du die x/y Koordinaten abgehst und dann dort die Layer übereinander einzeichnest? - das ist natürlich sehr ungünstig! Du solltest die Layer durchgehen, die x/y Tiles für das komplette Layer einzeichnen und dann zum nächsten wechseln. Wenn Du es so machst, hast Du auch keine Probleme mehr mit Deinen Objekt-Listen, da Du diese nur noch ein einziges Mal durchgehen musst! Vielleicht konnte ich Dir den einen oder anderen brauchbaren Denkanstoss geben. Gruss, Ava |
||
bruZard |
Di, Feb 07, 2006 18:26 Antworten mit Zitat |
|
---|---|---|
Bin derzeit etwas knapp an Zeit und musste eben noch schnell Xaron "anpissen", aber heute abend poste ich nochwas was die Sache verdeutlicht und auch eine Erklärung warum die Pointer-Geschichte so nicht funktioniert. | ||
PIV 2,4GHz - 1GB DDR 333 - ATI Radeon9600 - WinXP - DX9.0c - BMax 1.14 - B3D 1.91 - 1280x1024x32
User posted image |
bruZard |
Di, Feb 07, 2006 21:28 Antworten mit Zitat |
|
---|---|---|
Aaaalso ... die Geschichte mit den Pointern auf Instanzen hatte ich schon, das hat aber nicht so funktioniert wie ich es mir gedacht hatte.
Zeichnen in die Map und Wiedergabe derselben funktionierte wunderbar, aber wehe ich kam auf die verwegene Idee das aktuelle Tileset zu wechseln. Wie man den Pointer auf eine Instanz in eine Bank und wieder heraus bekommt hatten wir ja schon in diesem Topic abgehandelt: https://www.blitzforum.de/viewtopic.php?t=14196 Mein Ansatz ist dann folgernder (Dummy-Code) Code: [AUSKLAPPEN] Type TDummy Field _list:TList Function Add:TDummy() Local dummy:TDummy = New TDummy If dummy._list:TList = Null Then dummy._list:TList = New TList dummy._list.AddLast(dummy) Return dummy End Function End Type Die erzeugende Methode/Funktion übernimmt dann die Instanz und generiert daraus einen Zeiger welcher widerum in ein Integer gecastet wird Code: [AUSKLAPPEN] Local myDummy:TDummy = TDummy.Add Local pointer:TDummy Ptr = Varptr myDummy Local toBank:Int = Int(pointer) Soweit so lustig, das gecastete Integer kann nun problemlos per PokeInt() in die Bank geschrieben werden. Beim auslesen muss dann halt wieder gecastet werden... Code: [AUSKLAPPEN] Local fromBank:TDummy Ptr = TDummy Ptr(PeekByte(bank,offset)) ...auf das "wiedergewonnene" Object kann dann via fromBank[0].EinZugriff zugegriffen werden. Trotz dieser (eigentlich funktionierenden) Geschichte kam es immer wieder zu Seiteneffekten. Leider ist dieser Versuch schon eine Weile her und ich kann nicht mehr jedes Detail reproduzieren, aber ich kann ja mal einen kleinen Testcode schreiben und schauen ob der Fehler immer noch auftritt. Zum Problem mit den Objekten: Es können theoretisch beliebig viele Objekte pro Tile existieren, das bedeutet dass ich diese nicht als Raster in einer Bank ablegen kann da dies bedeuten würde dass immer nur exakt ein Objekt auf einem Tile sein darf ... sehr blöd Bedeutet: Ich muss die komplette Liste der Objekte durchgehen und nachschauen ob sich auf dem gerade zu verarbeitenden Tile eines oder mehrere dieser Objekte befindet. Ich denke ich müsste das irgendwie per Sortierung lösen, habe da aber noch keinen wirklichen Ansatz. |
||
PIV 2,4GHz - 1GB DDR 333 - ATI Radeon9600 - WinXP - DX9.0c - BMax 1.14 - B3D 1.91 - 1280x1024x32
User posted image |
Jolinah |
Mi, Feb 08, 2006 0:15 Antworten mit Zitat |
|
---|---|---|
Ich versteh nicht ganz wieso du das über Bank und Pointer lösen willst, wäre sowas in der Art nicht einfacher?
Ist Pseudocode, funktioniert nicht, und soll nur ein Beispiel sein: Code: [AUSKLAPPEN] Type TLevel
Field Layer:TLayer[5] Field Width:Int, Height:Int Method Draw() For l:TLayer = EachIn Layer l.Draw() Next End Method End Type Type TLayer Field Map:TObject[,] Method Draw() For Local y:Int = 0 To 24 For Local x:Int = 0 To 32 Map[x,y].Update() Map[x,y].Draw(x,y) Next Next End Method End Type Type TObject Field TileID Field offX:Int, offY:Int Method Draw(x:Int, y:Int) DrawImage Tileset, x + offX, y + offY, TileID End Method Method Update() 'Normale Tiles machen nix End Method End Type Type TMovingTile Extends TObject Field timer:Int 'Update Methode überschreiben 'Dieses Tile bewegt sich irgendwie Method Update() If MilliSecs() - timer > 4000 offX = 0 timer = MilliSecs() Else If MilliSecs() - timer > 2000 offX :+ 1 EndIf End Method End Type BMax-Intern sind die Objekthandles sowieso Pointer, ich glaub wenn du da noch dauernd hin und her casten musst, dann wird es eher langsamer als schneller |
||
AvaGast |
Mi, Feb 08, 2006 1:56 Antworten mit Zitat |
|
---|---|---|
bruZard hat Folgendes geschrieben: Zum Problem mit den Objekten:
Es können theoretisch beliebig viele Objekte pro Tile existieren, das bedeutet dass ich diese nicht als Raster in einer Bank ablegen kann da dies bedeuten würde dass immer nur exakt ein Objekt auf einem Tile sein darf ... sehr blöd Bedeutet: Ich muss die komplette Liste der Objekte durchgehen und nachschauen ob sich auf dem gerade zu verarbeitenden Tile eines oder mehrere dieser Objekte befindet. Ich denke ich müsste das irgendwie per Sortierung lösen, habe da aber noch keinen wirklichen Ansatz. Ich verstehe immer noch nicht genau, warum Du Dir dieses Problem machst? Zeichne nicht Tile für Tile sondern Layer für Layer. Für jedes Tile die komplette Objekt-Liste durchzugehen ist doch völlig unnötig (und wenn nicht, dann erkläre es mir bitte noch einmal *zwinker*). Also ich bin fast geneigt, meine TileEngine hier zu posten, um's mal zu verdeutlichen, wie ich es meine und Dir zu zeigen, dass es läuft (und gut läuft und schnell läuft). Nur wäre das wohl etwas übertrieben viel Code... Im Übrigen geht Jolinahs Vorschlag schon in etwa in die Richtung, wie ich es eigentlich gemeint hatte. |
||
bruZard |
Mi, Feb 08, 2006 18:16 Antworten mit Zitat |
|
---|---|---|
Dass ich meine Daten in einer Bank ablege hat einen Grund: Ich bin kein besonders guter Programmierer, sondern Designer. D.h. dass ich mir Dinge immer räumlich vorstellen muss. Das klappt bei Banks sehr gut, funktioniert mit verzwickten "hier ein Type und da ein Type" Lösungen aber nur solange wie ich vor dem Quelltext sitze. Habe ich eine Nacht über den Kram geschlafen kann ich ihn nicht mehr oder kaum noch lesen.
@Ava: Es ist schon so dass ich Layer für Layer zeichne ... erst den Boden, dann die Decals, dann die Entities etc. Ich weiß nicht was mir Dein Hinweis bringen soll Allerdings habt Ihr mich da auf eine Idee gebracht: Ich schreibe nicht mehr den Zeiger auf ein Tileset in die Bank, sondern den Zeiger auf eine Map-Cell. Das spart ein Integer, also die Hälfte der Bank In dieser Map-Cell (nennen wir das Type einfach mal TCell) sichere ich dann Tileset, Tile-ID etc. als Instanzen auf die dahinter liegenden Klassen Code: [AUSKLAPPEN] -> Bank -> Zeiger auf TCell Instanz -> Instanzen von TTileset -> Instanzen von TObject (für Decals und Entities) -> andere Infos über die Zelle ...muss ich zuhause mal checken ob das so machbar ist. |
||
PIV 2,4GHz - 1GB DDR 333 - ATI Radeon9600 - WinXP - DX9.0c - BMax 1.14 - B3D 1.91 - 1280x1024x32
User posted image |
bruZard |
Mi, Feb 08, 2006 20:24 Antworten mit Zitat |
|
---|---|---|
Ich habe jetzt hier mal einen rudimentären, noch nicht funktionierenden und denke dass dieser die Lösung sein könnte.
Das Level erzeugt aus der Klasse TLayer noch immer eine neue Bank und diese werden mit den gecasteten Integers der Instanzen der Klasse TCell gefüllt aus welcher man widerum weitere Informationen über diverse Links bekommt. Code: [AUSKLAPPEN] Type TLevel Field cell:TCell Field layer:TLayer Function Init:TLevel(width:Int, height:Int) Local level:TLevel = New TLevel Return level End Function EndType Type TCell Global _list:TList Global count:Int Field id:Int Field tileset:TTileset Field frame:Int Function Add:TCell(tileset:TTileset,frame:Int) Local cell:TCell = New TCell cell.count:+1 If cell._list:TList = Null Then cell._list:TList = New TList cell._list.AddLast(cell) cell.id = cell.count cell.tileset = tileset cell.frame = frame Return cell End Function End Type Type TTileset Global _list:TList Global count:Int Field id:Int Field filename:String Field typ:String Field image:TImage Field tile_count:Int Field tile_vars:Int Field tile_anim:Int Function Load:TTileset(filename:String,typ:String,tile_count:Int,tile_vars:Int,tile_anim:Int,tile_width:Int,tile_height:Int) Local tileset:TTileset = New TTileset tileset.count:+1 If tileset._list:TList = Null Then tileset._list:TList = New TList tileset._list.AddLast(tileset) tileset.id = tileset.count tileset.filename = StripDir(filename) tileset.typ = typ tileset.tile_count = tile_count tileset.tile_vars = tile_vars tileset.tile_anim = tile_anim tileset.image = LoadAnimImage(filename,tile_width,tile_height,0,tile_count) Return tileset End Function End Type Type TLayer Global _list:TList Global count:Int Field id:Int Field width:Int Field height:Int Field data:TBank Field name:String Field ui:String Function Add:TLayer(width:Int, height:Int, name:String, ui:String) Local layer:TLayer = New TLayer layer.count:+1 If layer._list:TList = Null Then layer._list:TList = New TList layer._list.AddLast(layer) layer.id = layer.count layer.width = width layer.height = height layer.name = name layer.ui = ui layer.data = CreateBank((width*height)*4) Return layer End Function End Type Is'n bissl viel und nicht dokumentiert, aber ich baue mal an dieser Idee weiter. |
||
PIV 2,4GHz - 1GB DDR 333 - ATI Radeon9600 - WinXP - DX9.0c - BMax 1.14 - B3D 1.91 - 1280x1024x32
User posted image |
suberror |
Mi, Feb 08, 2006 23:17 Antworten mit Zitat |
|
---|---|---|
gelöscht | ||
Übersicht BlitzMax, BlitzMax NG Allgemein
Powered by phpBB © 2001 - 2006, phpBB Group