Screen¶
Technical overview. The Game Boy LCD renders a 160 by 144 pixel image. PyBoy keeps the current frame in a 32-bit RGBA buffer, which is updated as emulation advances.
Using the API. Screen exposes the
current frame as a Pillow image, a NumPy array, or the raw buffer, together
with its dimensions and format. The image and array reference live data, so
copy them when a frame must be kept after the next call to
tick.
This class gives access to the frame buffer and other screen parameters of PyBoy.
- class pyboy.api.screen.Screen(mb)[source]¶
Bases:
objectAs part of the emulation, we generate a screen buffer in 32-bit RGBA format. This class has several helper methods to make it possible to read this buffer out.
If you’re making an AI or bot, it’s highly recommended to _not_ use this class for detecting objects on the screen. It’s much more efficient to use
pyboy.PyBoy.tilemap_background,pyboy.PyBoy.tilemap_window, andpyboy.PyBoy.get_spriteinstead.- raw_buffer¶
Provides a raw, unfiltered
bytesobject with the data from the screen. CheckScreen.raw_buffer_formatto see which dataformat is used. The returned type and dataformat are subject to change. The screen buffer is row-major.Use this, only if you need to bypass the overhead of
Screen.imageorScreen.ndarray.Example:
>>> import numpy as np >>> rows, cols = pyboy.screen.raw_buffer_dims >>> ndarray = np.frombuffer( ... pyboy.screen.raw_buffer, ... dtype=np.uint8, ... ).reshape(rows, cols, 4) # Just an example, use pyboy.screen.ndarray instead
- Returns:
92160 bytes memoryview of screen data.
- Return type:
- raw_buffer_dims¶
Returns the dimensions of the raw screen buffer. The screen buffer is row-major.
Example:
>>> pyboy.screen.raw_buffer_dims (144, 160)
- Returns:
A two-tuple of the buffer dimensions. E.g. (144, 160).
- Return type:
- raw_buffer_format¶
Returns the color format of the raw screen buffer. This format is subject to change.
Example:
>>> from PIL import Image >>> pyboy.screen.raw_buffer_format 'RGBA' >>> image = Image.frombuffer( ... pyboy.screen.raw_buffer_format, ... pyboy.screen.raw_buffer_dims[::-1], ... pyboy.screen.raw_buffer, ... ) # Just an example, use pyboy.screen.image instead >>> image.save('frame.png')
- Returns:
Color format of the raw screen buffer. E.g. ‘RGBA’.
- Return type:
- image¶
Reference to a PIL Image from the screen buffer. Remember to copy, resize or convert this object if you intend to store it. The backing buffer will update, but it will be the same
PIL.Imageobject. Accessing this property requires Pillow; if Pillow is unavailable, access raisesPyBoyDependencyError.Convenient for screen captures, but might be a bottleneck, if you use it to train a neural network. In which case, read up on the Hardware API features, Pan Docs on tiles/sprites, and join our Discord channel for more help.
Example:
>>> image = pyboy.screen.image >>> type(image) <class 'PIL.Image.Image'> >>> image.save('frame.png')
- Returns:
RGBA image of (160, 144) pixels. Access requires Pillow to be installed.
- Return type:
- ndarray¶
References the screen data in NumPy format. Remember to copy this object if you intend to store it. The backing buffer will update, but it will be the same
ndarrayobject.The format is given by
pyboy.api.screen.Screen.raw_buffer_format. The screen buffer is row-major.Example:
>>> pyboy.screen.ndarray.shape (144, 160, 4) >>> # Display "P" on screen from the PyBoy bootrom >>> pyboy.screen.ndarray[66:80,64:72,0] array([[255, 255, 255, 255, 255, 255, 255, 255], [255, 0, 0, 0, 0, 0, 255, 255], [255, 0, 0, 0, 0, 0, 0, 255], [255, 0, 0, 255, 255, 0, 0, 255], [255, 0, 0, 255, 255, 0, 0, 255], [255, 0, 0, 255, 255, 0, 0, 255], [255, 0, 0, 0, 0, 0, 0, 255], [255, 0, 0, 0, 0, 0, 255, 255], [255, 0, 0, 255, 255, 255, 255, 255], [255, 0, 0, 255, 255, 255, 255, 255], [255, 0, 0, 255, 255, 255, 255, 255], [255, 0, 0, 255, 255, 255, 255, 255], [255, 0, 0, 255, 255, 255, 255, 255], [255, 255, 255, 255, 255, 255, 255, 255]], dtype=uint8)
- Returns:
Screendata in
ndarrayof bytes with shape (144, 160, 4)- Return type:
- property tilemap_position_list¶
This property provides the screen (SCX, SCY) and window (WX - 7, WY) position for each horizontal line in the screen buffer. These parameters are often used for visual effects, and some games will reset the registers at the end of each call to
pyboy.PyBoy.tick().See
Screen.get_tilemap_positionfor more information.Example:
>>> pyboy.tick(25) True >>> swoosh = pyboy.screen.tilemap_position_list[66:77] >>> print(*swoosh, sep=newline) # Just to pretty-print it [0, 0, -7, 0] [1, 0, -7, 0] [2, 0, -7, 0] [2, 0, -7, 0] [3, 0, -7, 0] [3, 0, -7, 0] [3, 0, -7, 0] [2, 0, -7, 0] [1, 0, -7, 0] [1, 0, -7, 0] [0, 0, -7, 0]
- Returns:
A list of 144
[SCX, SCY, WX - 7, WY]lists. Returns[0, 0, 0, 0]for each line when the LCD is off.- Return type:
- gpu_tensor(device)[source]¶
Render a fast-mode frame from VRAM and OAM into a PyTorch tensor on
device.devicemust be an accelerator:"mps"or"cuda". The GPU decodes tile data, applies DMG/CGB palettes, renders the window, and composites sprites. VRAM and OAM are synchronized incrementally. The result is atorch.uint8tensor with shape(144, 160, 4).This fast-mode rendering path uses VRAM, OAM, LCDC, and palette state captured at VBlank, together with captured per-scanline viewport/window parameters. It intentionally does not reproduce mid-frame changes or exact PPU priority timing, and it does not replace
screen.ndarray.The GPU render is submitted at VBlank, and the regular CPU renderer is skipped on subsequent frames, so
screen.ndarrayis not updated while an accelerator is selected. CUDA VRAM/OAM updates are prefetched at the start of the LY 143 HBlank when their generations change. The returned tensor is reused and overwritten by subsequent frames; clone it to retain a frame.Install
torch>=2.6to use this feature.Example:
>>> pyboy = PyBoy("game.gb", window="null", fast_mode=True) >>> pyboy.tick(1) True >>> frame = pyboy.screen.gpu_tensor("mps") >>> frame.shape torch.Size([144, 160, 4])
- get_tilemap_position()[source]¶
These coordinates define the tile-map offsets for the top-left corner of the screen and window. The tile map is 256x256 pixels, while the screen shows 160x144 pixels; scrolling past an edge wraps around to the other side.
For more details, see “7.4 Viewport” in the report, or the Pan Docs under LCD Position and Scrolling.
Example:
>>> pyboy.screen.get_tilemap_position() ((0, 0), (-7, 0))
- Returns:
((SCX, SCY), (WX - 7, WY)).- Return type: