pokepetter / ursina

A game engine powered by python and panda3d.
https://pokepetter.github.io/ursina/
MIT License
2.23k stars 328 forks source link

Close Ursina app completely. #707

Closed Dinorigami-SLHIDE closed 2 months ago

Dinorigami-SLHIDE commented 3 months ago

So I have this while loop on the main branch :

app = QApplication(sys.argv)
menu = Menu(URL="")
app.exec_()
while True : 
    App = Ursina(title = "My Game", icon = "icon.ico") 
    Ply = Player() # The Player class using FirstPersonController
    UI = GameUI() # The class that contains all buttons/gimmicks not part of the 3D scene
    MAP = Map() # The game environment
    App.run()
    app = QApplication(sys.argv)
    menu = Menu(URL="results")
    app.exec_()

And I have this function that is called on game over :

def ENDGAME():
    RESULT_LINK = "victory"
    App.destroy()

My goal is to make a game that opens a main menu, then closes it and opens the Ursina game and on gameover reopens a menu to show the results, from which we can play again and so on. The problem is that when destroying the Ursina window, it closes it all right but does not stop it from actually running. PS : 1) I don't want to use subprocess or any other library to stop the script and relaunch it. 2) Launching a menu from a function triggers errors.

How would I do that?

a2cy commented 3 months ago

instantiating objects in a loop doesn't really make sense in this case if you want to implement menus you don't need multiple instances of ursina, you can make the ui parented to one entity and just enable and disable it

Dinorigami-SLHIDE commented 3 months ago

Thanks, but... can you provide some code please?

a2cy commented 3 months ago

Sure this is very basic but I hope it helps`from ursina import *

app = Ursina()

menu1 = Entity() # your menus
menu2 = Entity()

menu_state = Animator({"" : None, # use an Animator to automate enabeling and disabeling
                       "menu1" : menu1,
                       "menu2" : menu2})

menu_state.state = "menu1" # change wich menu is enabled

app.run()
Dinorigami-SLHIDE commented 3 months ago

Thanks, but my menu is a PyQT5 window, not an Ursina entity. Oh, maybe my UI class is confusing some bit. It is the parent of all the in-game buttons, the 2D interface that does not belong to the 3d world. What I need is to open a Pyqt5 window (the menu) then open the Ursina game, then close it and reopen a PyQT5 window to play again and so on. Since both Ursina and PyQT5 windowa block the mainloop, I need to close them completely and reopen them without errors such as GEGL operations.

a2cy commented 3 months ago

Why are you using pyqt5 in the first place? Wouldn't it be easier to just make everything in ursina?

Dinorigami-SLHIDE commented 3 months ago

No, I really need PyQt5 unless there is a web browser feature in Ursina. I just need to be able to close the Ursina window, execute some code and reopen it in loop.

pokepetter commented 3 months ago

I don't think what you're asking is possible. You can use subprocess.

Dinorigami-SLHIDE commented 3 months ago

Then would it be possible to hide the Ursina app and open the PyQT menu in a thread and show the Ursina window again after the menu closes?

Dinorigami-SLHIDE commented 3 months ago

No, I can't use Subprocess because I plan to convert the game to .exe and since it has no certificate and it takes a lot of time to load, closing and reopening entirely the game every time does not seem to be a viable solution.

pokepetter commented 3 months ago

Well, the PyQT5 starts a while loop to control drawing the window, input, and so one. So does ursina. They're kind of two separate programs. Your best best is to make the UI in ursina as well, which is how ursina is intended to be used.

Dinorigami-SLHIDE commented 3 months ago

Then would it be possible to display a website on Ursina because I really can't dispose of it?

Dinorigami-SLHIDE commented 2 months ago

I have managed to do it this way :

I used a library called "win32gui" to handle the Ursina window and a "multiprocess" to run the PyQt5 at the same time since both PyQT5 and Ursina cannot run at the same time in the same process.

App = Ursina(title = "Heliosphere", icon = "icon.ico") hwnd = win32gui.FindWindow(None,window.title)

In the main update() function, I put the following code. global hwnd win32gui.ShowWindow(hwnd, win32con.SW_HIDE) proc1 = OpenWindowProcess(conn=child_conn,url=RESULT_LINK) is_multiprocessing = 1 proc1.start() proc1.join() win32gui.ShowWindow(hwnd, win32con.SW_SHOW) resetGame() # Function that resets every object that was generated

And this is the WindowProcess class : class OpenWindowProcess(multiprocessing.Process): def __init__(self,conn,url): multiprocessing.Process.__init__(self) self.conn = conn def run(self): print("Opening window...") app = QApplication(sys.argv) window = Menu(URL=self.open_link) app.exec_()

I hope it can help anyone having the same issue as me.