Problem mit 16x16 Raster

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Problem mit 16x16 Raster

    Hi

    Ich habe jetzt ein soweit gut funktionierendes 16x16 Raster erstellt und stoße nun auf eine kleine Schwierigkeit:
    Jedes Mal, wenn ich mit dem Spieler irgendwo anecke verändert sich der Winkel mit dem ich auf die Tür treffe.
    Kleines Beispiel:
    Wenn ich zu Beginn direkt auf die Tür zugehe komme ich wie gewünscht mittig durch.
    Wenn ich vorher aber etwas rumlaufe und gegen ein paar Wände komme, komme ich eher versetzt zur Tür, also ein paar Pixel weiter rechts/links.

    Ich habe die gmz verlinkt damit ihr es euch selbst ansehen könnt.
    filehorst.de/d/brAhDDEj
    Weiß jemand vielleicht was ich tun muss um das zu beheben?

    MfG :)
  • Ich habe es mir nicht angeschaut, aber du solltest immer beim gehen schauen, ob 16px weiter eine Wand ist. Wenn, dann geh gar nicht erst weiter.
    Ein Bug ist mehr als nur ein Bug, es ist ein... Käfer!
    Egal, wie gut du eine Mauer baust, sie fällt um.... der klügere gibt nach :D

    Willst du mit mir auf Discord Chatten/Quatschen?
    Meine Husi's Tutorial Reihe
  • Ich kann es leider nicht komplett testen, da mein Game Maker mich leider das Projekt immer nur einmal starten lässt. Warum auch immer.. :rolleyes: Aber hier ein paar Dinge, die mir aufgefallen sind:
    1. Player-Sprites: Die Masks sind teilweise unterschiedlich groß. Passe alle auf dieselbe Größe an, denn wenn die Figur bei einem Richtungswechsel plötzlich eine andere Mask hat, sind Fehler vorprogrammiert. Ich empfehle außerdem, die Mask an das 16er-Raster anzupassen, also: Left:0, Right:31, Top:48, Bottom:63.
    2. Room-Erstellung: obj_player wird im Room nicht im 16er-Raster erstellt. Seine Position ist bei der Erstellung X:259, Y:177. Ich empfehle X:256, Y:176.
    3. Wie Husi schon sagte, solltest du vor dem Laufen überprüfen, ob eine Wand im Weg ist. Dies geht beispielsweise, indem du

      GML-Quellcode

      1. if ( target_x > x ) { x += 2 } //right
      zu

      GML-Quellcode

      1. if ( !position_meeting(x + 16, y, obj_wall) and target_x > x ) { x += 2 } //right
      abänderst.
    Wie gesagt, ich kann es zwar leider so nicht testen, aber wenn du diese Dinge anpasst, dann müsste es passen. :)
    kostenlose Android-Spiele:
    hexavirScribble Triple

    Mr. Peperonico auf Facebook
  • Vielen Dank erstmal für deine Hilfe :)
    Die Masken haben unterschiedliche Größen? Hm komisch, ich habe genau darauf versucht zu achten, weil ich ja wusste, dass das ein Muss ist.
    Das mit der Room-erstellung hab ich auch schon gemerkt, dass das ein Problem ist, wusste nur nicht, wie ich es richtig machen kann. Werde mal gucken.
    Das mit der Wand habe ich nicht wirklich verstanden, ich soll aufpassen, wo eine Wand ist und dann?

    Edit: Das mit den Masken habe ich auch nicht ganz verstanden:
    Left:0 und Right: 31?
    Dann ist ja die ganze Sprite in der Mask, plus der ganze Platz wo nichts ist.
    Und 31-0=31 Das kann doch gar nicht mit einem 16x16 Raster kompatibel sein
  • Matt Mats schrieb:

    [...] Die Masken haben unterschiedliche Größen? [...]

    Japp, die Bottom-Werte unterscheiden sich. Zwar nur um einen Pixel (62 bzw. 63), aber es kann unter Umständen je nach Code einen Unterschied machen.

    Matt Mats schrieb:

    [...] Das mit der Wand habe ich nicht wirklich verstanden, ich soll aufpassen, wo eine Wand ist und dann?

    Sorry, ich habe da einen kleinen Denkfehler gemacht. Vergiss meine Codezeile oben. :) Also, im Wesentlichen funktioniert dein Code momentan so:
    1. Spieler drückt Taste "Links".
    2. target_x wird auf x-16 gesetzt.
    3. x wird um 2 verringert.
    4. Schritt 3 wird pro Step wiederholt, bis x gleich target_x ist.
    Schritt 3 sollte rein rechnerisch acht mal (16/2=8) wiederholt werden.

    Während der Wiederholungen von Schritt 3 wird in jedem Step überprüft, ob eine Kollision mit obj_wall vorliegt. Die Maske für spr_player_left fängt bei Left:4 an. Das heißt, Schritt drei wird nur drei mal wiederholt, denn dann liegt eine Kollision vor und das Laufen wird gemäß des Kollisions-Events beendet. Und schon ist obj_player nicht mehr im 16er-Raster, da er nur sechs Pixel nach links gelaufen ist.

    Abhilfe schafft entweder die Anpassung der Maske auf Left:0 oder, die saubere Variante, eine Überprüfung, ob sich links neben dem Spieler eine Wand befindet. Wenn dort eine Wand ist, braucht der Spieler dann gar nicht loszulaufen. Die anzupassende Codezeile wäre dann:

    GML-Quellcode

    1. if ( (key_left) && !moving ) {
    2. //wird zu:
    3. if ( (key_left) && !moving && !position_meeting(x - 16, y, obj_wall) ) {
    So wird das Laufen gar nicht erst ausgelöst, wenn sich eine Wand im Weg befindet. Das Kollisions-Event kannst du dann auch entfernen, das wird nicht mehr benötigt.
    kostenlose Android-Spiele:
    hexavirScribble Triple

    Mr. Peperonico auf Facebook
  • Vielen Dank,
    jetzt habe ich nur noch eine Frage zu den Masken.
    Und zwar passt doch das, was du vorgeschlagen hast, gar nicht in das Raster, und auch wenn es das würde, sähe es doch ziemlich schlecht aus,
    weil die Kollision so klotzartig wäre.
    Ich dachte es funktioniert folgendermaßen:
    Left/Right 7 - 23
    Top/Down 47 - 63

    Ergeben 32-7= 16
    63-47=16

    Oder habe ich da einen Denkfehler?
  • Es zählen immer die ersten und die letzten Pixel in der Maskengröße mit. Sprich bei Left/Right 7/23 hast du eine Mask-Breite von 17 Pixeln. Um horizontal mittig 16 Pixel als Mask zu setzen, brauchst du demzufolge Left:8 und Right:23. Vertikal wären es dann Top:48 und Bottom:63.

    Mein Vorschlag für die Maske ist 32x16px groß, was ins 16er-Raster passt. Bei 32x16px hält die Spielfigur immer einen Abstand von 16px zur nächsten Wand nach rechts und links. Bei 16x16px kann er mit der Nase die Wand berühren. Die Wahl ist nun eine Frage des Geschmacks oder eine Frage, was besser zum Rest des Gameplays passt. :)
    kostenlose Android-Spiele:
    hexavirScribble Triple

    Mr. Peperonico auf Facebook
  • lös es lieber so:

    du brauchst zwei collision_line abfragen, eine horizontale und eine vertikale. Wie ein Fadenkreuz auf dem Spieler, aber die Linien bewegen sich je nach playerspeed nach oben oder unten und links oder rechts.

    GML-Quellcode

    1. if !collision_line(x-8,y+(spd*8), x+7,y+(spd*8), obj_wall, false, true){
    2. y += spd;
    3. }


    spd*8 falls spd 1 ist, wenn spd 2 ist dann * 4, damit du immer auf 8 vom mittelpunkt kommst.

    Damit bleibst du an Wänden nicht mehr Hängen sondern kannst daran entlang gleiten. Das geht aber nur für rechtecke. Wenn du vielecke haben willst, dann musst du das anders lösen.

    ancient-pixel.com
    youtube.com/user/SebastianMerkl <<< ich freu mich über einen Besuch ;)
  • Na...Ich glaube wir entfernen uns zu sehr vom Anfang.
    Also ich habe die Maske bei allen Sprites jetzt auf
    Left 8 Right 23
    Top 48 Bottom 63
    gesetzt und die Origin auf 16 | 32
    Was mir übrigens auch gerade auffällt ist, dass die Sprite nach oben so merkwürdig verzerrt aussieht im Spiel,
    also ganz anders aussieht als außerhalb.
    Bilder
    • Screenshot - 21_05.png

      24,64 kB, 544×416, 509 mal angesehen
  • Also du kannst es einfach so machen :
    Schmeiß mal den ganzen collision code raus und für deine Steuerung, dann machst du einfach im step event vom Spieler:

    GML-Quellcode

    1. var spd = 4;
    2. var forward = keyboard_check(ord("W")) - keyboard_check(ord("S"));
    3. var side = keyboard_check(ord("D")) - keyboard_check(ord("A"));
    4. scr_motion(side*spd,forward*spd,obj_wall);


    Das Script sieht wie folgt aus, brauchst du nur kopieren und einfügen:
    obj ist das Objekt mit dem kollidiert werden soll. Du kannst auch ein leeres par_wall Objekt erstellen und das als parent für mehrere Objekte eintragen. Dann berücksichtigt die Funktion alle "childs" dieses parent objektes.

    GML-Quellcode

    1. ///scr_motion(hsp,vsp,obj)
    2. repeat(ceil(abs(argument0))) {
    3. if(place_meeting(x+lengthdir_x(1,sign(argument0)*90),y + lengthdir_y(1,sign(argument0)*90),argument2)== 0) {
    4. x += lengthdir_x(1,sign(argument0)*90);
    5. y += lengthdir_y(1,sign(argument0)*90);
    6. } else break;
    7. }
    8. repeat(ceil(abs(argument1))) {
    9. if(place_meeting(x+lengthdir_x(1,-90+sign(argument1)*90),y + lengthdir_y(1,-90+sign(argument1)*90),argument2)== 0) {
    10. x += lengthdir_x(1,-90+sign(argument1)*90);
    11. y += lengthdir_y(1,-90+sign(argument1)*90);
    12. } else break;
    13. }
    Alles anzeigen

    132 little bugs in the code. 132 little bugs. Fix a few, set the compiler to stew, 172 little bugs in the code... :vogel:

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

  • Jetzt kommen wir wieder an den Punkt an den wir immer beide immer kommen, Rhazul^^
    Ich verstehe nicht, was das ist, was das machen soll und in wie fern mir das was helfen soll und ob und wieso ich nun meinen ganzen bisherigen Code löschen soll, weil ich die Bewegung anders aufgebaut habe.
    Mir würde es am besten helfen, wenn man mir sagen würde, was genau falsch läuft und weshalb genau das mit den feldern nicht hinhaut und was dagegen zu tun ist, schließlich will ich ja wissen, was ich da für einen Code benutze.
    Ich habe ja oben alles gepostet, was ich bisher verändert habe.
    Was wir vielleicht auch machen könnten ist wenn du willst, dass du mal versuchst, das in die Datei die ich dir geschickt habe einzusetzen und mir dann zu schicken, damit ich sehen kann ob es klappt.
  • Das script nimmt eine horizontale und eine vertikale Geschwindigkeitskomponente. Es prüft für Kollisionen mit obj, geht aber dabei pixel für pixel vor. Das heißt wenn du bspw. 8 pixel nach rechts verschieben willst, bei 6 aber schon die wand kommt, dann bewegt es deinen spieler genau bis an die Wand. Und wiegesagt das Script brauchst du ja nur speichern unter dem Namen scr_motion. Was du im Endeffekt nur selber machen musst ist den scriptaufruf selber im step event einzufügen, das sind die paar zeilen ganz oben. forward und side können jeweils entweder -1,0 oder 1 ergeben, jenachdem in welche Richtung gedrückt wird. Mit spd multipliziert ergibt das dann die Geschwindigkeitskomponente. Ich meine ja auch nicht das du alles wild löschen sollst, nur deinen bewegungscode mal auskommentieren damit es nicht zu Konflikten kommt. Ich kann dir einen Lösungsvorschlag anbieten, aber wenn du ihn dann nichtmal testest sind mir die Hände gebunden. Ansonsten musst du auch sagen was genau du nicht verstehst, ich hoffe ich konnte es aber schon etwas mehr erläutern.
    132 little bugs in the code. 132 little bugs. Fix a few, set the compiler to stew, 172 little bugs in the code... :vogel:
  • Da ich nicht weiß was du willst, und ich mir nichtmal sicher bin ob du das selber genau weißt, war ich mal so frei dein Projekt zu modifizieren wie ich es mir in etwa vorgestellt habe. Das Hauptproblem war das du deine Origins nicht gecentert hast. Ich habe jetzt ein sprite namens msk_player erstellt, das wird als Maske für alle Richtungen verwendet, ausserdem ist es 32x32 was genau in dein grid passt. Gucks dir einfach mal alles an, hab hier und da ein paar Kleinigkeiten angepasst.

    mediafire.com/file/m33cwoir44551z8/Grain_fixed_Rhz.gmz
    132 little bugs in the code. 132 little bugs. Fix a few, set the compiler to stew, 172 little bugs in the code... :vogel:
  • Vielen Dank für deine Mühe,
    aber das ist ja wieder was völlig anderes xD
    Bitte nimm es mir nicht übel, aber in sämtlichen meinen Threads bisher in denen du einen Lösungsvorschlag gebracht hast, hat sich alles nur verschlimmert, bis ich es gar nicht mehr verstanden habe und entnervt aufgehört habe..
    Also entweder haben wir ein Kommunikationsproblem oder ich weiß nicht woran das liegen könnte... ^^

    Das Problem ist nach wie vor einfach nur, dass der Character anscheinend nicht wie er es soll, nämlich auf dem gleichen Wege durch die Tür kommt.
    Das Raster ist 16x16 groß, ebenso sollte die Kollisionsmaske 16x16 breit sein.
  • Nun das lässt sich sicher noch einbauen, aber auch wenn du es nicht hören willst, dein Ansatz bis jetzt war sehr Fehlerhaft in seiner Ausführung. In wiefern ist das den jetzt was "ganz anderes", Macht doch eigentlich genau das wie vorher, nur das der Code im Spieler jetzt übersichtlicher ist und deine collisions waren vorher nach unten rechts verschoben. Beim "raster" bin ich jetzt mal von 32x32 ausgegangen weil dein Spieler 32 breit ist und auch sonst alle Hindernisse. Kannst aber einfach die msk_player 16x16 machen und dann das origin davon auf x:8 y:0 setzen EDIT: Bei einem Raster von 16x16 kann er doch auch garnicht "gerade" auf die Türe zulaufen? Zumindest nicht wenn man davon ausgeht das der Spieler In der mitte eines Feldes stehen soll
    132 little bugs in the code. 132 little bugs. Fix a few, set the compiler to stew, 172 little bugs in the code... :vogel:

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