Sokoban

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

    • Hallo zusammen!

      Das Spielprinzip Sokoban ist recht bekannt. Es gilt bei diesem Spielprinzip eine Figur aus der Sicht von oben Kisten auf vorgeschriebene Plätze schieben zu lassen. Die Schwierigkeit dieses Spielprinzips liegt darin, dass die Spielfigur lediglich die Kisten schieben und nicht ziehen kann und auch nur eine auf einmal bewegen darf.

      In diesem Tutorial werde ich erklären wie man die grundlegende Spiellogik entwickelt. Die fertige Engine des Spieles kann auch am Ende der Anleitung heruntergeladen werden. Damit du alle Teile des Tutorials verstehst du solltest am besten GML-Anfänger sein, oder du liest dich bei Unklarheiten in die Hilfe ein.


      Wir beginnen damit alle notwendigen Sprites und Objects zu erstellen.

      spr_spieler
      spr_wand
      spr_block
      spr_ziel

      Das sind die Grafiken die ich für das Tutorial verwendet habe, für ein "richtiges" Spiel solltest du andere/bessere Bilder verwenden. Vergiss nicht bei spr_spieler und spr_ziel den Haken bei Transparent zu setzen damit der grüne Hintergrund nicht dargestellt wird.

      Jetzt erstellen wir für jede dieser Grafiken noch die entsprechenden Objekte namens obj_spieler, obj_wand, obj_block und obj_ziel und stellen für diese die entsprechenden Sprites ein, die wir oben erstellt haben.

      Als nächstes erstellen wir einen neuen Raum in den wir unser erstes Level bauen, das uns zunächst nur zu Testzwecken dienen soll. Später kannst du hier noch jede Menge Räume für weitere Level erstellen.
      Bevor wir jetzt die Objekte im Raum setzen, solltest du die Größe des Hilfsgitters auf eine Größe von 24x24 Pixel setzen, denn das entspricht genau der Größe unserer sprites und erleichtert uns somit das Entwerfen des Levels. In diesem Tutorial verwende ich folgendes Level:




      Jetzt kommen wir zu der eigentlichen Spiellogik, den Events der Objekte.

      obj_spieler erhält folgende Events:

      Create Event:

      Execute a piece of code

      GML-Quellcode

      1. move_speed = 2; // Geschwindigkeit des Spielers
      2. grid_size = 24; // Größe der Kästchen

      Wenn du willst, dass deine Spielfigur schneller läuft erhöhe die Variable move_speed.
      Für eine andere Laufweite, also bei einer anderen Größe der Grafiken als 24x24 Pixel, solltest du die Variable grid_size entsprechend ändern.

      Alarm 0 Event:

      Dieses Event dient der "Laufanimation", also der Bewegung der Figur von einem Kästchen in ein Benachbartes. In unserem Beispiel eine Bewegung um 24 Pixel.

      Execute a piece of code

      GML-Quellcode

      1. if (!mp_linear_step(aim_x,aim_y,move_speed,false))
      2. alarm[0] = 1;
      3. else
      4. alarm[0] = -1;

      Mit der Funktion mp_linear_step wird die Figur einen Schritt in Richtung der neuen Position bewegt. Diese Zielpostion ist in den Variablen aim_x und aim_y gespeichert. Zu diesen Variablen werden wir später noch kommen. Das dritte Argument der Funktion verlangt die Bewegungsgeschwindigkeit welche wir schon weiter oben mit move_speed definiert haben. Die Funktion mp_linear_step gibt nun zurück ob das Objekt jetzt an dem Zielpunkt angekommen ist oder nicht. Ist dies der Fall wird die "Laufanimation" beendet, anderen Falls wird sie wiederholt.


      Die folgenden 4 Events sind für die Steuerung der Spielfigur zuständig. Dabei wird jeweils ein Script namens scr_bewegen aufgerufen, welches die Figur unter Berücksichtigung aller Spielregeln in die entsprechende Richtung bewegt welche durch zwei Argumente angegeben wird. Das erste Argument legt die Bewegung in x-Richtung fest, -1 für links, 0 für keine Bewegung und 1 für rechts. Gleiches gilt für das zweite Argument in y-Richtung.

      Keyboard Left

      script: scr_bewegen; argument0: -1; argument1: 0;

      Keyboard Right

      script: scr_bewegen; argument0: 1; argument1: 0;

      Keyboard Up

      script: scr_bewegen; argument0: 0; argument1: -1;

      Keyboard Down

      script: scr_bewegen; argument0: 0; argument1: 1;


      Das waren auch schon alle Events von obj_spieler, weiter gehts mit dem Script scr_bewegen:

      GML-Quellcode

      1. var aim_xt, aim_yt;
      2. if (alarm[0] == -1) {
      3. aim_x = x+argument0*grid_size;
      4. aim_y = y+argument1*grid_size;
      5. if (!place_meeting(aim_x,aim_y,obj_wand)) {
      6. if (place_meeting(aim_x,aim_y,obj_block)) {
      7. aim_xt = aim_x+argument0*grid_size;
      8. aim_yt = aim_y+argument1*grid_size;
      9. if (!place_meeting(aim_xt,aim_yt,obj_wand) and !place_meeting(aim_xt,aim_yt,obj_block)) {
      10. with (obj_block) {
      11. if (x == other.aim_x and y == other.aim_y) {
      12. aim_x = aim_xt;
      13. aim_y = aim_yt;
      14. alarm[0] = 1;
      15. }
      16. }
      17. alarm[0] = 1;
      18. }
      19. }
      20. else
      21. alarm[0] = 1;
      22. }
      23. }
      Alles anzeigen

      Die erste Überprüfung if (alarm[0] == -1) sorgt dafür, dass man nur die Richtung ändern kann, wenn man sich genau auf einem Kästchen befindet, sodass man sich nur in einem Gitter mit 24x24 Pixel großen Zellen bewegen kann. Denn wie bereits erwähnt sorgt das Alarm0-Event von obj_spieler für die Laufanimation. Deshalb lässt sich mit der Variable alarm[0] die Überprüfung durchführen.

      Im nächsten Schritt werden die Zielkoordinaten aim_x und aim_y gesetzt, welche uns schon vom Alarm0-Event weiter oben bekannt sind. Dabei handelt es sich je nach übergebenen Argumenten um eines der 4 benachbarten Felder.

      Die nächste Abfrage lässt eine Bewegung nur zu, wenn sich auf dem Zielfeld kein Wand-Objekt befindet. Ist dies der Fall gibt es 2 Möglichkeiten. entweder ist das Zielfeld frei und die Figur kann sich problemlos dort hin bewegen, oder dort steht ein Block-Objekt welches sich nur verschieben lässt wenn sich dahinter (von der Figur aus betrachtet) keine Wand oder ein weiterer Block befindet. Wenn der Block verschoben werden darf wird mit der with-Anweisung der entsprechende Block ausfindig gemacht der verschoben werden muss und dessen Alarm0-Event gestartet wodurch der Block genauso wie die Figur in die Laufrichtung bewegt wird. Das Verschieben des Blockes funktioniert genauso wie bei der Figur.

      obj_block bekommt folgendes Event:

      Alarm 0 Event

      GML-Quellcode

      1. if (!mp_linear_step(aim_x,aim_y,obj_spieler.move_speed,false))
      2. alarm[0] = 1;
      3. else
      4. if (scr_geschafft()) {
      5. screen_redraw();
      6. show_message("Geschafft!");
      7. }


      Wie schon oben erwähnt wird dieses Event von scr_bewegen aufgerufen, sobald ein Block geschoben wird. Genauso wie bei dem Alarm0-Event von obj_spieler wird der Block zum Zielpunkt verschoben. Sobald der Block dort angekommen ist, wird mit dem Script scr_geschafft überprüft ob sich nun alle Blöcke auf einem Zielfeld befinden. sollte das der Fall sein wird eine entsprechende Meldung ausgegeben.

      Zum Schluss wird noch das Script scr_geschafft mit folgendem Inhalt erstellt:

      GML-Quellcode

      1. var check;
      2. check = true;
      3. with (obj_block) {
      4. if (!place_meeting(x,y,obj_ziel))
      5. check = false;
      6. }
      7. return check;

      Es werden alle Blöcke durchgegangen und jeweils überprüft ob sie auf einem Zielfeld steht, anderenfalls wird check auf false gesetzt. Diese Variable wird am Ende zurück gegeben.

      Das wars auch schon! Jetzt kannst du das Spiel starten und probieren die Blöcke auf die Zielfelder zu verschieben. Wenn alles problemlos klappt hast du alles richtig gemacht. Dann ist es jetzt an der Zeit ein richtiges Spiel daraus zu machen. Füge bessere Grafiken ein, ein Menü, Musik, Sounds usw.

      Viel Spaß damit!

      MFG BlackSpark
      Dateien
      • sokoban_tut.rar

        (2,65 kB, 493 mal heruntergeladen, zuletzt: )

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Bl@ckSp@rk ()

    • Ja, natürlich. Einfach das

      GML-Quellcode

      1. show_message("Geschafft!");

      durch ein

      GML-Quellcode

      1. room_goto_next();

      oder ähnliches ersetzen. Ich bitte dich aber dir das nächste mal den code genauer anzuschauen und zu verstehen und wenn nötig in der Hilfe nach Befehlen zu suchen, denn dann hättest du das bestimmt selber herausgefunden. ;)