kitao / pyxel

A retro game engine for Python
MIT License
15.31k stars 847 forks source link

Run Pyxel with no window #489

Closed sanguchi closed 11 months ago

sanguchi commented 1 year ago

Is there any way to run pyxel in a mode that does not create a window? Currently i'm running pyxel normally for a game that is 64x64 but for every frame in the draw function, i store the graphics contents as a class variable:

palette = pyxel.colors.to_list() # type: ignore
# transform screen data from color indexes to color hex
pixel_data = [palette[p] for p in pyxel.screen.data_ptr()]  # 64x64 = 4096 pixel data
arr = [[[0,0,0] for _ in range(64)] for _ in range(64)]  # 64x64x3 list
  for i in range(64):
    for j in range(64):
      n = i * 64 + j  # index of pixel in pixel_data
      p = pixel_data[n]  # pixel color reference ex: int 16750488 = hex 0xff9798
                arr[i][j] = [ (p >> 16) & 0xFF, (p >> 8) & 0xFF, p & 0xFF] # create [r, g, b]
self.native_pixel_data = arr  # Store a 64x64x3 Array 

Then i load that array with numpy and PIL to create a PIL.Image and show it in a tkinter canvas

# Somewhere in my loop
import numpy, PIL
np_array = numpy.asarray(game.native_pixel_data)  # Parse list as numpy array
img = PIL.Image.fromarray(np_array)
img = ImageTk.PhotoImage(img)  # Convert to image format suitable for tkinter
# Tkinter initialization omitted (create root window and attach Label)
tkinter_panel.configure(image=img)  # Update and display the pyxel frame to tkinter

I'm doing this to get the game frame and feed it to a neural network, but also i want to display the current game state in the tkinter window.

kitao commented 11 months ago

Unfortunately, Pyxel does not have a mode to launch without a window. The reason is that the frequency of using such a feature is very low, and providing this functionality would be meaningless without also offering additional features to utilize it (for example, the ability to copy the contents of the screen to a different UI framework).

A more practical approach seems to be accessing Pyxel from a separate layer. For instance, one could obtain the window handle of Pyxel in a platform-specific manner and then set the display attributes of that window to be invisible.