PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Kistenverschiebung blockieren wenn keine Bewegung möglich ist?



dasBAUM
25.12.2006, 19:52
Servus,
ich bin derzeit dabei bewegbare Kisten in einem Dungeon zu erstellen. Hat bisjetzt auch soweit funktioniert, allerdings hab ich ein Problem.

http://img166.imageshack.us/img166/5874/unbenanntpy0.png

Die grauen Kisten (Kiste B) lassen sich bewegen, die roten nicht (Kiste A). Wenn ich eine graue Kiste bewege, spielt sich folgendes ab.

---

Event: Kiste_Grau_4
Event Start Condition: On Hero Touch

<> Play SE: Oot_Epona_Scrape.wav
<> Move Event... : This Event, Escape from Hero
<> Wait: 0.4.s.

---

Allerdings wird das Event auch abgerufen, wenn die graue Kiste sich nicht bewegen lässt (wenn sie z.B. an einer Wand oder einer roten Kiste steht).
Gibt es eine Möglichkeit, das Event bei einer nicht-möglichen Bewegung zu stoppen?

Ich möchte Switches vermeiden, da die Kiste bei Wiederkehr auf die Map wieder auf der Startposition stehen soll und wieder bewegbar sein soll.

Gruß

Phönix Tear
25.12.2006, 20:33
Bei den Move Events sollte es unter der Anzeige wo deine eingegebene Bewegung steht ein Feld sein bei dem man "Ignore if can't be moved" mit einem Haken versehen kann. Den hinmachen und fertig ;)
Außerdem solltest du besser nicht auf "On Hero Touch", sondern "On Touch Hero / Event" einstellen und den Block (es sind keine Kisten -.-) auf "Same Level as Hero" einstellen. Das wirkt viel besser ;)

mfg
Phönix Tear

Edit:
Ich editiere hier gleich noch einen vernünftigen Zeldamäßigen Steinschiebecode rein...

Edit 2:
So, da es ja allem Anschein nach bei deinem Projekt um ein Zelda Fanfic geht, möchte ich bei der Gelegenheit gleich einen vernünftigen Schiebecode beifügen. Wie du sicherlich gemerkt hast dauert es bei Zelda immer einen kurzen Moment den man gegen die Steine gegen laufen muss, bevor sie verschoben werden. Dies kann man im Maker natürlich auch umsetzen. Ich weiß nicht genau ob es an meiner Funktastatur liegt, aber manchmal gibt es mit diesem Code kurzzeitig Probleme, aber egal. Probier es am besten einfach selber aus.

Was braucht man für diesen Code? 3 Variablen und 2 Label (ich kann nicht sagen ob dies der einfachste Code ist, aber er funktioniert immerhin ;) ).

Legen wir gleich los. Du brauchst auch nur das Steinevent, welches selbstverständlich kopierbar ist (ich nenne es im Folgenden auch weiterhin nicht mehr Block, sondern Stein, da ich es einfacher finde und es ebenfalls passt (aber "Kiste", nya :P )).

Steinevent | Same Level As Hero | Keine Startbedingung | On Touch Event / Hero

<>Change Variable "Steinzähler", set 0
<>
<>Fork Hero Face Dir. 'Up'
<><>Change Variable "Held Facerichtung", set 4
<>Else:
<>Fork Hero Face Dir. 'Right'
<><>Change Variable "Held Facerichtung", set 3
<>Else:
<>Fork Hero Face Dir. 'Down'
<><>Change Variable "Held Facerichtung", set 1
<>Else:
<>Fork Hero Face Dir. 'Left'
<><>Change Variable "Held Facerichtung", set 2
<>End:
<>
<>Change Hero Walk GFX -> "Link in Schiebepose"
<>
<>!Lable 1!
<>
<>Enter Password "Steinpasswort" [(1,2,3,4) | Do not wait until Key hit]
<>
<>Fork Variable "Steinpasswort" = "Held Facerichtung"
<><>Change Variable "Steinzähler" + 1
<>Else:
<><>Change Variable "Steinzähler", set 0
<><>Goto !Lable 2!
<>End:
<>
<>Wait 0,0 secs
<>
<>Fork Variable "Steinzähler" > 30
<><>Move Event 'This Event' [Play SFX "Steinschiebsound" ; Step away from Hero]
<>Else:
<><>Goto !Lable 1!
<>End:
<>
<>!Lable 2!
<>
<>Change Hero Walk GFX -> "Link in normaler Pose"
<>
Die einzelnen Codeabschnitte sind jeweils durch eine freie Zeile voneinander abgetrennt.
So, jetzt aber: Was zur Hölle macht der Code???
Dazu werde ich ihn wieder auseinander nehmen.
Sinn abschnitt 1:

<>Change Variable "Steinzähler", set 0
<>
Die Variable "Steinzähler" (ich weiß, der Name mag etwas ungenau sein :rolleyes: ) soll die Zeit zählen, in der der Spieler gegen den stein "drückt". Dies macht der folgende Code. Damit man den Stein aber kopieren kann muss diese Variable am Anfang immer auf 0 gesetzt werden, da man sonst Schiebezeit "horten" könnte (man könnte somit bei Stein 1 anfangen zu drücken (eine halbe Sekunde) und würde dann Stein 2 auch nur noch eine halbe Sekunde drücken müssen, selbst wenn die eigentliche "Drückzeit" eine ganze Sekunde wäre...). Nun aber zum

Sinn abschnitt 2:

<>Fork Hero Face Dir. 'Up'
<><>Change Variable "Held Facerichtung", set 4
<>Else:
<>Fork Hero Face Dir. 'Right'
<><>Change Variable "Held Facerichtung", set 3
<>Else:
<>Fork Hero Face Dir. 'Down'
<><>Change Variable "Held Facerichtung", set 1
<>Else:
<>Fork Hero Face Dir. 'Left'
<><>Change Variable "Held Facerichtung", set 2
<>End:
<>
Wenn du mal mit "Enter Password" gearbeitet hast, dürfte dies nichts neues für dich sein. Aber ich erkläre es zur Sicherheit einfach mal ^^:
Der "Enter Password"-Befehl speichert, ob der Spieler eine von 6 Tasten gedrückt hat (die 4 Pfeiltasten + Leertaste / Enter + Escape). Diese werden als Zahlen in eine vom Makerer angebbare Variable eingespeichert. Dies geschieht in folgender Form:

Pfeil unten -> 1
Pfeil links -> 2
Pfeil rechts -> 3
Pfeil oben -> 4
Enter -> 5
Escape -> 6
Da ich im folgenden Code einen solchen "Enter Password"-Befehl verwende, mit dem ich abfragen will in welche Richtung der Spieler drückt, liegt es nahe bei der Vergabe der Zahlen für die Face-Richtung (Blickrichtung) des Helden eine gleiche Formatierung (falls man das hier so sagen darf ^^°) zu wählen. Dazu aber im nächsten

Sinn abschnitt 3:

<>!Lable 1!
<>
<>Enter Password "Steinpasswort" [(1,2,3,4) | Do not wait until Key hit]
<>
<>Fork Variable "Steinpasswort" = "Held Facerichtung"
<><>Change Variable "Steinzähler" + 1
<>Else:
<><>Change Variable "Steinzähler", set 0
<><>Goto !Lable 2!
<>End:
<>
<>Wait 0,0 secs
<>
<>Fork Variable "Steinzähler" > 30
<><>Move Event 'This Event' [Play SFX "Steinschiebsound" ; Step away from Hero]
<>Else:
<><>Goto !Lable 1!
<>End:
<>
<>!Lable 2!
<>
<>Change Hero Walk GFX -> "Link in normaler Pose"
<>
Erinnern wir uns erst nochmal was wir bis jetzt, außerhalb der Lable Schleife gamcht haben:
Wir haben die "Steinzähler" Variable auf 0 gesetzt und wir haben die Blickrichtung des Helden mittels Fork-Conditions abgefragt und als Zahlen von 1 bis 4 in die Variable "Held Facerichung" eingespeichert.
Nun wird diese Variable gebraucht. Dazu sollte ich aber erst nochmal genauer erläutern was wir eigentlich machen wollen:
Das Ziel ist es ja, ein Event zu schaffen, welches selbstständig überprüft ob der Held gegen es drückt und wenn ja soll es eine gewisse Zeit lang gegen sich drücken lassen und dann nachgeben und verschoben werden. Von welcher Richtung aus der Held gegen das Event drückt haben wir bereits oberhalb der Schleife festgestellt und eingespeichert. Jetzt müssen wir nur noch überprüfen ob der Spieler dies auch weiter tut / tun will.
Dazu haben wir mit einem Lable eine Schleife gebastelt. Am Anfang der Schleife steht ein "Enter Password"-Befehl der die Pfeiltasten kontrolliert. Sollte der Spieler nun also weiterhin gegen den Stein drücken muss die Pfeiltaste die er drückt mit der Blickrichtung des Helden übereinstimmen, da er ja im Grunde genommen in die gleiche Richtung "weiterlaufen" will. Die Blickrichtung des Helden haben wir bereits, den Pfeiltaste welche gedrückt wird fragen wir gerade ab. Damit wir dies einfacher vergleichen können habe ich wie oben erwähnt die Blickrichtung genau so als Zahlen gespeichert wie der "Enter Password"-Befehl es mit den Pfeiltasten auch macht. Nochmal zur Erinnerung:

Enter Passwort:
Unten -> 1
Links -> 2
Rechts -> 3
Oben -> 4

Wir haben gespeichert:
Unten -> 1
Links -> 2
Rechts -> 3
Oben -> 4
Beide Speicherungen gleichen sich. Von daher muss ich also nur noch überprüfen ob beide Variablen gleich sind, also der Spieler in die selbe Richtung drückt in die der Held schaute als er gegen den Stein lief.
Das macht die Fork Condition im Code.
Sollte dies der Fall sein wird die "Steinzähler" Variable (genauer: Der Wert der "Steinzähler" Variable) um 1 erhöht. Sollte diesem nicht so sein wird die "Steinzähler" Variable auf 0 zurück gesetzt (könnte man sich evtl auch sparen, ich mach es zur Sicherheit trotzdem immer) und zum Lable 2 gesprungen, welcher das Ende des Events darstellt. Dadurch entkommen wir auch der Schleife.
Ist die obere Fork Condition überwunden und die Bedingung erfüllt (sonst wird ja zum Lable 2 gesprungen) wartet der Maker 0,0 Sekunden (6x 0,0 Sekunden = 0,1 Sekunde) und springt dann zum Lable 1, also zum Anfang der Schleife, um erneut zu prüfen ob der Spieler immer noch in die selbe Richtung drückt.
Damit dies aber nicht ewig so weitergeht muss der "Goto Lable"-Befehl in eine weitere Fork eingepackt werden, welche den Stand der "Steinzähler" Variable kontrolliert. Hier kannst du einen beliebigen Wert wählen, je nachdem wie lange man drücken soll bis sich der Stein verschiebt. 30 erschien mir dabei sehr passend...
Sollte die "Steinzähler" Variable noch kleiner als 30 sein wird, wie oben gesagt, zum Lable 1 gesprungen und weiter gewartet, bzw. kontrolliert.
Ist aber 30 erreicht kommt es zu einem "Move Event". In diesem "Move Event" spielt der Stein einen Verschiebesound (z.B. "Earth 4") und verschiebt sich selbst. Dabei muss natürlich "Ignore if can't be moved" aktiviert sein.
Damit bist du auch schon fast fertig. Nun wird der Lable 2 erreicht.
Da wir am Anfang die Heldengraphik geändert haben, müssen wir dies zum Ende des Codes natürlich wieder rückgängig machen. Also ändern wir die Heldengraphik entsprechend und haben erfolgreich ein Event erstellt welches sich nach einer halben Sekunde drücken um ein Feld vom Held weg verschiebt ;).

Ich hoffe Code und Erläuterung sind einigermaßen verständlich und dein Zelda Game rückt dadurch einen Schritt näher an das Original.

mfg
Phönix Tear

dasBAUM
25.12.2006, 20:48
Dieses "Ignore if can't be moved" habe ich ja aktiviert, die Kiste bewegt sich ja auch nicht, wenn ich gegen sie laufe. Aber der Wait und der Sound werden trotzdem ausgeführt. Ziemlich nervig, wenn man ausversehen gegen den Block (:D) läuft.

CapSeb
25.12.2006, 21:20
Es sei zuerst gesagt, dass es Möglichkeiten gibt. Die sind aber meistens aufwendiger als effektiv.
Eine Möglichkeit das Wait zu umgehen wäre eine Überprüfung des Objektes vor und nach der Bewegung. Das Wait kommt nur bei einer Veränderung der Positon. Das geht aber wie gesagt erst nach der Bewegung weshalb der Ton nicht umgangen werden kann.
Dazu eine kompliziertere Methode. Hier auf der Atelier-Seite gibt es ein Script, dass Objekte einzeln erkennt, ohne dass man Switches per Hand erstellen muss. Es erstellt anhand der Objekt-ID Variablen und speichert die Position. Diese würden sich dann bei deinem Spiel per Loop überprüfen lassen. Wenn du soetwas auch für andere Sachen gebrauchen kannst, wäre ein Einbauen nicht verkehrt. Einfach mal das Script ansehen.
Anti-Switch-Script (http://ipx22052.ipxserver.de/rpg-maker/netzwerk/dueltower/atelier/Anti-Switch_Skript.exe)

Das Prinzip ohne das Script ist folgendes:
Du speicherst die x- und y-Koordinate eines Blockes in zwei Variablen. Dann überprüfst du, ob dieses Koordinate hinter dem zu verschiebenden Block liegt. Wenn ja darfs keinen Ton geben. Das ganze per Loop für jeden Block im Raum wiederholen lassen. Fertig!

@Phönix Tear unten drunter: Das Anti-Switch-Scipt ist so ziemliche das einzige Script, das mich bisher beeidrucken konnte. Sehr gut Arbeit! ^^

Phönix Tear
25.12.2006, 21:23
Achso. Gut. Dann musst du eben eine weitere Abfrage einbauen. Ich benutze dabei weiter den oben erläuterten Code.

Dabei brauche ich diesen Bereich:

<>Fork Variable "Steinzähler" > 30
<><>Move Event 'This Event' [Play SFX "Steinschiebsound" ; Step away from Hero]
<>Else:
<><>Goto !Lable 1!
<>End:
<>
So, damit wir verhindern das ein Sound gespielt wird, müssen wir erstmal herausfinden ob sich der Stein bewegt hat. Da haben wir als einzige Möglichkeit seine Koordinaten zu speichern. Dazu brauche ich 2 Variablen. Ich nenne sie "Stein X" und "Stein Y" (logisch, oder? ^^).
Also:

<>Change Variable "Stein X", set [(This Event) X-Coord.]
<>Change Variable "Stein Y", set [(This Event) Y-Coord.]
<>
Nun soll sich der Stein bewegen und geprüft werden, ob sich der Stein auch wirklich bewegt hat. Dazu brauchen wir zwei weitere Koordinatenvariablen. In unserem Fall eignen sich als Namen "Stein X 2" und "Stein Y 2" wohl am besten. Zwischen Bewegung und Einspeichern der Koordinaten sollten allerdings mindestens 0,0 Sekunden vergehen ;). Also:

<>Fork Variable "Steinzähler" > 30
<><>Change Variable "Stein X", set [(This Event) X-Coord.]
<><>Change Variable "Stein Y", set [(This Event) Y-Coord.]
<><>Move Event 'This Event' [Step away from Hero]
<><>Wait 0,0 secs
<><>Change Variable "Stein X 2", set [(This Event) X-Coord.]
<><>Change Variable "Stein Y 2", set [(This Event) Y-Coord.]
<>Else:
<><>Goto !Lable 1!
<>End:
<>
Nun zur Abfrage. Sollte sich der Stein bewegt haben sind entweder die beiden X- oder die Y-Koordinaten-Variablen unterschiedlich. Also müssen wir kontrollieren:

<>Fork Variable "Stein X" other than "Stein X 2"
<><>Play SFX "Verschiebesound"
<>Else:
<>Fork Variable "Stein Y" other than "Stein Y 2"
<><>Play SFX "Verschiebesound"
<>End:
<>
Zusammenhängend sieht dann der komplette Code so aus:

Steinevent | Same Level As Hero | Keine Startbedingung | On Touch Event / Hero

<>Change Variable "Steinzähler", set 0
<>
<>Fork Hero Face Dir. 'Up'
<><>Change Variable "Held Facerichtung", set 4
<>Else:
<>Fork Hero Face Dir. 'Right'
<><>Change Variable "Held Facerichtung", set 3
<>Else:
<>Fork Hero Face Dir. 'Down'
<><>Change Variable "Held Facerichtung", set 1
<>Else:
<>Fork Hero Face Dir. 'Left'
<><>Change Variable "Held Facerichtung", set 2
<>End:
<>
<>Change Hero Walk GFX -> "Link in Schiebepose"
<>
<>!Lable 1!
<>
<>Enter Password "Steinpasswort" [(1,2,3,4) | Do not wait until Key hit]
<>
<>Fork Variable "Steinpasswort" = "Held Facerichtung"
<><>Change Variable "Steinzähler" + 1
<>Else:
<><>Change Variable "Steinzähler", set 0
<><>Goto !Lable 2!
<>End:
<>
<>Wait 0,0 secs
<>
<>Fork Variable "Steinzähler" > 30
<><>Change Variable "Stein X", set [(This Event) X-Coord.]
<><>Change Variable "Stein Y", set [(This Event) Y-Coord.]
<><>
<><>Move Event 'This Event' [Step away from Hero]
<><>
<><>Wait 0,0 secs
<><>
<><>Change Variable "Stein X 2", set [(This Event) X-Coord.]
<><>Change Variable "Stein Y 2", set [(This Event) Y-Coord.]
<><>
<><>Fork Variable "Stein X" other than "Stein X 2"
<><><>Play SFX "Verschiebesound"
<><>Else:
<><>Fork Variable "Stein Y" other than "Stein Y 2"
<><><>Play SFX "Verschiebesound"
<><>End:
<>Else:
<><>Goto !Lable 1!
<>End:
<>
<>!Lable 2!
<>
<>Change Hero Walk GFX -> "Link in normaler Pose"
<>

Edit @CapSeb:
Woa, es hat sogar jemand meinen Skript entdeckt *freu* :)

Edit 2:
Danke ;)

dasBAUM
25.12.2006, 22:13
Okay, das scheint zu funktionieren. Vielen Danke =)