Tutorial für RandomMapGeneration mit Slopes, Part 1

    • GM 8
    • Tutorial für RandomMapGeneration mit Slopes, Part 1

      Hallo Leute,

      ich bin zurzeit am arbeiten eines vollen 2D Random Map-Generators.
      Hier im ersten Teil behandeln wir die Floor-Creation und das setzen von Slopes.
      Ich empfehle das hier für etwas fortgeschrittene Nutzer, weil ich nicht jeden einzelnen Schritt bis ins Detail erklären will.

      Ihr braucht hierfür nur ein Sprite, welches 6 Subimages hat:
      Leer (16x16)
      Block (16x16)
      Slope Right (16x16)
      Slope Left (16x16)
      Long Slope Right (32x16)
      Long Slope Left (32x16)

      Die Idee hinter diesem Generator ist, die floorLevel[x] Variable als Basis für jede weitere Berechnung zu führen.
      floorLevel[x] gibt immer die Höhe des Bodens an der Koordinate [x] an.
      So kann man weitere Sachen wie Slopes, Platformen, usw. sehr einfach setzen, ohne extra eine Funktionen für das Suchen des Bodens zu machen (Was ich durchaus bei anderen Codes schon gesehen habe.)

      Nach der MapGeneration will ich das Ganze block[x, y] - Array in eine Instanz der Klasse "Map" werfen, welche das Array dann mit "|" Seperatoren abspeichert bzw. laden kann.

      Ich habe ebenfalls Konstanten gesetzt, damit die blockIDs (Slope, Wasser, whatever) besser zu identifzieren sind, und alles mit nur einem 2D-Array lösbar ist (blocks[,]).

      (Werde die Erklärung hier morgen weiterführen, entschuldigt bitte mein halbfertiges Tutorial, hab vergessen dass das hier erst approved werden muss ^_^)


      Fangen wir mal an.
      Verbesserungsvorschläge und Kritik gerne gesehen.

      GML-Quellcode

      1. /***************************\
      2. | Block IDs (Konstanten!)
      3. | 1: BLOCK_GROUND
      4. | 2: BLOCK_SLOPER
      5. | 3: BLOCK_SLOPER
      6. | 4: BLOCK_LSLOPER
      7. | 5: BLOCK_LSLOPEL
      8. | 6: BLOCK_PLATFORM
      9. | 7: BLOCK_WATER
      10. | 8: BLOCK_
      11. | 9: BLOCK_FILL
      12. \***************************/
      13. mapBiome = argument0; //Wird hier nicht benötigt
      14. mapWidth = argument1; //Die Breite der Map in Blocks
      15. mapHeight = argument2; //Die Höhe der Map in Blocks
      16. gridSize = argument3; //Die Größe eines Blocks (Qudratisch, in Pixel, zB "16")
      17. thisMap = instance_create(0, 0, Map); //Hier erstellen wir eine Instanz der Klasse "Map", um später die Map darin abzuspeichern.
      18. //Eine relative schlechte Pseudo-Random ID-Generation, kann aber ignoriert werden:
      19. _ran = string(random((mapWidth+mapHeight)*mapBiome)) + string(thisMap.id);
      20. thisMap.mapID = md5_string_utf8(_ran);
      21. //getBiomeInfo(mapBiome);
      22. //Ich verwende hier normalerweise eine Funktion, die die Biome-Einstellungen in einem switch() Statement erkennt,
      23. //aber in diesem Tutorial werde ich die Variablen direkt setzen.
      24. biomeHeightVariation = 2; //Die Höhenvariation der Map (Wie stark die "Stufen" der Map sein sollen)
      25. biomeHeightFrequency = 20; //Soll zwischen 0-100 sein, quasi in %. Die Wahrscheinlichkeit, dass sich die Höhe pro Generation Step verändert. Niedrige Zahl = Flache Map.
      26. biomeHighestLevel = 5; //Der maximale Abstand von Decke zu Boden.
      27. biomeLowestLevel = 5; //Der maximale Abstand von untersten Levelrand zu Boden.
      28. biomeSlopeFrequency = 50; //Die Häufigkeit von "Slopes". (Schräge Platformen)
      29. /*****************\
      30. | Generate Floor |
      31. \*****************/
      32. floorLevel[0] = floor(mapHeight/2); //Der floorLevel[x] (Höhe des Boden auf gegebener X Koordinate) wird auf die Mitte(y) der Map gesetzt.
      33. block[0, 0] = 0;
      34. _level = floorLevel[0]; //_level ist eine temporäre Variable, die wir während der nächsten for-Schleife brauchen
      35. for(xx=0; xx<mapWidth; xx+=1) { //Diese For-Schleife geht die gesamte Map von 0 - mapWidth durch.
      36. hMod = round(random_range(-biomeHeightVariation, biomeHeightVariation)); //Hier erhalten wir einen zufälligen Wert, der die Höhenmodifikation beschreibt...
      37. if(getChance(biomeHeightFrequency)) { //Dieser wird aber nur wirksam, wenn getChance() true zurückgibt.
      38. // getChance() ist eine Funktion, die mit einer Prozentzahl gefütter wird (0-100) und dann true oder false zurück gibt. Code für getChance() weiter unten.
      39. _level = _level + hMod;
      40. }
      41. if(_level < biomeHighestLevel) { //Checken, ob _level nicht über dem highestLevel ist.
      42. _level = biomeHighestLevel; //Und zurücksetzen, falls doch.
      43. }
      44. if(_level > mapHeight - biomeLowestLevel) { //Dasselbe wird mit lowestLevel gemacht.
      45. _level = biomeLowestLevel;
      46. }
      47. floorLevel[xx] = _level; //den derzeitigen _level im floorLevel array abspeichern.
      48. block[xx, _level] = BLOCK_GROUND; //und einen Block auf diese Koordinate setzen.
      49. _fill = mapHeight - _level; //_fill ist die Höhe, die der Mapgenerator füllen muss, damit auch unter nicht nur Luft ist.
      50. for(h=0; h<_fill; h+=1) {
      51. block[xx, _level+h+1] = BLOCK_FILL; //Hier wird aber nicht mit BLOCK_GROUND gefüllt, da das sehr leistungsfressend ist.
      52. // stattdessen nehmen wir BLOCK_FILL her, das im nächsten Teil des Tutorials als Tile gesetzt wird, und nicht als Objekt.
      53. }
      54. }
      55. /*****************\
      56. | Generate Slopes |
      57. \*****************/
      58. //Kommen wir nun zu den Slopes
      59. for(xx=1; xx<mapWidth-1; xx+=1) { //Wir gehen ein weiteres mal die gesamte Map durch.
      60. _possibleSlope = getPossibleSlope(xx, floorLevel[xx]); //getPossibleSlope() gibt einen Wert zwischen 0 und 5 zurück, welche Slope an dieser Stelle passend wäre.
      61. if(_possibleSlope != 0 && getChance(biomeSlopeFrequency) == true) { //Falls getPossibleSlope() keine 0 geliefert hat, setzen wir über dem aktuellen Block eine Slope.
      62. block[xx, floorLevel[xx] - 1] = _possibleSlope;
      63. }
      64. }
      65. /*****************\
      66. | Place Blocks |
      67. \*****************/
      68. //Nun werden die Blocks gesetzt.
      69. for(w=0; w<mapWidth; w+=1) {
      70. for(h=0; h<mapHeight; h+=1) { //Wir gehen das gesamte 2-D Array block[,] durch, und setzen für jeden Block, der nicht 0 (BLOCK_AIR) oder 9(BLOCK_FILL) ist, eine Instanz.
      71. if(block[w, h] != BLOCK_AIR && block[w, h] != BLOCK_FILL) {
      72. _b = instance_create(w*16, h*16, Block);
      73. _b.image_index = block[w, h];
      74. }
      75. }
      76. }
      Alles anzeigen


      Hier der getPossibleSlope() Code:

      GML-Quellcode

      1. _x = argument0;
      2. _y = argument1;
      3. _possible = 0;
      4. // Slope Right
      5. if(block[_x+1, _y-1] == 1 && block[_x, _y] == 1) {
      6. if(block[_x, _y-1] == 0 && block[_x-1, _y-1] == 0 && block[_x-1, _y] == 0) {
      7. _possible = BLOCK_SLOPER;
      8. }
      9. }
      10. // Slope Left
      11. if(block[_x-1, _y-1] == 1 && block[_x, _y] == 1) {
      12. if(block[_x, _y-1] == 0 && block[_x+1, _y-1] == 0 && block[_x+1, _y] == 0) {
      13. _possible = BLOCK_SLOPEL;
      14. }
      15. }
      16. // Long Slope Right
      17. if(block[_x+1, _y-1] == 1 && block[_x, _y] == 1 && block[_x-1, _y] == 1) {
      18. if(block[_x-1, _y-1] == 0 && block[_x, _y-1] == 0) {
      19. _possible = BLOCK_LSLOPER;
      20. }
      21. }
      22. // Long Slope Left
      23. if(block[_x-1, _y-1] == 1 && block[_x, _y] == 1 && block[_x+1, _y] == 1) {
      24. if(block[_x+1, _y-1] == 0 && block[_x, _y-1] == 0) {
      25. _possible = BLOCK_LSLOPEL;
      26. }
      27. }
      Alles anzeigen


      return _possible;

      Und hier noch der getChance() Code:

      GML-Quellcode

      1. _chance = argument0;
      2. _ran = random(100);
      3. if(_ran < _chance) {
      4. return true;
      5. }

      Das Ganze ist eigentlich weniger ein Tutorial als ein nützlicher Script zum völlig modularen erstellen von Zufällig generierten Maps.
      In den Folgeteilen werde ich noch Platformen, Tilesets, usw. Hinzufügen.

      Ich hoffe ich habe hiermit jemandem weitergeholfen. :)

      Mir fällt gerade auf, dass das Ganze hier ohne Beispieldatei relativ nutzlos ist.
      Werde morgen eine .gmk hierfür hochladen.
      Dieser Beitrag wurde bereits 8.675.628 mal editiert, zuletzt von »levarris07« (Heute, 11:33)

      Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von levarris07 ()