ubuntuusers.de

GameLauncher für Blender-Projekte

Status: Gelöst | Ubuntu-Version: Ubuntu 10.10 (Maverick Meerkat)
Antworten |

Developer92 Team-Icon

Avatar von Developer92

Anmeldungsdatum:
31. Dezember 2008

Beiträge: 4101

Hallo, ich möchte ein kleines Projekt initiieren, welches aber schon *fast* fertiggestellt ist. Ich hab nur leider ein paar Probleme bei der Programmierung, deshalb wollt ich mal die Community fragen ☺

Der GameLauncher an sich funktioniert eigentlich schon, nur eben nicht so, wie ich es will.

Im Anhang ein kleines deb-Paket, welches man installieren kann, mit funktionierendem GameLauncher.

Deinstallation geht über "sudo apt-get remove gamelauncher", starten kann mans über "gamelauncher" oder halt unter Anwendungen → Systemwerkzeuge → gamelauncher.

Wie gesagt, das ganze funktioniert eigentlich schon fast. Jedenfalls, vorwiegend ist es dafür gedacht, dass man seine Blender-Projekte, welche in der GameEngine laufen, auf einfache Art und Weise in ein deb-Paket packen kann, sodass man als Ubuntu-User dieses Paket nur anklicken muss, installieren und dann auch schon starten kann.

Ich zeige euch hier mal das aktuelle Skript, welches das Spiel später startet:

 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
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Import-Anweisungen
import gtk
import os
import sys

UIfile = "gamelauncher.ui"
#CONFIG = "gamelauncher.config"
SCRIPTDIR = str(os.path.dirname(os.path.abspath(sys.argv[0])))
FOLDER = "game"
CONFIG = ""
PROGRAM = "blenderplayer"
FILE = "test.blend"

class gui(object):
    builder=None

    def __init__(self):
        guidir = str(SCRIPTDIR + os.sep + UIfile)
        # Init for builder
        self.builder = gtk.Builder()
        self.builder.add_from_file(guidir)
        self.builder.connect_signals(self)
        # Get Mainframe)
        mainframe = self.builder.get_object('mainframe')
        # Set settings
        mainframe.set_title("GameLauncher")
        # Show Mainframe
        mainframe.show()
        # and start the game
        self.startgame()

    # run() to start program
    def run(self):
        try:
            gtk.main()
        except KeyboardInterrupt:
            pass

    # Quit program
    def quit(self):
        gtk.main_quit()

    # Close-Button
    def on_mainframe_delete_event(self, *args):
        self.quit()

    ##########################################
    # Game specific
    def startgame(self):
        command = str(PROGRAM + " " + CONFIG + " \"" + SCRIPTDIR + os.sep + FOLDER + os.sep + FILE + "\"")
        os.system(command)#
        self.quit()

    ##########################################
    # Actions
    def on_act_quit_activate(self, widget, *args):
        self.quit()

if __name__ == '__main__':
    launcher = gui()
    launcher.run()

Aktuell ist es so, dass der Launcher startet und dann das Spiel lädt. Ohne dass der Launcher auch nur irgendwie angezeigt wird.

Ich brauche aber eigentlich folgende Funktion: Nachdem unter "main" "launcher.run()" ausgeführt wird, soll der Launcher seine GUI zeigen (mainframe.show()). Das Funktioniert soweit. Wenn der launcher geladen wurde (dafür hab ich leider keine Funktion gefunden, deshalb wird startgame() aktuell im Init-Block ausgeführt), sollte startgame() ausgeführt werden. Hierbei sollte dann ein Subprocess gestartet werden, welcher aber im aktuellen Programm läuft. D.h., der so gestartete Blenderplayer soll *keinen* eigenen Eintrag in der Fensterliste haben und wenn möglich auch nicht im Taskmanager angezeigt werden (bzw. Prozessliste).

Und: schließt man den GameLauncher, so soll auch das Spiel (bzw. der blenderplayer) gestoppt werden.

Wäre schön wenn mir hier jemand helfen kann.

Ich konnte mich übrigens nur schwer entscheiden obs unter "Projekte" läuft oder unter "Shell und Programmieren", aber ich denke, da es ein kleiens Projekt ist, ist die Kategorie hier im Forum schon richtig, wenn nicht dann bitte verschieben.

mfg

gamelauncher-1.0-all.deb (57.7 KiB)
Download gamelauncher-1.0-all.deb

Kuehly

Anmeldungsdatum:
15. Oktober 2006

Beiträge: 282

Hi,

soweit ich weiß, muss die init-Methode zu Ende laufen, damit die GUI angezeigt wird.

Das heißt, du müsstest entweder die startgame-Methode in einem anderen Thread starten, oder über ein Event in der GUI ausführen lassen (z.B. Button-Klick). Wenn du sie über ein Event aufrufst, reagiert wahrscheinlich die GUI so lange nicht mehr, bis die Methode, die durch den Event aufgerufen wurde, beendet ist. Also wäre ein Thread für die Methode startgame wahrscheinlich am sinnvollsten.

Gruß, Jan

Developer92 Team-Icon

(Themenstarter)
Avatar von Developer92

Anmeldungsdatum:
31. Dezember 2008

Beiträge: 4101

Kuehly schrieb:

Hi,

soweit ich weiß, muss die init-Methode zu Ende laufen, damit die GUI angezeigt wird.

Das heißt, du müsstest entweder die startgame-Methode in einem anderen Thread starten, oder über ein Event in der GUI ausführen lassen (z.B. Button-Klick). Wenn du sie über ein Event aufrufst, reagiert wahrscheinlich die GUI so lange nicht mehr, bis die Methode, die durch den Event aufgerufen wurde, beendet ist. Also wäre ein Thread für die Methode startgame wahrscheinlich am sinnvollsten.

Gruß, Jan

Die Frage ist: Wie lasse ich den Thread starten? Eine GUI-was-loaded-Event gibt es ja leider nicht (oder hab ichs übersehen?). Es gibt zwar ein show()-Event, aber das wird aufgerufen bevor meine GUI gezeigt wird. Also ebenfalls nix gut ☹

mfg

Kuehly

Anmeldungsdatum:
15. Oktober 2006

Beiträge: 282

Hi.

Am schnellsten kann man so eine Funktion in einem anderen Thread aufrufen:

1
2
3
4
5
6
7
import thread
thread.start_new_thread(self.startgame, ())

# Oder du nimmst das neuere threading-Modul:
import threading
t = threading.Thread(target=self.startgame)
t.start()

Siehe hier http://docs.python.org/library/thread.html#thread.start_new_thread und hier http://docs.python.org/library/threading.html#thread-objects.

Damit das mit GTK zusammen funktioniert muss man glaube ich noch 2 Zeilen mehr einfügen:

1
2
3
4
5
6
7
import gobject

gobject.threads_init()

# Um aus dem Thread dann eine Funktion der GUI aufzurufen,
# muss man das benutzen:
gobject.idle_add(gui_function)

Ich hoffe, das hilft dir weiter.

Gruß, Jan

Developer92 Team-Icon

(Themenstarter)
Avatar von Developer92

Anmeldungsdatum:
31. Dezember 2008

Beiträge: 4101

Threading ist eine gute Idee, funktioniert soweit, DANKE!

Mal ne andre Frage: startgame() führt ja lediglich ein os.system("blenderplayer xyz") aus. D. h., der Blenderplayer läuft eigenständig, auch wenn ich den "GameLauncher" beende. Was natürlich ein Problem darstellt. Ein beenden des GameLaunchers sollte den Blenderplayer auch beenden. Weiß da zufällig jemand eine Möglichkeit? Ich denke, mit subprocess könnts gehen, aber irgendwie bekomm ich das nicht zum laufen (Was mach ich nur falsch?)

mfg

Kuehly

Anmeldungsdatum:
15. Oktober 2006

Beiträge: 282

Also das funktioniert bei mir:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import subprocess
import time

print "Start programm"
p = subprocess.Popen(["gedit", "test.py"])

print "Wait"
for i in range(5, 0, -1):
    time.sleep(1)
    print i

print "Stop programm"
p.terminate()
p.wait()

Gruß, Jan

Developer92 Team-Icon

(Themenstarter)
Avatar von Developer92

Anmeldungsdatum:
31. Dezember 2008

Beiträge: 4101

So, ich hab das eben mal getestet: Bei mir funktioniert das auch wunderbar, sofern ichs mit gedit versuche. Der blenderplayer hingegen lässt sich durch p.terminate() nicht beenden. Schade. Somit wird ein weiteres Projekt zum Scheitern verurteilt 😉

Ich werds jetzt so machen, dass der GameLauncher lediglich nach Updates sucht und bei Bedarf danach fragt und ansonsten einfach nur das Spiel startet und sich selbst beendet.

mfg

Kuehly

Anmeldungsdatum:
15. Oktober 2006

Beiträge: 282

Hm schade. Und wie sieht's mit p.kill() aus? Den Prozess killen, ist zwar nicht die beste Lösung, würde ich sagen, aber wenn nur das funktioniert sollte...

Developer92 Team-Icon

(Themenstarter)
Avatar von Developer92

Anmeldungsdatum:
31. Dezember 2008

Beiträge: 4101

Kuehly schrieb:

Hm schade. Und wie sieht's mit p.kill() aus? Den Prozess killen, ist zwar nicht die beste Lösung, würde ich sagen, aber wenn nur das funktioniert sollte...

Stimmt, p.kill() funktioniert wunderbar.

Andrerseits hab ich jetzt die komplette Oberfläche vom Launcher entfernt und wirklich nur ein Startskript daraus gemacht. Im Prinzip reicht das vollkommen aus.

Es sucht nach Updates (noch nicht implementiert), anschließend ließt es die CONFIG aus (zum Beispiel -f für Fullscreen aus der Config-datei) und startet anschließend das Spiel. Sollte also genügen.

mfg

EDIT: Hab grad alles über den Haufen geworfen und den GameLauncher zum GameCreator umgebastelt (auch wenn der Name etwas irreführend ist - man kann damit nämlich keine Spiele erstellen). Der GameCreator ist ein kleines Skript dass eigentlich aus jeder beliebigen Datei ein deb-Paket bastelt. So auch für Blend-Dateien. Und der Vorteil des ganzen ist: Der GameLauncher ist integriert. D. h., mann kann aus einem bestehenden Blender-Projekt ganz leicht ein deb-Paket basteln und dieses weitergeben. Und durch den integrierten Launcher ist es möglich, dass man dem Blenderplayer sagt, dass er zum Beispiel die Auflösung vom Spiel ändern soll. Das ist mir dem Blenderplayer allein ohne den integrierten GameLauncher nicht möglich.
Hier der Link zur Zip-Datei, falls sich das jemand ansehen will: GameCreator

Antworten |