PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [VX Ace] Ruby - Einsteigerfragen



Fuxfell
24.09.2012, 13:37
Hi!
Ich versuche gerade vom "Event-Makern" auf den RPG Maker VX Ace (und da eben Ruby) umzusteigen und hab da ein paar Fragen, hoffe ihr könnt mir helfen :)

(Vorkentnisse: Mit Ruby direkt wenig, aber ich hatte ein Semster Java-Programmierung (und auch eins in C zum Programmieren von Mikrocontrollern) und kenn mich schon bisschen mit Objekt-Orientierter-Programmierung aus. (Ist Ruby ja auch :)
Außerdem hab ich mir schon ein paar Videotutorials von GubiD (http://www.youtube.com/user/gubid/videos?view=0) zum RPG Maker VX Ace angesehen.)

1) Notetag Reader
Ich versuche gerade jedem Actor (evtl. auch Gegner fürs eigene KS) ein Bild (so nen Bustshot) zuzuweisen. Dazu möchte ich dann z.B. den Notetag <battlepic: "Battler - 1"> einem Actor geben und dann soll mein Script die Notizen durchlaufen und dann den String "Battler - 1" zurück geben, der der Dateiname des Pictures ist.
Ein Tutorial zu Notetags hab ich auch gefunden und zwar das von Formar0153 (http://cobbtocs.co.uk/wp/?p=312).
Das funktioniert so aber leider nicht (nach meinem Verständnis modifiziert) (Alles noch ohne Strings und mit Integers zum "Debuggen", damit ich sehen kann, ob die Notetag gefunden wrid):

class RPG::BaseItem
def battlepic
if @battlepic.nil?
if @note =~ /<battlepick (.*)>/i
@battlepic = $1.to_i
else
@battlepic = 0
end
end
@battlepic
end
end

Wenn ich nun folgenden Code ausführen (Aufruf beim zeichnen eines Menüs) möchte:


draw_text_ex(x, y, @actor.battlepic)

Bekomme ich die Fehlermeldung "undefiend method for Game_Actor". Wenn ich nun das "class RPG::BaseItem" durch ein "class Game_Actor < Game_Battler" ersetze
findet er zwar die methode (logisch) aber @note ist immer nil.

class Game_Actor < Game_Battler
def battlepic
if @battlepic.nil?
if @note =~ /<battlepick (.*)>/i
@battlepic = $1.to_i
else
@battlepic = 0
end
end
@battlepic
end
end
Ich bezweifle langsam, dass diese Aussage von Formar0153 so richtig ist:

In all the classes with notes the note is stored in a variable called @note. Oder verstehe ich das einfach nicht richtig? Was ist denn der Unterschied zwischen z.B.: RPG::Actor und Game_Actor? In welcher Beziehung stehen die beiden zueinander? Und warum ist die Klasse RPG::Actor im Skripteditor nicht zu finden?

YanFly regelt das mit den Notetags ja über Regexp (http://www.ruby-doc.org/core-1.9.3/Regexp.html) nur werde ich daraus leider kein bisschen schlau :(
(Weder aus der Seite noch aus YanFlys Skripts, in denen er scheinbar einen DataManager dafür zusammenbaut.)

2) Sonstiges:
- Wie kann man die Konsole für den RPG Maker VX Ace öffnen? Damit ich z.b. einen print-Befehl sehen kann. (zum Debuggen)
- Kann man aus dem Skript heraus Ingamevariablen manipulieren, wenn ja wie?

Würde mich über jede Hilfe freuen! (Auch der Hinweis auf gute Tutorials ist erwünscht :P )

-KD-
24.09.2012, 23:48
Dein Code ist schon weitgehend richtig. Nur der Regexp sollte besser folgendermaßen lauten: /<battlepic ([^>]+)>/i
Die Konvertierung von String zu Integer würde ich lieber über die Integer() Methode lösen. Also Integer($1.strip) statt $1.to_i. Der Unterschied ist, dass Integer() eine Exception wirft, wenn das Argument keine Zahl ist. to_i gibt dann einfach 0 zurück.


draw_text_ex(x, y, @actor.battlepic)
Die richtige Schreibweise wäre

draw_text_ex(x, y, @actor.actor.battlepic)

Denn @actor ist eine Instanz von Game_Actor, die @note Variable steht aber in RPG::Actor drinne (bzw. in deren Superklasse RPG::BaseItem). Die Methode Game_Actor#actor gibt dir das entsprechende RPG::Actor Objekt.


Was ist denn der Unterschied zwischen z.B.: RPG::Actor und Game_Actor? In welcher Beziehung stehen die beiden zueinander? Und warum ist die Klasse RPG:ctor im Skripteditor nicht zu finden?
RPG::Actor ist eine Eingabedatenstruktur, die du über den RPG-Maker erstellst. Diese RPG-Klassen sind reine Datenstrukturen, d.h. sie definieren nur Methoden um auf ihre Variablen zuzugreifen, nicht mehr. Sie sollten am besten wie Konstanten gehandhabt werden, also ihre Variablen sollten im Spiel nie geändert werden. Diese RPG-Daten werden nicht in die Spielstände geschrieben, sondern werden pro Projekt global vom Maker verwaltet. D.h. wenn du eine Map im Maker änderst, ändert sich diese Map auch in allen laufenden Spielständen. Dem gegenüber stehen die Game-Klassen (die im Scripteditor stehen). Diese Klassen beinhalten die eigentliche Spiellogik und die sich verändernden Zustände. Mal ein Beispiel: Du kannst den Namen eines Helden im Maker ändern. Du kannst ihn aber auch im Spiel über den Event-Befehl NameInputProcessing ändern. Tatsächlich sind beide Namen komplett unabhängig voneinander. Der eine Name steht in den RPG-Daten und wird vom Maker verwaltet, der andere Name wird vom Game-Objekt verwaltet und kann innerhalb des Spiels geändert werden. Entsprechend gibt es viele Variablen in Game_Actor und RPG::Actor doppelt. Einmal in veränderlicher Form und am Spielstand gebunden, einmal in unveränderlicher Form und vom Maker verwaltet. Wann immer du also Variablen hast, die du im Laufe des Spiels ändern willst, solltest du diese in die Game-Klassen schreiben.


YanFly regelt das mit den Notetags ja über Regexp nur werde ich daraus leider kein bisschen schlau
Die Frage kam schonmal auf, darum zitiere ich mich einfach mal selbst:

Mal 'nen ganz kurzer Überblick über Regexps:

Ein regulärer Ausdruck (so wie er in Ruby ist, der mathematische Hintergrund ist ja nochmal was ganz anderes) ist ein Muster für Strings. Eine Art Schablone, in die mehrere Strings reinpassen. Er baut sich aus folgenden Elementen zusammen:
- Terminale: Du kannst in einen Regexp ganz normale Zeichen reinsetzen, solange sie nicht schon für was anderes reserviert sind (in diesem Fall kannst du sie escapen, in dem du ein \ davorsetzt). zB. passt der Regexp /Hallo Welt/ genau auf den String "Hallo Welt". Der Regexp /Hallo\/Welt/ passt auf den String "Hallo/Welt". Das / muss hier escaped werden, weil es ja eigentlich das Trennzeichen für Regexps darstellt

- Gruppierung: Mit Klammern kannst du innerhalb eines regulären Ausdrucks einen Unterausdruck gruppieren. Auf diese Weise wirkt er im Grunde genommen wie ein Terminal. Bsp: /Hallo (Welt)/. Hier wurde Welt gruppiert. Wozu das genau dient, später.

- Wiederholungen: Mit {a, b} kannst du sagen, dass der letzte Ausdruck (Terminal oder Gruppierung) um mindestens a mal und maximal b mal wiederholt werden muss. /Hallo (Welt){2, 4}/ passt also auf die Strings "Hallo WeltWelt", "Hallo WeltWeltWelt" und "Hallo WeltWeltWeltWelt". Lässt du a weg, so wird für a automatisch 0 eingesetzt. Lässt du b weg, so wird automatisch unendlich dazu eingesetzt. /Hallo{,2}/ passt also zu "Hall", "Hallo", "Halloo".

- Alternation: Mit Alternation kannst du sagen, dass entweder der eine, oder der andere Ausdruck vorkommen muss. Man setzt Alternation mit |. Alternation beziehen sich nicht nur auf ein Terminal. Deswegen musst du sie selbst gruppieren.
/Hallo (Welt|Wald)/ passt auf "Hallo Welt" und "Hallo Wald"

- Zeichengruppen: Eine Gruppe ist nur eine Form der Alternation einzelner Terminale. Du kannst statt (a|b|c|d|e) auch eine Gruppe [abcde] schreiben. Beides ist äquivalent. Gruppen kennen zudem noch den Bindestrich Operator, mit dem du hintereinanderkommende Zeichen mit einbeziehen kannst: /[e-h]/ passt auf die Strings "e", "f", "g", "h". /[A-z]/ passt auf jeden Buchstaben. Weiterhin kannst du am Anfang einer Gruppe das ^ Zeichen setzen. Dann wird das Komplement der Gruppe gebildet. [^0-9] passt also auf alles, nur nicht auf "0", "1", "2", ..., "9".

- Weiterhin gibt es noch verschiedene vordefinierte Macros. + ist dasselbe wie {1,}. * ist dasselbe wie {0,}. ? ist dasselbe wie {0,1}.
/Hallo(Welt)?/ passt auf "Hallo" und "HalloWelt". /Hallo du+/ passt auf "Hallo du", "Hallo duu", "Hallo duuu", ...
\d ist dasselbe wie [0-9]. \D ist dasselbe wie [^0-9]. \s ist die Gruppe aller Leerzeichen (Neue Zeile, Tab, Leerzeichen usw.). \S ist wieder das Komplement davon. \w sind alle Buchstaben und Zahlen. \W ist das Komplement. Der einfache . Punkt ist die Gruppe ALLER Zeichen (außer Newline)

- Es gibt noch ein paar Optionen für Regexps. Die zwei wichtigsten:
i = case insensitiv. Wenn diese Option gesetzt ist, ist Groß- und Kleinschreibung egal. /a/ matcht dann also sowohl "A" als auch "a"
m = multiline-Mod. Wenn diese Option gesetzt ist zählt das Newline-Zeichen mit in die Gruppe von .
x = Hier zählen Leerzeichen und Kommentare (fangen mit # an) nicht als Terminale. Auf diese Weise kannst du deinen Regexp über mehrere Zeilen spannen und hübscher aufschreiben. Echte Leerzeichen musst du dann mit dem Escapezeichen "\ " kennzeichen
Optionen setzt man ans Ende des Regexps-Literals.
/Hallo ./cm =~ "hallo \n wie geht es dir?" #=> 0
/(\d+) # hier kommen Zahlen
\ Jahre \ alt # dieser Text soll danach kommen/x =~ "Ich bin 7 Jahre alt" #=> 8

Die vollständige Liste findest du in der Helpdatei des Makers.

- Dann gibt es noch einige weitere Kniffe (Anker, Greedy, usw.). Darauf will ich erstmal nicht eingehen. Auch hier: Guck in die Helpdatei.

- Jede Gruppierung bekommt, nach ihrem Auftreten, eine Nummer. /(Hallo (wie)) (gehts)/ hier gibt es drei Gruppen. (Hallo wie) ist Gruppe 1. (wie) ist Gruppe 2. (gehts) ist Gruppe 3. Wenn du einen Regexp auf einen String anwendest, wird versucht den String in die Regexp-Schablone reinzustecken. Dabei wird der Inhalt der Gruppen in den globalen Variablen $1, $2, $3, ... abgespeichert.
/Ich bin (\d+) Jahre alt/ =~ "Ich bin 20 Jahre alt"
p $1 #=> "20"
/Um (\d\d):(\d\d) Uhr/ =~ "Um 17:30 Uhr"
p $1 #=> "17"
p $2 #=> 30


- Wie kann man die Konsole für den RPG Maker VX Ace öffnen? Damit ich z.b. einen print-Befehl sehen kann. (zum Debuggen)
Im Maker in der Menüleiste und dort auf "Game". Da kannst du dann "Show Console" auswählen. Sie wird aber nur angezeigt wenn du das Spiel über den Maker startest. Einen richtigen Debugger hat der Maker leider nicht eingebaut.


- Kann man aus dem Skript heraus Ingamevariablen manipulieren, wenn ja wie?

$game_variables[ID] = 5 # setzen
puts $game_variables[ID] # wert ausgeben


(Auch der Hinweis auf gute Tutorials ist erwünscht :P )
Ist leider nur für den XP: http://www.rpg-studio.de/scientia/RGSS/Tutorials/Rubykurs_1_-_Grundlagen
Prinzipiell hat sich im VXAce nicht viel geändert, aber manche Sachen sind eben leider doch etwas anders. z.B. heißt RPG::Cache im VXAce einfach nur Cache. Kann also sein, dass manche Codebeispiele nicht funktionieren.

Fuxfell
25.09.2012, 10:23
Wow -KD-!
Vielen Dank für die ausführliche und äußerst hilfreiche Antwort! :) (Jetzt funktionierts auch wie gewünscht :D)
Vorallem die Erklärung zu den Datenstrukturen hat mich weitergebracht. Nach meinem Verständnis wäre es dann jetzt auch nicht sinnvoll einen Notetag Ingame dann zu überschreiben (falls dies überhaupt möglich ist (ich wills ja garnicht machen :D)), weil dann das entsprechende Bild des Actors auch in allen Savestates geändert werden würde?!
(wenn man sowas flexibles haben will, dann sollte man das quasi über ein neues Attribut in der Game_Actor Klasse regeln, oder? Müsste ich mich jetzt aber erstmal genauer einlesen.)
Den Artikel über Regexp hab ich mir gleich mal gespeichert, den werd ich später sichernochmal brauchen und der ist wenigstens verständlich geschrieben ;P
Über dein Tutorial bin ich bei meiner eigen Recherche schonmal gestoplert, aber ich hab irgendwo mal aufgeschnappt, dass im RPG Maker VX Ace vieles anderes gehandhabt wird (z.B. dass vielmehr Gebrauch von Handlern gemacht wird?) und da dachte ich, dass es wenig sinnvoll ist sich mit dem RPG Maker XP auseinander zu setzen, weil sowieso alles anders gemacht wird :D Leider gibts für den Ace noch nicht viele Tutorials, deswegen werd ich wohl doch deins als Referenz erstmal hernehmen :)

-KD-
25.09.2012, 19:43
Nach meinem Verständnis wäre es dann jetzt auch nicht sinnvoll einen Notetag Ingame dann zu überschreiben (falls dies überhaupt möglich ist (ich wills ja garnicht machen )), weil dann das entsprechende Bild des Actors auch in allen Savestates geändert werden würde?!
(wenn man sowas flexibles haben will, dann sollte man das quasi über ein neues Attribut in der Game_Actor Klasse regeln, oder?Genau.


Über dein Tutorial bin ich bei meiner eigen Recherche schonmal gestoplert, aber ich hab irgendwo mal aufgeschnappt, dass im RPG Maker VX Ace vieles anderes gehandhabt wird (z.B. dass vielmehr Gebrauch von Handlern gemacht wird?)Hm, eigentlich nicht. Es gibt drei Unterschiede:
- Beide Maker haben natürlich unterschiedliche Standardskripte. Deshalb sind Scripte für den einen Maker normalerweise zu einem anderen Maker inkompatibel. Da mein Tutorial sich aber eh kaum bei den Standardskripten aufhält, ist das nicht so tragisch. Du müsstest nur Einzelheiten (z.B. die Scene Klasse) im Tutorial anpassen.
- Beide Maker haben eine unterschiedliche RGSS-Version. Die gute Sache dabei: In der Regel kommen nur neue Features dazu. Es gibt nur sehr wenige Sachen, die in RGSS 1 (XP) anders gehandhabt werden als in der RGSS3 (VXAce). Da wäre zum einen die Mapdarstellung, aber die kommt in meinem Tutorial eh nicht vor. Zum anderen noch dass man Cache statt RPG::Cache schreibt und einige weitere Kleinigkeiten. Wenn was nicht funktioniert kannst du ja einfach Fragen.
- Beide Maker nutzen unterschiedliche Rubyversionen. RGSS1 nutzt Ruby 1.81, RGSS3 nutzt Ruby 1.92 (oder 1.93? k.a.). Auch hier wieder: Hauptsächlich sind bei Ruby 1.93 neue Features und neue Syntax hinzugekommen. Es wurde nur wenig entfernt oder geändert. Hauptsächlich fällt mir da nur die String-Klasse ein, die in beiden Rubyversionen völlig unterschiedlich funktioniert - aber das fällt dem Programmierer im Maker in der Regel gar nicht auf. Für den Maker relevant ist vielleicht die Fiber-Klasse, die in Ruby 1.9 dazugekommen ist und die in den Standardskripten intensiv verwendet wird. Aber wie gesagt: Das Tutorial beschäftigt sich eh kaum mit den Standardskripten, sondern hauptsächlich mit den Grundfunktionen der RGSS. Und die sind in RGSS1 und RGSS3 weitgehend gleich.