• Login

Dear visitor, welcome to RPG Studio - Make your World real. If this is your first visit here, please read the Help. It explains in detail how this page works. To use all features of this page, you should consider registering. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

  • Playm

    RPG Studio Webmaster

    You have to register first, to connect to this user.

316

Eine App schreiben, die RPG Maker Projekte öffnen kann

Rating:

by Playm, Sunday, October 8th 2017, 5:10pm

Wer immernoch nicht mitbekommen hat, dass ich gerade an einem Programm schreibe, was den RPG Maker XP um für Spielentwickler nützliche Features erweitern soll nochmal der Hinweis mal ins Forum zu schauen.
Jetzt ist es für dieses Programm (die Kids von heute sagen dazu auch "App") ganz praktisch auf die Ressourcen des Projekts zuzugreifen, für das es gerade Unterstützung liefert. Auf diese Weise kann die App dann nachgucken, welche Weapons gerade in der Database eingetragen sind oder welche Charakter-Grafiken für Events zur Verfügung stehen. Ich hoffe das fixt euch schon an, dass euch selber ganz viele Möglichkeiten einfallen, was man alles anstellen kann, wenn unser Programm ein RPG Maker Projekt öffnen kann. Im heutigen Blogpost beschäftigen wir uns genau damit.

Was bedeutet es ein Projekt "zu öffnen"?
Wir kennen es aus dem RPG Maker XP, wenn wir auf "Projekt öffnen" klicken. Es erscheint der gewohnte Dateidialog, der uns unsere Dateien auf dem Rechner zeigt. Zusätzlich zeigt uns der Dateidialog an, dass ein sogenannter Filter aktiv ist und wir nur bestimmte Dateien gerade sehen - im Falle des Dateidialogs des RPG Makers XP ist der Filter "RPGXP Project (*.rxproj)".

Diese Datei finden wir auch in jedem Maker Projektordner. Aber was ist eigentlich der Inhalt dieser Datei? Text. In der Datei steht nur eine Zeile Text:

Quoted from "Game.rxproj"

RPGXP 1.05
Mehr steht da nicht. Nur die Versionsnummer des Makers mit dem dieses Projekt erstellt wurde.

Jetzt ist die Frage, warum dann diese Datei? Die Antwort ist kurz: Es geht um den Dateipfad. Den Ort auf der Festplatte.
Haben wir erstmal den Dateipfad zu einem Projekt gefunden, können wir coole Dinge tun.
Angenommen der Dateipfad ist der folgende:

Ruby Source code

1
"C:/Users/Playm/RPGXP/Project Defender/Game.rxproj"

Dann wissen wir, wir finden die Weapons dieses Projekts genau hier:

Ruby Source code

1
2
3
4
5
filename = "C:/Users/Playm/RPGXP/Project Defender/Data/Weapons.rxdata"
File.open(filename, "rb") do |f|
  data_weapons = Marshal.load(f)
  print "We have #{data_weapons.length} weapon entries.\n"
end


Und wir finden die Charaktergrafiken, die das Projekt importiert hat genau hier:

Ruby Source code

1
Dir.glob("C:/Users/Playm/RPGXP/Project Defender/Graphics/Characters/*.*")


Um diese Dateipfade uns zusammen zu bauen, schneiden wir vom Dateipfad der Projektdatei einfach das letzte Stück ab:

Ruby Source code

1
project_path = File.dirname( "C:/Users/Playm/RPGXP/Project Defender/Game.rxproj" )


Und schon können wir unsere Unterpfade dranhängen:

Ruby Source code

1
path_to_weapons = project_path + "/Data/Weapons.rxdata"


Jetzt erstmal die größere Frage: Wie erstelle ich mir eigentlich so einen Dateidialog?

Der Dateidialog
Ich will hier mal drei Optionen aufzählen:
  1. Wir könnten uns unseren eigenen Dateidialog von Grund auf bauen. Ruby kann mittels der Klasse Dir den Inhalt eines Ordners anzeigen. Hierbei kann man auch nach Dateiendung filtern - also alles was man braucht wäre da. Der Nachteil ist, dass man sich noch die Anzeige drumherum bauen muss, sprich das Dialogfenster selber und sehr wahrscheinlich nicht an das Design heran kommt, was der jewilige Nutzer von seiner Windows-Version gewohnt ist.
  2. Wir könnten die WinAPI bemühen und den in Windows standartisierten Dateidialog darüber öffnen. Früher konnte man einfach über die Win32API-Klasse die Funktion GetOpenFileName aufrufen und war bedient. Seit Vista ist diese Funktion deprecated und man soll einen CommonItem-Dialog öffnen. Wer sich dafür interessiert hier ist ein grundlegendes Beispiel zur Benutzung von CommonItem Dialogen. Ich habe mich für meine App gegen diesen Weg entschieden, aber prinzipiell ist das ein gangbarer Weg. Erfordert aber, sich etwas in die Materie einzulesen.
  3. Wir können eine Bibliothek benutzen, die bereits diese Funktion enthält. In unserem Fall ist das Qt. Diese erlaubt uns ohne große Schwierigkeiten vom User eine Datei auswählen zu lassen. Nachteil hier ist, dass man zwingend Qt einbinden muss und der Dialog nur aus einer Qt-App heraus aufgerufen werden kann.


Da wir eh Qt für die restlichen Fenster in unserem Programm verwenden habe ich mich für Option 3 entschieden. Allerdings ist da eine Sache zu bedenken. Das Qt-Binding ist in einer Sache sehr speziell, dass es nicht alle Funktionen der Qt-Bibliothek 1:1 in Ruby wiedergibt, sondern einfach guckt, was für eine Methode für eine Klasse aufgerufen wurde, was die Parameter waren und was wohl am ehesten für eine Qt-Funktion dazu passen würde. Dies sorgt dafür, dass

Ruby Source code

1
Qt::FileDialog.getOpenFileName( parent, "Titelzeile", "." )

einen NoMethod-Error erzeugt, wenn parent den Wert 0 oder nil hat. Die Funktion kann nur aufgerufen werden, wenn wir für parent ein Objekt der Klasse Qt::Widget oder einer Unterklasse davon übergeben. Wenn man daran nicht denkt und nur mal schnell den Dateidialog testen möchte ist das sehr verwirrend.

Jetzt habe ich euch aber lange genug auf die Folter gespannt. Wie sieht denn so ein Beispielcode aus, um ein RPG Maker Projekt zu öffnen?

Rubyscript, um ein RPG Maker Projekt zu öffnen
Als ob ihr euch Ruby installiert habt. :-P Aber trotzdem hier mal ein vollfunktionsfähiger Beispielcode, um sich ein paar kleine Statistiken über ein RPG Maker Projekt ausgeben zu lassen.
Spoiler: Quellcode

Ruby Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
require 'Qt'
require_relative 'rpg.rb'
#==========================================================
# ** Open RPG Maker XP Projects and print statistics
#----------------------------------------------------------
#    Example Code by Playm
#==========================================================
class QtApp < Qt::Widget
  #--------------------------------------------------------
  # * Appwindow initialization
  #--------------------------------------------------------
  def initialize
    super
    setWindowTitle( "File dialog" )
    label = Qt::Label.new( "Open RPG XP Projects", self )
    label.setAlignment( Qt::AlignCenter )
    vbox = Qt::VBoxLayout.new self
    vbox.addWidget( label )
    resize 320, 240
    move 300, 300
    show
  end
  #--------------------------------------------------------
  # * Open FileDialog
  #--------------------------------------------------------
  def get_project_filename( start_path="." )
    title  = "Open Project"
    filter = "RPGXP Projekt (*.rxproj)"
    Qt::FileDialog.getOpenFileName( self, title,
                                    start_path, filter )
  end
  #--------------------------------------------------------
  # * Load content of .rxdata-File
  #--------------------------------------------------------
  def load_rxdata( filename )
    File.open(filename, "rb") do |f|
      Marshal.load(f)
    end
  end
  #--------------------------------------------------------
  # * Print Statistics
  #--------------------------------------------------------
  def print_statistics( path )
    data_items = load_rxdata(path+"/Data/Items.rxdata")
    data_weapons = load_rxdata(path+"/Data/Weapons.rxdata")
    data_armors = load_rxdata(path+"/Data/Armors.rxdata")
    # Print all
    print( "Your Project includes ",
           data_items.length,
           " Items and ",
           data_weapons.length,
           " Weapons and ",
           data_armors.length,
           " Armors.\n")
  end
  #--------------------------------------------------------
  # * Click Handler
  #--------------------------------------------------------
  def mousePressEvent event
    project_filename = get_project_filename()
    project_path = File.dirname( project_filename )
    print_statistics( project_path )
  end
end
#==========================================================
#  Main Run
#==========================================================
app = Qt::Application.new( ARGV )
QtApp.new
app.exec
highlight to read


Auf eine Zeile will ich noch kurz eingehen:

Ruby Source code

2
require_relative 'rpg.rb'

Damit das Script die Database lesen kann, muss es wissen wie die Klassen RPG::Item, RPG::Armor und RPG::Weapon aussehen. Also schnell mal die Makerhilfe aufgemacht, aus der Section "RPGXP Data Structures" die Definitionen der Klassen rauskopiert und in rgb.rb reingespeichert.


Ich hoffe der Blogeintrag war wieder interessant. Diesmal sehr lang und sehr technisch orientiert. Wenn euch das nicht gefällt schreibt es in die Kommentare dann blogge ich nächstes Mal über was lustiges.

This article has been read 481 times.


Comments (3)

  • 3

    by Josey (Monday, October 9th 2017, 10:21pm)

    Oh, woah, das wusste ich noch gar nicht!
    Danke fürs Erklären! :D

  • 2

    by Playm (Monday, October 9th 2017, 3:20pm)

    [quote]Auswahl eines Charsets? XD[/quote]
    Mhm. Das könnte man damit umsetzen.

    [quote]Weil bei den ganzen Data-Paths wird die Game.rxproj nicht miterwähnt o.o[/quote]
    Die Methode File.dirname(...) entfernt aus dem String auch den Dateinamen und liefert nur den Pfad zurück.

    pfad = "C:/Users/Playm/RPGXP/Project Defender/Game.rxproj"
    print( File.dirname( pfad ) )

    Gibt das folgende aus: "C:/Users/Playm/RPGXP/Project Defender"
    Und:

    pfad = "C:/Users/Playm/Desktop/Urlaubsfoto.jpg"
    print( File.dirname( pfad ) )

    Gibt "C:/Users/Playm/Desktop" aus.
    Das kannst Du auch mal im Maker ausprobieren.

  • 1

    by Josey (Monday, October 9th 2017, 12:09am)

    Ich sehe, du hast ein Thema gefunden? ;3

    "Ich hoffe das fixt euch schon an, dass euch selber ganz viele Möglichkeiten einfallen, was man alles anstellen kann, wenn unser Programm ein RPG Maker Projekt öffnen kann."
    Auswahl eines Charsets? XD

    "project_path = File.dirname( "C:/Users/Playm/RPGXP/Project Defender/Game.rxproj" )"
    -> Müsste es nicht heißen
    "project_path = File.dirname( "C:/Users/Playm/RPGXP/Project Defender" )"?
    Weil bei den ganzen Data-Paths wird die Game.rxproj nicht miterwähnt o.o

    Ich fands interessant (hab aber wirklich kein ruby XD) und bin gespannt, was dabei rauskommt. Das Ergebnis interessiert mich, aber den Weg zu sehen ist super : D

Blog navigation

Next article

Mit Qt ganz schnell das RTP des Makers laden

by Playm (Sunday, October 15th 2017, 6:25pm)

Previous article

Ein super einfaches Pluginsystem für Ruby-Apps entwickeln

by Playm (Saturday, September 30th 2017, 10:31pm)