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

Copax

Frischling

  • »Copax« ist der Autor dieses Themas

Beiträge: 17

Beruf: Fachinformatiker

  • Private Nachricht senden

11

03.01.2014, 12:04

@DeKugelschreiber
Danke das sieht sehr gut aus.. hättest du jetzt noch einen Vorschlag wo ich mich dazu einlesen kann? Hab gerade mehrere Seiten studiert und jetzt qualmt mir der Kopf weil sie so wirr beschrieben waren. Speichert der Vector sozusagen am Ende die X und Y Koordinate oder kann man ihm mehr Daten eintrichtern? Am ende müsste man ihm ja sagen das er ein Feld mit den Werten (z.B. (1,1) (1,2) (2,1) (2,2)) speichert bzw. nur (1,1) (2,2) wenn es quadratisch werden soll und dann zusätzlich noch bestimmte Werte die für das Feld zutreffen.

Sry wenn ich weiter nerve aber bin gerade echt in einer Gedanklichen Sackgasse :wacko:
"Phantasie ist wichtiger als Wissen, denn Wissen ist begrenzt."



Albert Einstein

CeDoMain

Alter Hase

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

12

03.01.2014, 21:00

Ich programmiere gerade ein Minecraft ähnliches Spiel. Ich habe dabei das Problem, dass riesige Spiechermengen durch die vielen Blöcke anfallen. Zuerst hab ich alle Blöcke in einem dreidimensionalen Array gespeichert. Aber ab einer bestimmten Größe gibt es diffuseste Fehler. Von Heap beschädigt (ich habs mit dem Heap gemacht, nachdem ich Stackoverflows bekommen hab) bis zu solchen Fehlermeldungen, mit denen ich garnichts anfangen kann:

Zitat

Unbehandelte Ausnahme bei 0x754dc41f in Main.exe: Microsoft C++-Ausnahme: std::bad_alloc an Speicherposition 0x0018f9ac..

Dann habe ich mir gedacht, zerteilst du die Daten in kleinere Stücke, wie es auch im Original realisiert ist, aber nichts bringt etwas. Ich habs zuerst in Chunks und diese dann in Sections zerteilt, die dann nur noch 16*16*16 Blöcke beinhalten. Im Augenblick hab ich mich damit abgefunden, aber jetzt ist etwas sehr merkwürdiges aufgetaucht. Ich hab eine sehr lange Methode in der Sectionklasse, an deren Ende eine if-else Struktur ist. Wenn ich das Programm im Debugger ausführe, wird der if Teil bei wahrer Bedingung ausgeführt bei falscher nicht. Ist ja OK, der zugehörige else-Zweig wird aber NIE ausgeführt!? Ich hab einen anderen Programmierer nochmal drüberschauen lassen, um Klammer- und Syntaxfehler auszuschließen. Nichts gefunden! :(

Kann es sein, dass es bei großen Klassen (ich find das ja nicht groß, ist nur ne Vermutung) die auf dem Heap ausgeführt werden Probleme gibt? Was kann ich da machen? Wer sich für den Code interessiert, darf sich gerne melden! Ich hab das mal hierrein gestellt, weil es ja hier auch um das Speichern von großen Datenmengen (Maps) geht.

Ich Programmiere mit Microsoft Visual Studio 2010/13 Professional und Windows 7. Mein Programm ist "glaub" ich 32bit - ich weiß jedenfalls nicht, wo ich es auf 64bit ändern kann.
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

13

03.01.2014, 21:07

Da gibts viele Möglichkeiten. Du kannst in der Klasse "Tile" ja grundsätzlich speichern was du möchtest.
Typischerweise verwendet man eine ID pro Tiletyp. Heißt z.B. Gras wäre die 4, Stein die 7 usw. Dazu kannst du nehmen was du möchtest, z.B. ob ein Tile betretbar ist oder nicht.

Das array selbst würde ich eigentlich immer linear aufbauen, also eindimensional. Das reicht eigentlich völlig, ist aber simpel zu handhaben. Den Index eines Tiles kannst du dir dann mit Hilfe der x, y Koordinaten berechnen:

Quellcode

1
Tile t = tiles[y*tileMapWidth+x]; // tiles ist dein array


Dafür speicherst du die Größe der Tilemap (in Feldern) mit.

Vielleicht hilft es dir einmal etwas Code zu lesen. Ich bastel auch gerade an einem Spiel mit Tilemap, die sehen aktuell so aus (in Textdatei):

Quellcode

1
2
3
4
5
6
7
8
9
10
1,2,33,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1


Also sehr einfach. Gelesen werden sie dann so: https://github.com/DeKugelschieber/Game/…se/map/Map.java

CeDoMain

Alter Hase

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

14

04.01.2014, 09:55

Danke für die schnelle Rückmeldung.

Ich habe deinen Vorschlag verstanden und auch sofort umgesetzt. Meine Sections und Chunks werden jetzt in einem eindimensionalen Array gespeichert. Den Index bekomme ich mit einem Unterprogramm heraus, dass die 3D-Koordinaten in einen Index umwandelt.

Meine Fehler bleiben aber bestehen. Der Else-Block wird weiterhin nicht ausgeführt und ich kann nicht z.B. 32*32 Chunks anlegen. Es geht im Augenblick nur 1*2 und wenn ich Glück hab auch mal 2*2.

Meint ihr, es reicht die Map in einer Datei zu abzuspeichern und nur bei Bedarf zu lesen (der Bedarf findet aber bei jedem Blockupdate statt: max. 4/sek) oder sie ständig im RAM zu lassen. Also ich mein das Geschwindigkeitsmäßig.

Ich habe ein 32bit Programm (jetzt weiß ichs :D ), kann es sein das die 4GB Grenze nicht überschritten werden darf und ich deshalb die Fehler bekomme? Wie ändere ich das in 64bit? Wie ist das mit der Auslagerungsdatei? Gilt da auch die Grenze? Ich programmiere in C++.
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

15

04.01.2014, 10:14

Hallo Forum,

ich komme aufgrund ext. Empfehlung und bin auf der Suche nach ein paar Antworten. Interessant: Thematisch suche ich eine ähnliche Antwort wie der TO, allerdings geht es bei mir tatsächlich nur ums Ablegen von Daten.

Dennoch nutze ich die Chance, um dem TO eine kleine Hilfestellung zu geben:
Am ende müsste man ihm ja sagen das er ein Feld mit den Werten (z.B. (1,1) (1,2) (2,1) (2,2)) speichert bzw. nur (1,1) (2,2) wenn es quadratisch werden soll und dann zusätzlich noch bestimmte Werte die für das Feld zutreffen.
Da ist Dein (ich dutze jetzt der Einfachheithalber) Denkfehler. Dein Vorhaben beschreibst Du ähnlich Civilization 5 - dort hast Du Wald, See, Meer, Berge, Rohstoffe und u. U. parkt eine Einheit drauf. Was Civ5 nicht speichert: Formen. Ich verstehe Deinen Text so, dass Du wirklich die Form mitschreiben willst, aber das gehört definitiv nicht in die Map-Datenbank (oder Datei).

Meine eigentlich logische Begründung: Civ5 hat Polygone - und zwar fest vorgegeben. Diese kannst Du nicht ändern - weder als Workshop-Nutzer, noch als Standardplayer. Und genau dieser Kompromiss schränkt Dein Datenvolumen deutlich ein (Civ5 ist so groß wegen Audio/Video und Animationen). Grundformat? Das gibst DU einmalig vor! ^^

Ich habe selbst eine kleine "Nussschale" geschrieben (bin aber in einer ganz anderen Sprache unterwegs - sorry). Über - ich meine - 55 Zeilen generiert mir der Scriptfetzen eine sich ständig individuelle, neue Welt. Das Konstrukt gibt sehr simpel vor, was da sein kann und ein Wahrscheinlichkeitsfaktor legt noch simpler fest, was dort sein könnte. Der Tipp von mir wäre demnach, dass Du mal ein wenig Papier schwarz machst: Hierarchie eines Feldes Deiner Map anlegen! Angenommen (ich bleibe bei Civ5 als Beispiel) Du hast die Grundtypen (für ein Polygon) "Wald" (typ1), "Wüste" (typ2), "Tundra" (typ3), "Berg" (typ4); etc.; ich beschränke mich auf vier).

Diese Typen können hierarchisch weiter spezialisiert/definiert werden. Denn alle haben Attribute - Dinge wie Form, Farbe, passier-/betretbar, bebaubar. In meinem eigenen Prototyp habe ich eine Fließkommazahl verwendet (geht auch mit Buchstaben) - mein multidimensionales Array sieht ähnlich dem Quellcode für die Tilemap vom DeKugelschreiber aus; hat aber einen - in meinen Augen - Vorteil:

Abstrakte "Map" ...

Quellcode

1
2
3
4
5
1.91 1.92 1.92 1.92 1.93
1.94 0.853869373 0.854869373 0.854869372 1.95
1.94 0.857734823 0.855990298 0.759298334 1.95
1.94 0.853869373 0.854869373 0.754899373 1.95
1.96 1.97 1.97 1.97 1.98


Ihr liegt genau richtig: "1." sagt aus, dass das Feld nicht betreten werden kann - kein Map-Übertritt aka "Außenkante" - zeitgleich maximale Scrollweite. Die 9 ist die Grundgrafik und die Ziffer dahinter regelt die Darstellung (wie die "Kante" eben aussieht, da oben "anders" als "unten" bzw. "links"/"rechts").

Spannend wird es erst mit den Zahlen hinter "0." - diese (da simpel aufgebaut) stehen für jeweils ein Attribut dieses Feldes. "0.853869373" sagt demnach: "betretbar", "Typ Berg", "zu verwendende Grafik", "Animation enthalten", "mögliche Rostoffe", "Vorkommen", "benötigtes Level zum Abbau", "Stadt baubar" usw. Nicht irritieren lassen: Es sind Dreiergruppen - also "853", "869", "373". ;) Damit wird jedes Feld für jeden Spieler "gleich" und das Einlesen entsprechend zackig. Steht dort nix (mehr), steht dort "000" (bspw. alles komplett abgebaut).

Die "Map" selbst liegt als serialisiertes Array in einer Datenbank und wird bei Spielstart abgeholt. Über dieses Array definiert sich später welche "Einheit/Stadt" eines Spielers wo ist (diese definieren sich auch genauso wie das Modell oben - darin sind dann Stärke, Beförderung, Bonus/Malus usw.). Auf die gleiche Weise siehst Du "andere Mitspieler", "Feinde" etc.

Und wieder zurück zum Anfang: Die Polygone sind fest vorgegeben - würde ich nun auch noch deren "Angaben" speichern müssen, wäre das sehr unglücklich und verdammt viel. Du wirst also, werter Copax, einen Kompromiss finden müssen bzgl. Sinn und Unsinn. Je größer die Map, umso fetter das Datenvolumen ... und das klettert tatsächlich auch linear! Und irgendwann kommt der Punkt: Datenbank (nicht erst bei Multiplayer, sorry).

Die Idee von mir dahinter ist das gewöhnliche Navigationssystem in Autos etc. Wenn Du Dir dort die Rohdaten mal anschaust, die das "Vorlesen" ("bitte wenden", "jetzt rechts abbiegen" usw.) benötigt, siehst Du die deutliche Parallele.

Wenn ihr mit den Hochsprachen nun noch Zoom oder 360°-Drehung eingebaut haben wollt, ändert sich am Polygon (Grundform) nichts (Größe (Zoom) und Umrechnungsfaktor aufgrund Perspektive?) ... daher auch mein Veto bzgl. "Mitspeichern".

Bei den echten 3D-Titeln (BF4 usw.) sind es tatsächlich Renderpunkte und Zuhauf Texturen (zzgl. Engine - na klar!). Der Titel zieht dann aber auch GB-Weise Platz und erfordert bequem 2 GB im Speicher. Hier tragen die Punkte noch ergänzende Informationen: "zerstörbar zwischen Punkt A/B" bspw. ... zumindest stelle ich es mir derart "simpel" vor. :spiteful:

Ich wünsche euch ein schönes WE und danke, dass ich kurz meinen Senf einbringen durfte.

Es grüßt ...

meinereiner

16

06.01.2014, 14:33

Also, ich würde für Feldinformationen keine float Werte nehmen. Stattdessen würde ich mir bits reservieren und ein uint32 oder uint64 damit zerlegen. Ist im Endeffekt bestimmt die schönere Variante, weil man nicht die Ungenauigkeit von Fließkommazahlen zu spüren bekommt.

17

06.01.2014, 17:09

... weil man nicht die Ungenauigkeit von Fließkommazahlen zu spüren bekommt.
Ich weiß gerade nicht, ob ich Dir jetzt recht geben soll - wie gesagt: "andere Sprachen". Ich kenne dieses "Problem" nur in Verbindung mit einer schlecht gemachten Datenbank (genauer: schlechte Typisierung, wodurch direkte Rechenoperationen auf der DB dann zu "Ungenauigkeit" führten).

Ob Du nun aber Zahlenfolgen nehmen willst, Buchstaben oder sogar alphanumerisch arbeitest je Polygon, ist eigentlich egal - vorausgesetzt, dass Du a) einen Standard einführst und b) Dich in der Folge bitter daran hältst. Hier funktioniert es überraschend reibungslos, wodurch ich das nur mal in den Raum werfen wollte. ;) Der Begriff "Pattern" ist gar nicht so weit davon weg ... aber das definiert man eben selbst und plant entsprechend.

Bin gespannt, was noch so kommt ...

Beste Grüße

18

06.01.2014, 17:34

Ich habe mich selbst nie wirklich damit beschäftigt, aber ich vermeide es, wo ich kann, floats oder doubles als Datenspeicher zu nehmen, wenn ich exakte Werte benötige. Du wirst auch in keinem Programm einen direkten Vergleich finden (also float == float), weil diese eben nicht exakt funktionieren. Das hängt damit zusammen, wie sie letztendlich gespeichert werden:
wiki

Außerdem würde ich jede Wette eingehen, das eine AND Operation wesentlich schneller ist, als durch 0.001 zu teilen ;)

19

07.01.2014, 11:17

[Kurzform, da der lange Beitrag dank IT-Freeze weg ist: Bestätigt, wenn Du RECHNEN willst ... ich lege aber nur Feldinformationen eines Polygon derart ab! Und genau daher fällt "uint" mit seinem "max value" aus meinem Konstrukt ganz raus, da nicht genügend Ziffern.]

20

07.01.2014, 15:04

Ich versteh nicht, was du mir sagen willst. Wenn ein uint32 nicht reicht, nimm ein uint64...

Werbeanzeige