Tile Layer als Kollision verwenden?

  • GM 8

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

  • Tile Layer als Kollision verwenden?

    GM Studio Professional

    Tagchen allerseits =)

    Ich denke über eine alternative Methode für die Kollisionen in einem 2D Jump N Run nach. Bisher kenne ich es nur, dass man mit unsichtbaren Objekten die Kollisionselemente wie Boden, Decke, Wand etc. platziert. Bei großen Leveln kommen dann viele Objekte zusammen.

    Ich würd gern wissen ob man sich diese Methode sparen kann. Wenn ich mit meinem Tileset das Level gestalte habe ich ja mehrere Layer bzw. ich kann mehrere nutzen. Kann man alle gesetzten Tiles eines bestimmten Layers als Kollisionselement nehmen? Also überall wo Tiles in Layer 100030 platziert sind gibt es Kollision. Anhand der platzierten Grafiken sagen worauf der Spieler sich bewegen kann. So müsste man nur einen Code schreiben, der diese Funktion bestimmt und nicht tasuend Objekte für die Kollision platzieren.

    Geht das? Wäre das möglich? Würd mich riesig freuen wenn da jemand weiterhelfen kann.

    Besten Dank :)
  • Hey MegaManXL

    natürlich geht dies,... und ich verwende es auch sehr häufig.
    Allerdings funktioniert das nur mit Rechteckigen Formen,... weil das Tile keine Kollisionsmaske besitzt und deshalb immer den kompletten Tile (egal ob Transparent oder nicht) prüft,... umgehen kannst du dies nur indem du die Tiles kleiner machst und dann ne Pixelkante legst :P,...

    Die Funktion mit der man dies machen kann heißt

    GML-Quellcode

    1. tile_layer_find(depth,x,y)


    würde dir empfehlen einfach die Wand/Decke/Boden auf jeweils ne andere Depth zu legen und dann ne Fallunterscheidung durchzuführen,....

    Ob die Funktion allerdings schneller ist als das ganze mit Objekten zu machen, kann ich dir net garantieren,... aber rein vom Gefühl her müsste es gerade bei großen Räumen deutlich schneller gehen

    Ne andere Alternative wäre folgendes
    Du erstellst dir ein Script welches am Anfang alle Tiles der Map durchläuft und ne Collisionsmap erzeugt
    Spoiler anzeigen

    GML-Quellcode

    1. ///CreateCollisionMap
    2. var xx,yy,i,t,top,left,s;
    3. global.mapsize=floor(room_width/32)*floor(room_height/32);
    4. // Loop through the tile map, and find the tiles, then place them
    5. // in the "simple" collision map.
    6. for( yy=0;yy<room_height;yy+=32)
    7. {
    8. s="";
    9. for( xx=0;xx<room_width;xx+=32)
    10. {
    11. i = (xx/32)+((yy/32)*(room_width/32));
    12. global.map[i]=-1;
    13. t = tile_layer_find(10,xx,yy);
    14. if( t>=0 )
    15. {
    16. s = s+"1";
    17. left = tile_get_left(t);
    18. global.map[i]=left/32;
    19. }else
    20. s = s+"_";
    21. }
    22. show_debug_message(s);
    23. }
    Alles anzeigen


    Anschließend prüfst du bei jeder Bewegung ob du Collidierst

    STEP:
    Spoiler anzeigen

    GML-Quellcode

    1. /// Process the player (move+collision)
    2. var xx,yy,c1,c2;
    3. /// Do payer "jump"
    4. if( !jump )
    5. {
    6. if( keys[JUMP_KEY] ) {
    7. grav=-8;
    8. jump=true;
    9. }
    10. }
    11. // Apply gravity (and jumping)
    12. y = y+grav;
    13. grav+=0.4;
    14. if( grav>=10 ) grav=10;
    15. // If falling, check UNDER the player
    16. if( grav<0 )
    17. {
    18. if( dir=1){
    19. sprite_index = jump_right;
    20. }else{
    21. sprite_index = jump_left;
    22. }
    23. c2 = -1;
    24. c1 = GetCollision(x,y);
    25. if( (x&$1f)>0 ) {
    26. c2=GetCollision(x+32,y);
    27. }
    28. if( c1>=0 || c2>=0 )
    29. {
    30. grav=0;
    31. y = (y&$ffffffe0)+32;
    32. }
    33. }
    34. else{
    35. // Otherwise, check above player
    36. if( jump )
    37. {
    38. if( dir=1){
    39. sprite_index = fall_right;
    40. }else{
    41. sprite_index = fall_left;
    42. }
    43. }else{
    44. grav=0;
    45. jump=true;
    46. }
    47. c2 = -1;
    48. c1 = GetCollision(x,y+32);
    49. if( (x&$1f)>0 ) {
    50. c2=GetCollision(x+32,y+32);
    51. }
    52. if( c1>=0 || c2>=0 )
    53. {
    54. y = (y&$ffffffe0);
    55. jump=0;
    56. if( dir=1){
    57. sprite_index = walk_right;
    58. }else{
    59. sprite_index = walk_left;
    60. }
    61. }
    62. }
    63. // If moving left, check LEFT collision
    64. if( keys[LEFT_KEY] )
    65. {
    66. dir=-1;
    67. if(!jump){
    68. sprite_index = walk_left;
    69. }
    70. x=x-xspeed;
    71. c2=-1;
    72. c1 = GetCollision(x,y);
    73. if( (y&$1f)>0 ) c2=GetCollision(x,y+32);
    74. if( c1>=0 ) || ( c2>=0 )
    75. {
    76. x = (x&$ffffffe0)+32;
    77. }
    78. }else if(keys[RIGHT_KEY] )
    79. {
    80. // Otherwise, check collision to the right
    81. dir=1;
    82. if(!jump){
    83. sprite_index = walk_right;
    84. }
    85. x=x+xspeed;
    86. c2 = -1;
    87. c1 = GetCollision(x+32,y);
    88. if( (y&$1f)>0 ) c2=GetCollision(x+32,y+32);
    89. if( c1>=0 ) || ( c2>=0 )
    90. {
    91. x = (x&$ffffffe0);
    92. }
    93. } else {
    94. // If standing still, don't animate
    95. image_index =0;
    96. }
    Alles anzeigen


    Das Script welches die Aktuellen Koordinaten prüft

    Script GetCollision
    Spoiler anzeigen

    GML-Quellcode

    1. ///GetCollision
    2. // argument0 = X coordinate to get tile (in pixels, not tiles)
    3. // argument1 = Y coordinate to get tile (in pixels, not tiles)
    4. //
    5. if( argument0>=room_width ) return -1;
    6. if( argument1>=room_height ) return -1;
    7. if( argument0<0) return -1;
    8. if( argument1<0) return -1;
    9. var xx,yy;
    10. xx = floor(argument0/32) + (floor(argument1/32) * floor(room_width/32));
    11. if( global.mapsize<xx ) return -1;
    12. return global.map[ xx ];
    Alles anzeigen



    Ich habe dieses Beispiel mal in einem Game Maker Tutorial gefunden und dachte vielleicht hilft es dir ja weiter ^^

    Grüße Blayde

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Blayde ()

  • DAS ist wunderbar!

    In MegaMan ist jedes Tile 16x16 Pixel groß. Da bedeuten Wand, Boden, Decke alle das selbe -> Kollision. Und es gibt in diesem Fall nirgends Tiles, die halbtransparent sind und für den Kollisionslayer benutzt werden. Rein für das Design wo es nicht um Kollision geht in anderen Layern gibts natürlich auch teils transparente Tiles. Bei diesem Spiel bedeutet es also: Wenn da ein Tile platziert ist dann ist es immer 16x16 Pixel groß, quadratisch.

    Das bedeutet ich kann sogar unterschiedliche Kollisionslayer machen oder? In einem zweiten Layer würde ich dann Stacheln setzen, die MegaMan bei der Berührung sofort zerstören. Ein anderer Layer gilt dann für Leitern an den MegaMan hoch und runter klettern kann. Noch ein Layer für Wasser in die Gravitation und Bewegungsgeschwindigkeit anders sind usw ....

    Das beste wäre dann ich verwende für jedes Level die gleiche Layer-Struktur oder? Also Layer 100030 immer für die normale Kollision. Layer 100040 für Stacheln usw...

    Seh ich das so richtig? Ich finde diese Vorgehensweise wesentlich eleganter als zighundert Kollisionsblöcke zu setzen.
  • Atomicmaster schrieb:

    Und es sollte natürlich machbar sein verschiedene Kollisionslayer zu machen.


    Das ist perfekt! Dann brauch ich mir keine unnützen Gedanken mehr über Kollisionsobjekte zu machen. Mein Bauchgefühl sagt mir ohnehin, dass es mit der Layermethode besser läuft.