[MonoGame]Minecraft-Klon

    • C#
    • .NET (FX) 4.5–4.8

    Es gibt 161 Antworten in diesem Thema. Der letzte Beitrag () ist von seh.

      Runshak schrieb:

      ich würde keinen shooter daraus machen sondern im minecraft style halten...aber wenn du monster etc hinzufügst, dann könntest du diese so spawnen lassen, sodass diese außerhalb gebauter mauern spawnen und nicht ständig innerhalb eines hauses oder so, nur weils dort dunkel ist...so würde man sich das mühsame ausleuchten ersparen

      Finde ich nicht notwendig. Wenn der Ersteller es jedoch dennoch so machen möchte, dann mach es mit speziellen Blöcken wo Monster nicht spawnen dürfen. Das erleichtert dir das Coden. Ansonsten müsstest du ja irgendwie nach dem Haus Abfragen aber.. dafür müsstest du dem Spiel erst sagen, ab wann ein Haus auch ein Haus ist und.. dafür müsstest du irgendwie das Haus scannen. Ach, egal. Lasst mich. xD Es ist jedenfalls viel einfacher, wenn die Monster nur auf Gras spawnen dürfen.
      Wenn ich eine Frage stelle, habe ich sie bereits gegooglet. Ja, es kommt vor, dass ich die Antwort übersehe. Ja, es kommt vor, dass ich sie nicht verstehe. Deshalb bin ich hier. Wenn dies eure Frage war, dann antwortet bitte nicht. Es stiehlt sämtliche Motivation.
      Ob ein Objekt O ein Haus H ist würde ich folgendergestalt determinieren:

      Fill-Algorithmus( Effiziente Fill Operation durchführen) auf alle preziösen Würfel anwenden.
      Wenn geschlossen; dann muss konkludiert werden das es ein Haus ist....

      aber

      Sekki schrieb:

      dann mach es mit speziellen Blöcken wo Monster nicht spawnen dürfen

      ist effizienter.

      Lichtquellen markieren solche Sektoren.
      Und Gott alleine weiß alles am allerbesten und besser.
      Guten Abend,
      ich verfolge momentan den Ansatz von @jvbsl .
      Problematisch ist jedoch die Indizierung:

      C#-Quellcode

      1. vertices = new VertexPositionColor[HEIGHT * 2 + WIDTH * HEIGHT * 2];
      2. indices = new int[(WIDTH * HEIGHT) * 6];
      3. indicesCounter = 0;
      4. for (int j = 0; j < HEIGHT; j++)
      5. {
      6. for (int i = 0; i < WIDTH; i++)
      7. {
      8. vertices[i + j * WIDTH] = new VertexPositionColor(new Vector3(i, j - 5, -10), Color.Blue);
      9. indices[indicesCounter++] = i + j * WIDTH;
      10. indices[indicesCounter++] = (i + 1) + j * WIDTH;
      11. indices[indicesCounter++] = (i + 1) + (j + 1) * WIDTH;
      12. indices[indicesCounter++] = (i + 1) + (j + 1) * WIDTH;
      13. indices[indicesCounter++] = i + (j + 1) * WIDTH;
      14. indices[indicesCounter++] = i + j * WIDTH;
      15. }
      16. }
      17. vBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor), vertices.Length, BufferUsage.None);
      18. iBuffer = new IndexBuffer(GraphicsDevice, IndexElementSize.ThirtyTwoBits, indices.Length, BufferUsage.None);
      19. vBuffer.SetData<VertexPositionColor>(vertices);
      20. iBuffer.SetData<int>(indices);


      Das Resultat:


      Woran mag das liegen?
      Und Gott alleine weiß alles am allerbesten und besser.
      Update:
      Hat funktioniert!

      Siehe,



      Post scriptum: Erster Test: 3000 x 3000 (187x187 Chunks) große Ebene ~ gefühlt 60 FPS lol!
      Und Gott alleine weiß alles am allerbesten und besser.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „φConst“ ()

      Durch das Entfernen der Indizes können nun "Würfel" gelöscht werden.


      Bald werden demzufolge Chunks fortan nicht anhand von Würfel-Modellen -, sondern mit Flächen repräsentiert.
      Und Gott alleine weiß alles am allerbesten und besser.
      Ich würde eher Vertices anstatt Indices löschen, die Vertices beinhalten ja auch die Information über Texturen etc. macht doch mehr Sinn die zu entfernen.
      Außerdem kann man die Indices für alle CHunks wiederverwenden.
      Ich wollte auch mal ne total überflüssige Signatur:
      ---Leer---
      Ne macht kaum Sinn; zumindest nicht im meiner Implementierung.

      Wenn exemplarisch,

      x x

      x x

      ein Viereck abbildet, so sind diese vier Vertices wiederum ein Teil eines anderen Vierecks,

      also


      X X X

      X X X

      Deswegen macht das Entfernen der Vertices keinen Sinn, denn alle werdene benötigt.
      Und Gott alleine weiß alles am allerbesten und besser.
      Es werden die Vertices erstellt, die gebraucht werden, für jede Seite an der Oberfläche erstmal alle 4 Vertices, d.h. du wirst viele doppelte Vertices haben, selbst wenn es sich bei den nebeneinanderliegenden Flächen um diesselbe Textur handelt(diese Optimierung wird denke ich auch sehr Kompliziert, ich hab mir dazu auch noch nicht wirklich etwas überlegt, da es viele andere Optimierungen gibt, die vermutlich eifacher zu lösen sind und sogar einen größeren Effekt haben dürften).
      Diese Vertices kommen alle einfach in deinen VertexBuffer pro Chunk.
      Der IndexBuffer dürfte dabei für jede Seite immer folgendes Enthalten:
      {i*4+0,
      i*4+1,
      i*4+3,

      i*4+0,
      i*4+3,
      i*4+2
      }
      n ist dabei der Index der Seite(die ansich nicht relevant ist), für jeden Chunk geht i von 0 bis n(Anzahl der Quadrate).
      Wie du aber dabei siehst, ist es vollkommen egal, was für Vertices später verwendet werden, die IndexBuffer werden für jeden Chunk(bis auf die Anzahl der indices) gleich sein. Deshalb reicht dir ein IndexBuffer, der einfach so groß ist, wie es der größte Chunk verlangt.

      Das maximale an benötigten Indices dürfte dem hier entsprechen(kann auch falsch sein):
      Jeder zweite Block gesetzt-> Chunk.Size.X / 2 * Chunk.Size.Y / 2 * Chunk.Size.Z / 2
      Bei jedem Block sind alle Seiten Sichtbar -> Chunk.Size.X / 2 * Chunk.Size.Y / 2 * Chunk.Size.Z / 2 * 6
      eine Seite braucht 6 Indices-> -> Chunk.Size.X / 2 * Chunk.Size.Y / 2 * Chunk.Size.Z / 2 * 6 * 6
      so kann man auch den höchsten Index bereichnen: Chunk.Size.X / 2 * Chunk.Size.Y / 2 * Chunk.Size.Z / 2 * 6 * 4 - 1


      bei 32*32*32 also
      16*16*16*36=147456
      der höchste Index:
      16*16*16*24-1=98303-> es wird ein (U)Int32 zur Indizierung benötigt

      bei 16*16*16:
      8*8*8*36=18432
      höchste Index:
      8*8*8*24-1=12287-> es genügt ein (U)Int16

      welches von beiden nun besser ist lässt sich streiten bei 32^3 brauchst du natürlich nur ein 8tel der DrawCalls, jedoch auch die doppelte größe für den IndexBuffer.
      Ich würde dabei zu den größeren Chunks tendieren, da du nur einen IndexBuffer hast und dieser nur einmal übertragen werden muss, ob das tatsächlich die schnellere Variante ist hab ich nie getestet. Andere Möglichkeit wäre natürlich den IndexBuffer mit Shorts zu machen, bis die obere Grenze bei der Indizierung erreicht wird, ich glaube, dass nur wenige Chunks tatsächlich an die obere Grenze kommen zumindest nicht in einer natürlichen Welt.

      Edit: es ist natürlich gut möglich, dass ich bei der Berechnung einen massiven Denkfehler drinne hab, also falls dir was auffällt auch am besten gleich sagen.
      Ich wollte auch mal ne total überflüssige Signatur:
      ---Leer---

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „jvbsl“ ()

      Texturatlas + entsprechende Texturkoordinaten, was natürlich die übergänge erschwert, da gibt es Möglichkeiten, die ich aber nie erfolgreich umgesetzt habe, wie man verhindert, dass er an den Rändern zwischen den einzelnen Texturen interpoliert.
      Sinnvoller wäre natürlich ein Texture-Array, welches von MonoGame nicht unterstützt wird, schließlich hatte XNA auch nichts in der Art und features hinzufügen wollen sie nicht.
      Andere Möglichkeit ist ein Custom-Vertex-Format(ist sowieso sinnvoll, da man die anderen Daten noch ziemlich komprimieren kann), indem dann für die Vertices die jeweilige Textur über einen Index gespeichert und im Shader aus einem Array die entsprechende auszuwählen.

      (Werbung: oder du versuchst irgendwann auf meine Engine umzustellen, die Texture2DArrays hat :D)
      Ich wollte auch mal ne total überflüssige Signatur:
      ---Leer---
      Sende mal URL zu deiner Engine ahah.

      Interessant:
      Gibt es eine signifikante Differenz zwischen .DrawIndexPrimitives und .DrawInstancedPrimitives?
      Habe beides probiert: Selbe FPS ( bei 3000x3000 ~60 FPS)
      Und Gott alleine weiß alles am allerbesten und besser.
      DrawIndexPrimitives dürfte schneller sein, da Static Instancing(welches genau so gemacht wird) über eben diese Funktion geschieht. Und immer wenn es um Instancing ging hab ich gelesen, dass man falls möglich immer das verwenden soll(heißt, wenn es eben statisch und nicht bewegt ist z.B.). Bewegte braucht man dann evtl. später für Dinge wie fallenden Sand, würde ich dann aber ähnlich MC als Entities machen.
      -> Wenn der Block beginnt zu fallen wird ein Entity gespawnt das genau aussieht wie der Block und an derselben Stelle, der Block wird aus dem Chunk entfernt->Dann beginnt das Fallen mit Kollision->Nachdem eine Kollision erfolgt wird der Block wieder im Chunk gesetzt und das Entity gelöscht.

      Werbung:
      github.com/OctoAwesome/engenious
      gibt sogar nen Nuget Paket dazu, jedoch muss ich dich warnen, ist alles in development das wenigste ist getestet und es funktioniert etwas anders als MonoGame, aber im Grunde ist der Aufbau ähnlich.
      Ich möchte aber im Gegensatz zu MonoGame nicht das exakte Verhalten von XNA nachahmen, sondern hab nur Grundsätzlich den gleichen architektonischen Aufbau, sodass das Umsteigen erleichtert wird(Hab damit angefangen, weil eben MonoGame die Shader nicht funktioniert haben und ich neue features verwenden möchte).
      Meine Engine läuft außerdem komplett auf OGL.
      Die Badges für Linux/Mac lügen aktuell, lokal buildet das bei mir einwandfrei, nur auf den Build-Servern scheint es Probleme zu bereiten(und das nicht mal beim compilen - sondern schon vorher).
      Ich wollte auch mal ne total überflüssige Signatur:
      ---Leer---

      jvbsl schrieb:

      Andere Möglichkeit ist ein Custom-Vertex-Format(ist sowieso sinnvoll, da man die anderen Daten noch ziemlich komprimieren kann), indem dann für die Vertices die jeweilige Textur über einen Index gespeichert und im Shader aus einem Array die entsprechende auszuwählen.


      Hallo, meinst du damit etwa Instancing?
      Ich meine, jeder Chunk ist ein Model für sich.
      Wie kann ich denn die Texture-Indizes für jedes Quad im "Chunk-Model" übergeben?
      Dachte an Instancing, macht ja aber keinen Sinn.


      EDIT: Ach , hab verstanden.
      Neben den fundamentalen Dingen wie Position et cetera, noch ein float, oder Vector2 deklarieren, und schon beim Erzeugen des Squads eine ID zuweisen.
      Dann wird dies dem Shader übergeben, und im Pixel Shader determiniere ich dann, welche Textur zur ID zugewiesen werden muss.
      Stimmt's?
      Und Gott alleine weiß alles am allerbesten und besser.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „φConst“ ()

      Wie gesagt, das sind zwei unterschiedliche herangehensweisen. MonoGame unterstützt keine richtigen TextureArrays, also musst du entweder merhere texturen an den shader einzeln übergeben, und diese dann im shader verwenden, oder in einem texturatlas, dann geht auch alles noch mit dem BasicShader
      Ich wollte auch mal ne total überflüssige Signatur:
      ---Leer---