Map erstellen

  • GM 8
  • Map erstellen

    Hi Leute,

    mit diesem Code simuliere ich einen unendlich großen Raum


    view_xview = obj_player.x - view_wview / 2
    view_yview = obj_player.y - view_hview / 2

    mein Raum ist nur 288x288 px groß

    Nun möchte ich, dass die Map, wie bei Minecraft(aber in 2d!), aus Erde, Stein, Erzen etc gemischt wird ( die Erze sollen unten sein).

    Ich hoffe ihr antwortet mir und bedanke mich schonmal
    Grüße Stupe
  • mit dem Code denn du da geschrieben hast, simulierst du keine n"unendlich" großen Raum sondern Centriest die View legindlich zu dem Player.

    "Unendlich großer Raum" ist ein sehr heikles Thema. Selbst wenn du eine Bewegung nur "simulieren" würdest, müsstest du 1. Die Map beim durchlaufen speichern, und wenn du zurückgehst, sie aus irgendeiner Quelle wieder laden. Wäre nähmlich blöd wenn du zurückgehen möchtest und sich vor deiner Nase auf einmal ein "Berg" generiert wird.
    Falls du so etwas machen möchtest musst du (zumindest fällt mir keine nadere Möglichkeit ein) eine imaginäre x- udn y koordinate machen. Durch das Bewegen des players verschiebst du diese, und generierst einfach eine neue Map die sich zu dem Player bewegt. Dabei Speicherst du die Position der generierten Teillandschaft in irgendeiner Datei. Wenn du nun zurückgehst, prüft er wo du dich befindest und ladet er die Teilmap aus der entsprechenden Datei. Dies ist aber nur so grob Theoretisch hingefetzt worden. Die Technick ist wohl das größte Problem dabei. (Der Game Maker ist nicht sonderlich schnell...)

    Und wenn wir schon beim generieren sind: Einen Map-Generator musst du wohl oder übel selber scripten, bzw. einen bereits existierenden in deine Engine portieren.
    Ich persöhnlich habe einen eigenen "simplen" generator gescriptet, das einzige wass er aber schaft ist "Berglandschaften" zu generieren, bei dem die oberste Spitze mit Erde bedeckt wird.
    Ich nehme dabei einfach mal eine nstartpunkt der Map, (z.B: von der Koordinate x = 0 im Raum und y = room_width/2) und gehe mit einer For schleife lansgam nach Rechts. Dabei generiere ich durch einige zufallszahlen die auf die Y-Koordinate übertragen werden, Blöcke die in einer Art "Linie" quer durch die Map gezogen wird. (das Wiederholt sich bis der definierte Raum z uende geht. Der Startpunkt wird dabei immer zum zuletzt generierten Punkt.)
    Dannach fülle ich die Map von unten nach oben (mittels einer For-Schleife) so lange aus, bis der Generator auf den Block trifft der zu der oben gennanten "Linie" gehört.

    Das ist meine Funktionsweise. Recht simpel, mehr aber auch nicht. Falls du jemals im Internet irgend so einen Generator findest (wo man zumindest die Theorie nachlesen kann) sag mir bescheid. ;)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von LEWA ()

  • ich habe mir jetzt folgendes überlegt

    GML-Quellcode

    1. for(i=1;i<=room_width;i+=16)
    2. var_wahrscheinlichkeit = 3; // in 1 von 3 Fällen trifft das Ergebnis zu
    3. if (ceil(random(var_wahrscheinlichkeit)) == 1) {
    4. //Funktion die ausgeführt werden soll.
    5. }
    6. {
    7. instance_create(x,y+256,obj_ground_gras)
    8. }


    aber das funktioniert nicht. Ich möchte, dass mit einer chance 1 von 3 soll das objekt obj_ground_gras erstellt werden.

    Könnt ihr mir helfen?
    Grüße Stupe
  • Du musst da schon mit mehr Infos rausrücken, damit ich dir helfen kann. Ohne zusätzliche Infos kann ich nur erahnen was der Fehler ist. Ich habe ja keine Ahnung wozu der Script dienen soll.
    Ist das nun ein Script der diese sogennante "Block-linie" erzeugen soll?

    erkläre mir das Problem genauer sonnst kann ich dir nicht helfen. ;)

    mfg

    LEWA
  • Das Skript soll auf jeder x position die chance ausrechnen. Wenn die chance true ist, soll ein Block erstellt werden. So hat man dann den Anfang einer zufällig erstellten Map. Auf der nächsten Ebene teste ich dann, ob ein Objekt unter der Position ist(noch nicht im Code) Wenn dies so ist, wird wieder die Chance 1 von 3 ausgerechnet. Und wenn sie true zurückgibt, wird an der Stelle ein Objekt erstellt. Das muss man nur ein paar mal Wiederholen und man hat Berge auf seiner Map, die Zufällig erstellt wurden. Das mit dem Speichern und laden, weil man sonst unendlich viele Objekte auf einmal auf der Map hätte muss ich dann später machen. Ich habe mir auch überlegt, das nur wenn der View sich bewegt, die Map erweitert wird. Das in Verbindung mit dem Speichern und Laden müsste wenig Speicher und Frames per Second fressen.
    Grüße Stupe
  • Asoo.

    Also so wird der Skript auf jedenfall nicht funktionieren.
    Du gehtst ja garnicht in der X-Position von links nach rechts. Das heisst, der Block wird sooft createt, bis er an das ende des Raums stößt, aber die Position an der das passiert, bleibt immer gleich.

    Ich würde das ungefähr so machen:

    GML-Quellcode

    1. for(i=1;i<=room_width;i+=16)
    2. var zufall;
    3. var x_koord;
    4. var y_koord;
    5. zufall = (random (4)-random(3))*16;
    6. x_koord = i; //x koordinate des Blocks
    7. if not(i=0){ //wenn das NICHT der erste Block ist
    8. y_koord = (floor(zufall/16)*16)+ y_koord; //setze ihn auf zufallsposition + die Position des letzten gesetzten Blocks
    9. }else{
    10. y_koord = (floor(zufall/16)*16)+500; //ansonsten setze ihn auf eine unabhängige zufallsposition (500 ist der abstand von dem oberen Ende der Map.)
    11. }
    12. instance_create(x_koord,y_koord,obj_ground_gras); //erstelle nun ein Objekt auf den Berrechneten Zufallskoordinaten.
    13. var y_fuellen;
    14. y_fuellen = room_height-16; //diese Variable ist der momentane "pointer" in der Y ebene der immer nach oben geschoben wird (in - bereich)
    15. while not (place_free(x_koord,y_fuellen,obj_ground_gras)) and (y_fuellen>0)){ //von unten nach oben solange durchgehen bis ein Objekt gefunden oder die Spitze der Map erreicht wurde.
    16. instance_create(x_koord,y_fuellen,obj_stein); //dies ist die Füllung der Map (also alles was unter dem objekt gras Block ist.)
    17. y_fuellen+=-16;
    18. }
    19. }
    20. }
    Alles anzeigen


    Hab den Code jetzt nicht getestet, aber im Prinzip ist das eine "vereinfachung" des Map generators aus meinem Spiel. Versuchs mal. Musst aber den Skript zu deinem Spiel anpassen.
  • Doch, er ergibt Sinn.
    In meinem Game richte ich die einzelnen Blöcke nach einem Raster aus. (16*16 pixel.)

    Um nun Bugs zu vermeiden, wo der Block um 1-2 Pixel verschoben ist, stelle ich diese Rundung an.
    Nehmen wir an du gibts anstatt zufall die Zahl 523 ein.
    nun rechne mal aus:

    523/16 = 32,6875 (ungerade zahl > nicht ernwünscht.) nun rundest du sie durch floor auf den nächst kleineren Integer ab. Dies wäre dann 32. und da wir die Zahl durch 16 geteilt haben, müssen wir sie wieder mit 16 multiplizieren.
    32* 16 = 512

    Wie du siehst, hat der Script die Zahl 523 auf 512 gerundet, was enorm wichtig ist wenn man Landschaften benutzt die nach einem Raster augerichtet sind.
    Falls du das nicht brauchst, entferne die Rundung einfach und berechne statdessen nur die Zufallszahl.

    das +yKoord am ende des Befehls, ist einfach dazu da um die jetzige Zufallszahl der letzten Zufallszahl "anzugleichen". Das bedeutet wenn dein Letzter Block z.B: auf der höhe y = 240 war, berechnet er eine neue Zufallszahl (für den neuen Block) und addiert sie mit 240. Auf die art und weise können recht schöne Landschaften entstehen, da der aktuelle Block immer auf dem letzten aufbaut. :)
  • Doch das geht. Schau dir mal den Teil des Scripts an:

    GML-Quellcode

    1. if not(i=0){ //wenn das NICHT der erste Block ist
    2. y_koord = (floor(zufall/16)*16)+ y_koord; //setze ihn auf zufallsposition + die Position des letzten gesetzten Blocks
    3. }else{
    4. y_koord = (floor(zufall/16)*16)+500; //ansonsten setze ihn auf eine unabhängige zufallsposition (500 ist der abstand von dem oberen Ende der Map.)
    5. }


    Du hast ja eine For schleife bei der du die Variable "i" deklariert hast.
    Hier prüfst du einfach ob die Variable i den Wert 0 überschritten hat.
    Der Wert ist ja beim ersten durchlafuf der schleife genau 0. Wenn du also den ersten Durchlauf machst, führt er dem Script aus der in }else{} definiert wurde. (da i ja laif der if anweisung nicht 0 sein darf.)
    Dort, überweist er der Variable y_koord zum ersten mal einen festen wert.
    Nun geht die Variable i nach oben, und die If anweisung ( if not(i=0){ ) trifft zu. Dort macht er das mit y_koord = irgendeiwert + y_koord.
    Da y_koord aber einen festen wert hat (und man variablen ebenso benutzen kann wie z.B: a= a*2) funktoniert es auch.

    Wenn bei dir ein Error kommt, musst du mir schon mehr Infos daz ugeben WAS genau schiefgegangen ist.
  • Hier der Fehler:


    ERROR in
    action number 3
    of Create Event
    for object obj_controller:

    Error in code at line 11:
    y_koord = (floor(zufall/16)*16)+ y_koord; //setze ihn auf zufallsposition + die Position des letzten gesetzten Blocks
    ^
    at position 43: Unknown variable y_koord
    Grüße Stupe
  • Ich habe genau den Code, der da oben steht:

    GML-Quellcode

    1. for(i=1;i<=room_width;i+=16)
    2. var zufall;
    3. var x_koord;
    4. var y_koord;
    5. zufall = (random (4)-random(3))*16;
    6. x_koord = i; //x koordinate des Blocks
    7. if not(i=0){ //wenn das NICHT der erste Block ist
    8. y_koord = (floor(zufall/16)*16)+ y_koord; //setze ihn auf zufallsposition + die Position des letzten gesetzten Blocks
    9. }else{
    10. y_koord = (floor(zufall/16)*16)+500; //ansonsten setze ihn auf eine unabhängige zufallsposition (500 ist der abstand von dem oberen Ende der Map.)
    11. }
    12. instance_create(x_koord,y_koord,obj_ground_gras); //erstelle nun ein Objekt auf den Berrechneten Zufallskoordinaten.
    13. var y_fuellen;
    14. y_fuellen = room_height-16; //diese Variable ist der momentane "pointer" in der Y ebene der immer nach oben geschoben wird (in - bereich)
    15. while not (place_free(x_koord,y_fuellen)) and (y_fuellen>0){ //von unten nach oben solange durchgehen bis ein Objekt gefunden oder die Spitze der Map erreicht wurde.
    16. instance_create(x_koord,y_fuellen,obj_stone); //dies ist die Füllung der Map (also alles was unter dem objekt gras Block ist.)
    17. y_fuellen+=-16;
    18. }
    Alles anzeigen
    Grüße Stupe
  • oh, mann. Der Fehler lag bei mir. Sry.^^

    Siehst du ganz oben die For-Schleife? da wird i mit 1 initialisiert. Das ist der Fehler. (Hab mich wohl beim schreiben vertippt...) Wenn i 1 ist, dann ist der erste durchlauf fehlerhaft, da bei der if abfrage das else von "if not i=0" nie zutrifft und die erste initialisierung des y_koords nicht gemacht wird.

    tausche einfach das

    GML-Quellcode

    1. for(i=1;i<=room_width;i+=16)


    gegen das aus:

    GML-Quellcode

    1. for(i=0;i<=room_width;i+=16)


    Nun sollte es funktionieren.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von LEWA ()

  • Mich sollte wirklich einer mal schlagen. XD

    Habe bei mir selber einige Bugs gefunden. (z.B: vbei der For schleife gibts kein "{") das war der primärfehler wieso y_koord nicht erkannt wurde.
    Habe den Script nun selber in ein File gepackt und einige Bugs ausgebessert. Nun sollte es richtig laufen.

    (PS: um die place_meeting/free funktionen im script richtig benutzen zu können, musst du dem obj_controller ein Sprite verpassen das genauso groß ist wie die Blöcke selbst.)
    Um obj_controller ncith anzuzeigen, mach einfach das häckhen bei visible weg. :) (Hab das glaub ich beim example vergessen. XD )

    Hier mal das File:
    Dateien
  • Also zuerst mal will ich mich herzlichst bei dir bedanken für das Programm(schade dass es keinen bedanke Button bei den Technischen Fragen gibt)
    Nur eine kleine Sache stört mich ein bisschen. Hin und wieder entstehen ein paar Missbildungen(siehe Anhang (rechts im Bild)).
    Kann man das irgendwie fixen?

    EDIT: Und noch etwas: Ich habe es schon ausprobiert aber ich kriegs irgendwie nicht hin. Wie könnte man es machen, dass zwischen z.B. 288 und 344 px tiefe an einer zufälligen Position z.B. Stein anfängt und da drüber Erde ist? Und, dass in dem Stein auch hin und wieder Erze (am besten dann in Gruppen) auftauchen?
    Bilder
    • Unbenannt.png

      47,23 kB, 653×514, 144 mal angesehen
    Grüße Stupe

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von xgamesproduction ()

  • Die "Missbildungen" tauchen leider ab und zu auch bei mir auf. Liegt am Generator.
    Anscheinend sind das irgendwelche Zufallswerte die auf einmal rasant hohe Zahlen annehmen.
    Du kannst ja überprüfen, wie groß nun der nächste Sprung nach oben oder unten ist, um nur einen Maximalwert zuzulassen. (eine einfache If-Abfrage.) Dadurch könntest du diese riesigen Wände zumindest auf den Maximal-zulässigen Wert reduzieren.
    Würde das gerne fixen, hab jedoch keine Zeit. (Schulstress.)
    Das mit dem erzen und sonstigem im Untergrund kann man so lösen, dass wenn die Map fertiggeneriert wurde, man einfach per Zufall einen Punkt rausssucht der sich unter der Erde befindet. (Zuffalspunkt auf der Map suchen, und überprüfen wie tief er im Boden steckt. Sprich: Wieviel solide blöcke sich über ihn befinden.) An ihm, löscht man den alten Block und Platziert einfach einen Erz-Block. Um das alles ein wenig realistischer zu gestalten könntest du ja noch einprogrammieren, dass er die Erze in einem bestimmten Radius spawnen lässt. (also z.B: erstelltes_erz.x-32,erstelltes_erz.y-16,etc...)

    Zum Generator kann ich im moment auch nicht viel Machen. Wenn ich bei meinem Game-Projekt mit dem generieren der Map ein wenig weiter bin, kann ich dir ja zur Hilfe kommen. :)