Wieder ein Pathfinding Problem

  • GM 7

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

  • Wieder ein Pathfinding Problem

    Ich habe einen Gegner, der nur in 4 Richtungen laufen kann, wie meine Hauptfigur. Generell soll es so sein, dass dieser Gegner die Spielfigur verfolgen soll, ggf. erst bei einem bestimmten Abstand, aber dies ist jetzt mal Nebensache.

    Nun habe ich hier schon einige Texte durch gelesen, an der Umsetzung scheitert es. Letztlich machte mir dieses Tutorial die meiste Hoffnung: Wegfindung mit den "mp-grid"...

    Dabei habe ich zwei Probleme.

    1.) Ein Kollisionsverhalten mit Wänden wird nicht berücksichtigt. Sprich: meine Figur geht durch die Wand durch.
    2.) Meine Figur berücksichtigt das Gitter (64*64) nicht mehr und läuft schräg.

    Kann mir da mal jemand auf die Sprünge helfen?
  • GML-Quellcode

    1. if (point_direction(x,y,obj_player.x,obj_player.y)>=90) && (point_direction(x,y,obj_player.x,obj_player.y)<180)
    2. {
    3. y-=1
    4. }
    5. if (point_direction(x,y,obj_player.x,obj_player.y)>=0) && (point_direction(x,y,obj_player.x,obj_player.y)<90)
    6. {
    7. x-=1
    8. }
    9. if (point_direction(x,y,obj_player.x,obj_player.y)>=180) && (point_direction(x,y,obj_player.x,obj_player.y)<270)
    10. {
    11. y+=1
    12. }
    13. if (point_direction(x,y,obj_player.x,obj_player.y)>=270) && (point_direction(x,y,obj_player.x,obj_player.y)<360)
    14. {
    15. x+=1
    16. }
    Alles anzeigen

    Das ist damit er direkt hin läuft. Doch Wände werden nicht berücksichtigt. Mal schauen was mir einfällt.


    1.) Ein Kollisionsverhalten mit Wänden wird nicht berücksichtigt. Sprich: meine Figur geht durch die Wand durch.
    Hast du die Wände Solid?
    MfG Henrik1235
    wupto.net/ Nicht meine Seite!
    We love Koalas.

    GM-D-Spam-o-Meter: 32%

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

  • Klar, alles was Spieler und Gegner blockt, ist "Solid". In der Maske/Gitter sind die auch aufgenommen. Der Code sieht so aus:

    GML-Quellcode

    1. mp_grid_clear_all(global.Netz);
    2. mp_grid_add_instances(global.Netz,obj_baum_001,0);
    3. mp_grid_add_instances(global.Netz,obj_baum_002,0);
    4. mp_grid_add_instances(global.Netz,obj_exit,0);
    5. mp_grid_add_instances(global.Netz,obj_felsen,0);
    6. mp_grid_add_instances(global.Netz,obj_loch,0);
    7. mp_grid_add_instances(global.Netz,obj_block,0);
    8. mp_grid_add_instances(global.Netz,obj_brocken,0);


    Der Witz: bei zwei von drei dieser Objekte macht er auch einen Boden drum herum. Bei obj_baum_001 aber nicht. Alle sind Solid, alle haben die selbe Maske. :S
  • false hat leider nichts gebracht. Ich habe aber festgestellt, dass er in etwa 32 Pixel in die Objekte rein läuft, die ihn blockieren sollen. Ich glaube das liegt an der Ausrichtung der Figur, die nicht im Zentrum ist sondern links oben.

    GML-Quellcode

    1. mp_grid_path(global.Netz,Pfad,x+32,y+32,obj_pospos.x,obj_pospos.y,0);


    Das +32 sieht schon wesentlich besser aus. Deinen Code habe ich so angepasst:

    GML-Quellcode

    1. if (point_direction(x,y,obj_pospos.x,obj_pospos.y)>90) && (point_direction(x,y,obj_pospos.x,obj_pospos.y)<180)
    2. {
    3. y+=1
    4. }
    5. if (point_direction(x,y,obj_pospos.x,obj_pospos.y)>0) && (point_direction(x,y,obj_pospos.x,obj_pospos.y)<90)
    6. {
    7. x+=1
    8. }
    9. if (point_direction(x,y,obj_pospos.x,obj_pospos.y)>180) && (point_direction(x,y,obj_pospos.x,obj_pospos.y)<270)
    10. {
    11. y-=1
    12. }
    13. if (point_direction(x,y,obj_pospos.x,obj_pospos.y)>270) && (point_direction(x,y,obj_pospos.x,obj_pospos.y)<360)
    14. {
    15. x-=1
    16. }
    Alles anzeigen


    Aber egal wo ich es einfüge (Step, End Step, Beginn Step) es bringt leider keine Verbesserung.
  • Ja es muss ins Step Event.

    GML-Quellcode

    1. if (point_direction(x,y,obj_pospos.x,obj_pospos.y)>=90) && (point_direction(x,y,obj_pospos.x,obj_pospos.y)<180)
    2. {
    3. y-=1
    4. }
    5. if (point_direction(x,y,obj_pospos.x,obj_pospos.y)>=0) && (point_direction(x,y,obj_pospos.x,obj_pospos.y)<90)
    6. {
    7. x+=1
    8. }
    9. if (point_direction(x,y,obj_pospos.x,obj_pospos.y)>=180) && (point_direction(x,y,obj_pospos.x,obj_pospos.y)<270)
    10. {
    11. y+=1
    12. }
    13. if (point_direction(x,y,obj_pospos.x,obj_pospos.y)>=270) && (point_direction(x,y,obj_pospos.x,obj_pospos.y)<360)
    14. {
    15. x+=1
    16. }
    Alles anzeigen

    Habs verbessert und getestet.
    wupto.net/ Nicht meine Seite!
    We love Koalas.

    GM-D-Spam-o-Meter: 32%
  • Also wenn ich dich richtig verstanden habe bewegt sich dein charakter auf nem Grid von Kästen zu Kästchen? So wie bei Pokemon, oder?

    Ich hatte son ähnliches Problem mit Pathfinding und mir ist aufgefallen, dass der GM die Pfade immer von den Origins der Sprites/Mask aus berechnet. Deswegen wirds bei dir auch besser geworden sein als du +32 dazu gemacht hast. 64/2 = 32 <- das ist der Wert um welchen du die Pfadberechnung verschieben musst. Sowohl Start- als auch Endpunkt. In deinem Code oben haste nur den Startpunkt verbessert.

    Mein Pathfinding sieht so aus:

    GML-Quellcode

    1. tile_half = c_tilesize/2;
    2. mp_grid_path(global.grid,path0,x+tile_half,y+tile_half,obj_player2.x+tile_half,obj_player2.y+tile_half,false); //Wenn du hier statt false/true schreibst gehen deine Gegner auch diagonal
    3. px = path_get_point_x(path0,1)-tile_half;
    4. py = path_get_point_y(path0,1)-tile_half;
    5. x = px;
    6. y = py;


    tile_half ist natürlich die halbe Größe eines Grid-Kästchens. In meinem Fall sind das 8 da mein Grid 16x16 große Felder hat.
    Die Origin meiner Mask (die ist auch 16x16 groß) ist wie bei dir auch links oben. Durch das Addieren von der halben Tilegröße wird der Start bzw. Endpunkt des zu berechnenden Path in die Mitte verschoben und auf einmal funktioniert das einwandfrei.

    px/py ist der erste Knoten innerhalb des Path, da mein Spiel rundenbasiert ist brauch ich nur diesen Knoten, damit die Koordinaten aber wieder stimmen muss man den Pfad wieder zum Ursprung zurück verschieben. Also die Hälfte eines Tiles wieder abziehen.
    Weiß aber nich ob du sowas brauchst, wenn du den Pfad nicht unbedingt starten willst dann kannste so halt jeden Punkt einzeln auslesen und dann den Gegner von Hand einfach in jedem Step um einen Knoten oder so weiter verschieben.
    Ansonsten musste halt drauf achten dass du den Pfad vor dem Starten wieder um eine halbe Tile Größe zurück verschiebst sonst spinnt wieder alles rum und deine Gegner laufen wenn überhaupt nur komisch durch die Wände :|

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

  • Dank der Hilfen, vor allem von henrik1235, hat es funktioniert. Danke an Thodd für das Feintuning!

    Die Figur findet nun den Weg. Mein Problem ist nur noch, dass die Animationsrichtungen nicht funktionieren wollen. Bei anderen Gegnern, die Stur ihren Weg laufen, habe ich das über hspeed und vspeed Abfragen gelöst, was auch eine saubere Sache war. henrik1235 hilft mir hier zwar auch schon über PN, aber den aktuellen, nicht funktionieren wollenden Code schreibe ich mal hier rein. Was nicht funktioniert sind die Animationen, Wegfindung ist 1A. Das ist aus dem Step-Event des Gegners:

    Spoiler anzeigen

    GML-Quellcode

    1. tile_half = 64/2;
    2. mp_grid_path(global.Netz,Pfad,x+tile_half,y+tile_half,obj_pospos.x+tile_half,obj_pospos.y+tile_half,0);
    3. path_start(Pfad,2,0,0);
    4. px = path_get_point_x(path0,1)-tile_half;
    5. py = path_get_point_y(path0,1)-tile_half;
    6. x = px;
    7. y = py;
    8. if (point_direction(x,y,obj_pospos.x,obj_pospos.y)>=90) && (point_direction(x,y,obj_pospos.x,obj_pospos.y)<180)
    9. {
    10. y-=1
    11. if (hspeed > 0)
    12. {
    13. sprite_index=spr_chu_verf1
    14. image_speed=1;
    15. }
    16. if (hspeed < 0)
    17. {
    18. sprite_index=spr_chu_verf2
    19. image_speed=1;
    20. }
    21. if (vspeed > 0)
    22. {
    23. sprite_index=spr_chu_verf4
    24. image_speed=1;
    25. }
    26. if (vspeed < 0)
    27. {
    28. sprite_index=spr_chu_verf3
    29. image_speed=1;
    30. }
    31. }
    32. if (point_direction(x,y,obj_pospos.x,obj_pospos.y)>=0) && (point_direction(x,y,obj_pospos.x,obj_pospos.y)<90)
    33. {
    34. x+=1
    35. if (hspeed > 0)
    36. {
    37. sprite_index=spr_chu_verf1
    38. image_speed=1;
    39. }
    40. if (hspeed < 0)
    41. {
    42. sprite_index=spr_chu_verf2
    43. image_speed=1;
    44. }
    45. if (vspeed > 0)
    46. {
    47. sprite_index=spr_chu_verf4
    48. image_speed=1;
    49. }
    50. if (vspeed < 0)
    51. {
    52. sprite_index=spr_chu_verf3
    53. image_speed=1;
    54. }
    55. }
    56. if (point_direction(x,y,obj_pospos.x,obj_pospos.y)>=180) && (point_direction(x,y,obj_pospos.x,obj_pospos.y)<270)
    57. {
    58. y+=1
    59. if (hspeed > 0)
    60. {
    61. sprite_index=spr_chu_verf1
    62. image_speed=1;
    63. }
    64. if (hspeed < 0)
    65. {
    66. sprite_index=spr_chu_verf2
    67. image_speed=1;
    68. }
    69. if (vspeed > 0)
    70. {
    71. sprite_index=spr_chu_verf4
    72. image_speed=1;
    73. }
    74. if (vspeed < 0)
    75. {
    76. sprite_index=spr_chu_verf3
    77. image_speed=1;
    78. }}
    79. if (point_direction(x,y,obj_pospos.x,obj_pospos.y)>=270) && (point_direction(x,y,obj_pospos.x,obj_pospos.y)<360)
    80. {
    81. x+=1
    82. if (hspeed > 0)
    83. {
    84. sprite_index=spr_chu_verf1
    85. image_speed=1;
    86. }
    87. if (hspeed < 0)
    88. {
    89. sprite_index=spr_chu_verf2
    90. image_speed=1;
    91. }
    92. if (vspeed > 0)
    93. {
    94. sprite_index=spr_chu_verf4
    95. image_speed=1;
    96. }
    97. if (vspeed < 0)
    98. {
    99. sprite_index=spr_chu_verf3
    100. image_speed=1;
    101. }}
    Alles anzeigen
  • Mir faellt da jetzt spontan folgendes ein:
    Der GM speichert fuer jedes Objekt 2 Variablen xprevious und yprevious, die geben die vorherigen Koordinaten aus dem letzten Step an.
    Damit kannste jetzt pruefen wie sich die aktuellen Koordinaten zu den Vorherigen verhalten.
    Wenn z.B. der aktuelle x Wert kleiner bzw. groesser ist als xprevious dann hat sich das Objekt nach Links bzw. Rechts bewegt etc.

    Musste mal ausprobieren ob du das irgendwie verwenden kannst.
  • Der Aktuelle Code sieht jetzt so aus:

    GML-Quellcode

    1. tile_half = 64/2;
    2. mp_grid_path(global.Netz,Pfad,x+tile_half,y+tile_half,obj_pospos.x+tile_half,obj_pospos.y+tile_half,0);
    3. path_start(Pfad,2,0,0);
    4. px = path_get_point_x(Pfad,1)-tile_half;
    5. py = path_get_point_y(Pfad,1)-tile_half;
    6. x = px;
    7. y = py;
    8. if (y > yprevious)
    9. {
    10. sprite_index=spr_chu_verf4
    11. image_speed=1;
    12. }
    13. if (y < yprevious)
    14. {
    15. sprite_index=spr_chu_verf3
    16. image_speed=1;
    17. }
    18. if (x > xprevious)
    19. {
    20. sprite_index=spr_chu_verf1
    21. image_speed=1;
    22. }
    23. if (x < xprevious)
    24. {
    25. sprite_index=spr_chu_verf2
    26. image_speed=1;
    27. }
    Alles anzeigen


    Das Problem was ich noch habe: manchmal passt es 1A, manchmal nicht. k.A. warum. ;(
  • Benutzer online 1

    1 Besucher