pyxora.display
1from .assets import Assets 2 3from typing import Tuple 4 5import pygame 6 7class Display: 8 """Handles the main game display surface and rendering.""" 9 10 window = None 11 """The main display window""" 12 surface = None 13 """The main display surface""" 14 clock = None 15 """The main display clock""" 16 17 @classmethod 18 def init(cls, title: str, resolution:Tuple[int, int] ,monitor=0, stretch=False, 19 dynamic_zoom=False,fullscreen=False, resizable=False, vsync=False) -> None: 20 """ 21 Initializes the main display window used by all scenes. 22 23 Args: 24 title (str): The title of the window. 25 resolution (Tuple[int, int]): The resolution of the window (width, height). 26 stretch (bool): Whether to stretch the internal surface to fit the screen. Defaults to False. 27 dynamic_zoom (bool): Whether to dynamically zoom the internal surface. Defaults to False. 28 fullscreen (bool): Start in fullscreen mode. Defaults to False. 29 resizable (bool): Allows the window to be resizable. Defaults to False. 30 vsync (bool): Enables vertical sync. Defaults to False. 31 """ 32 cls._title = title 33 cls._res = tuple(resolution) # make sure it's tuple, no need to raise an error 34 cls._width, cls._height = resolution 35 36 cls._vsync = vsync 37 cls._fullscreen = fullscreen 38 cls._resizable = resizable 39 40 cls._stretch = stretch 41 cls._dynamic_zoom = dynamic_zoom 42 43 cls._new_res = None 44 cls._last_res = None 45 cls._icon = None 46 cls._index = monitor 47 48 cls.clock = pygame.time.Clock() 49 cls.surface = pygame.Surface(resolution) 50 51 cls.set_title(title) 52 53 cls.__set_mode() 54 55 @classmethod 56 def set_title(cls,title: str) -> None: 57 """Class method to set the window title.""" 58 pygame.display.set_caption(title) 59 60 @classmethod 61 def set_icon(cls,icon: pygame.Surface) -> None: 62 """Class method to set the window icon.""" 63 cls._icon = icon 64 pygame.display.set_icon(icon) 65 66 @classmethod 67 def set_res(cls, res: Tuple[float, float]) -> None: 68 """ 69 Set a new resolution (without re-sizing the window) 70 If you want to re-size the window, use the `resize` method instead. 71 72 Args: 73 res (Tuple[float, float]): The new resolution. 74 """ 75 cls._new_res = res 76 77 @classmethod 78 def get_res(cls) -> Tuple[float, float]: 79 """ 80 Get the base resolution. 81 82 Returns: 83 Tuple[float, float]: The main (base) resolution of the window. 84 """ 85 return cls._res 86 87 @classmethod 88 def get_center(cls) -> Tuple[float, float]: 89 """ 90 Get the center point of the base resolution. 91 92 Returns: 93 Tuple[float, float]: The (x, y) center coordinates of the base resolution. 94 """ 95 return (cls._res[0] / 2, cls._res[1] / 2) 96 97 @classmethod 98 def get_size(cls) -> Tuple[float, float]: 99 """ 100 Get the possibly scaled resolution. 101 102 If a new resolution is set, it returns that. 103 Otherwise, it returns the base resolution. 104 105 Returns: 106 Tuple[float, float]: The size of the window. 107 """ 108 return cls._res if not cls.is_resized() else cls._new_res 109 110 @classmethod 111 def is_resized(cls) -> bool: 112 """ 113 Check if the display has been resized. 114 115 Returns: 116 bool: True if a new resolution has been set, otherwise False. 117 """ 118 return bool(cls._new_res) 119 120 @classmethod 121 def is_fullscreen(cls) -> bool: 122 """ 123 Check if the display has been resized. 124 125 Returns: 126 bool: True if a new resolution has been set, otherwise False. 127 """ 128 return cls._fullscreen 129 130 @classmethod 131 def resize(cls, new_res) -> None: 132 """ 133 Resize the display window. 134 135 Args: 136 new_res (tuple[int, int]): The new resolution. 137 """ 138 cls.set_res(new_res) 139 cls.__set_mode() 140 141 @classmethod 142 def get_stretch_surf(cls) -> pygame.Surface: 143 """ 144 Get a stretched version of the internal surface to the new resolution. 145 146 Returns: 147 pygame.Surface: The scaled surface. 148 """ 149 return pygame.transform.scale(cls.surface, cls._new_res) 150 151 @classmethod 152 def toggle_fullscreen(cls) -> None: 153 """Toggle fullscreen mode on or off.""" 154 cls._fullscreen = not cls._fullscreen 155 cls.set_icon(cls._icon) # re-set icon for the new display mode 156 # hack to keep the old resolution after toggling fullscreen 157 if cls._fullscreen: 158 cls._last_res = cls._new_res if cls._new_res is not None else cls._res 159 cls._new_res = pygame.display.get_desktop_sizes()[cls._index] 160 else: 161 cls._new_res = cls._last_res 162 cls.set_res(cls._new_res) 163 # second hack to fix the toggle event problem 164 pygame.event.post(pygame.event.Event(pygame.VIDEORESIZE,w=cls._new_res[0], h=cls._new_res[1])) 165 cls.__set_mode() 166 167 @classmethod 168 def draw_shape(cls, Shape, fill=0) -> None: 169 """ 170 Draw a shape on the screen. 171 172 Args: 173 Shape: The shape object with a `.draw()` method. 174 fill (int, optional): Fill mode or color. Defaults to 0. 175 """ 176 177 # Just calls the abstracted shape.draw method, so we only need one method to draw any future shape :) 178 Shape.draw(cls.surface, fill=fill, scale=1) 179 180 @classmethod 181 def draw_text(cls, Txt) -> None: 182 """ 183 Draw text on the screen. 184 185 Args: 186 Txt: A text object with a `.draw()` method. 187 """ 188 Txt.draw(cls.surface, scale=1) 189 190 191 @classmethod 192 def draw_image(cls, Image) -> None: 193 """ 194 Draw an image on the screen. 195 196 Args: 197 Image: An image object with a `.draw()` method. 198 """ 199 Image.draw(cls.surface, scale=1) 200 201 # Note: I planned to use the new pygame.Window for more features, 202 # but it caused issues with pybgag (web builds), so set_mode for now. 203 @classmethod 204 def __set_mode(cls) -> None: 205 """Private method to set the display mode based on flags and resolution.""" 206 window_res = cls.get_size() 207 vsync = int(cls._vsync) 208 display = cls._index 209 210 # apply the flags 211 flags = 0 212 213 if cls._fullscreen: 214 flags |= pygame.FULLSCREEN 215 flags |= pygame.HWSURFACE 216 flags |= pygame.SCALED 217 218 if cls._resizable and not cls._fullscreen: 219 flags |= pygame.RESIZABLE 220 221 cls.window = pygame.display.set_mode(window_res, flags=flags, vsync=vsync,display=display)
8class Display: 9 """Handles the main game display surface and rendering.""" 10 11 window = None 12 """The main display window""" 13 surface = None 14 """The main display surface""" 15 clock = None 16 """The main display clock""" 17 18 @classmethod 19 def init(cls, title: str, resolution:Tuple[int, int] ,monitor=0, stretch=False, 20 dynamic_zoom=False,fullscreen=False, resizable=False, vsync=False) -> None: 21 """ 22 Initializes the main display window used by all scenes. 23 24 Args: 25 title (str): The title of the window. 26 resolution (Tuple[int, int]): The resolution of the window (width, height). 27 stretch (bool): Whether to stretch the internal surface to fit the screen. Defaults to False. 28 dynamic_zoom (bool): Whether to dynamically zoom the internal surface. Defaults to False. 29 fullscreen (bool): Start in fullscreen mode. Defaults to False. 30 resizable (bool): Allows the window to be resizable. Defaults to False. 31 vsync (bool): Enables vertical sync. Defaults to False. 32 """ 33 cls._title = title 34 cls._res = tuple(resolution) # make sure it's tuple, no need to raise an error 35 cls._width, cls._height = resolution 36 37 cls._vsync = vsync 38 cls._fullscreen = fullscreen 39 cls._resizable = resizable 40 41 cls._stretch = stretch 42 cls._dynamic_zoom = dynamic_zoom 43 44 cls._new_res = None 45 cls._last_res = None 46 cls._icon = None 47 cls._index = monitor 48 49 cls.clock = pygame.time.Clock() 50 cls.surface = pygame.Surface(resolution) 51 52 cls.set_title(title) 53 54 cls.__set_mode() 55 56 @classmethod 57 def set_title(cls,title: str) -> None: 58 """Class method to set the window title.""" 59 pygame.display.set_caption(title) 60 61 @classmethod 62 def set_icon(cls,icon: pygame.Surface) -> None: 63 """Class method to set the window icon.""" 64 cls._icon = icon 65 pygame.display.set_icon(icon) 66 67 @classmethod 68 def set_res(cls, res: Tuple[float, float]) -> None: 69 """ 70 Set a new resolution (without re-sizing the window) 71 If you want to re-size the window, use the `resize` method instead. 72 73 Args: 74 res (Tuple[float, float]): The new resolution. 75 """ 76 cls._new_res = res 77 78 @classmethod 79 def get_res(cls) -> Tuple[float, float]: 80 """ 81 Get the base resolution. 82 83 Returns: 84 Tuple[float, float]: The main (base) resolution of the window. 85 """ 86 return cls._res 87 88 @classmethod 89 def get_center(cls) -> Tuple[float, float]: 90 """ 91 Get the center point of the base resolution. 92 93 Returns: 94 Tuple[float, float]: The (x, y) center coordinates of the base resolution. 95 """ 96 return (cls._res[0] / 2, cls._res[1] / 2) 97 98 @classmethod 99 def get_size(cls) -> Tuple[float, float]: 100 """ 101 Get the possibly scaled resolution. 102 103 If a new resolution is set, it returns that. 104 Otherwise, it returns the base resolution. 105 106 Returns: 107 Tuple[float, float]: The size of the window. 108 """ 109 return cls._res if not cls.is_resized() else cls._new_res 110 111 @classmethod 112 def is_resized(cls) -> bool: 113 """ 114 Check if the display has been resized. 115 116 Returns: 117 bool: True if a new resolution has been set, otherwise False. 118 """ 119 return bool(cls._new_res) 120 121 @classmethod 122 def is_fullscreen(cls) -> bool: 123 """ 124 Check if the display has been resized. 125 126 Returns: 127 bool: True if a new resolution has been set, otherwise False. 128 """ 129 return cls._fullscreen 130 131 @classmethod 132 def resize(cls, new_res) -> None: 133 """ 134 Resize the display window. 135 136 Args: 137 new_res (tuple[int, int]): The new resolution. 138 """ 139 cls.set_res(new_res) 140 cls.__set_mode() 141 142 @classmethod 143 def get_stretch_surf(cls) -> pygame.Surface: 144 """ 145 Get a stretched version of the internal surface to the new resolution. 146 147 Returns: 148 pygame.Surface: The scaled surface. 149 """ 150 return pygame.transform.scale(cls.surface, cls._new_res) 151 152 @classmethod 153 def toggle_fullscreen(cls) -> None: 154 """Toggle fullscreen mode on or off.""" 155 cls._fullscreen = not cls._fullscreen 156 cls.set_icon(cls._icon) # re-set icon for the new display mode 157 # hack to keep the old resolution after toggling fullscreen 158 if cls._fullscreen: 159 cls._last_res = cls._new_res if cls._new_res is not None else cls._res 160 cls._new_res = pygame.display.get_desktop_sizes()[cls._index] 161 else: 162 cls._new_res = cls._last_res 163 cls.set_res(cls._new_res) 164 # second hack to fix the toggle event problem 165 pygame.event.post(pygame.event.Event(pygame.VIDEORESIZE,w=cls._new_res[0], h=cls._new_res[1])) 166 cls.__set_mode() 167 168 @classmethod 169 def draw_shape(cls, Shape, fill=0) -> None: 170 """ 171 Draw a shape on the screen. 172 173 Args: 174 Shape: The shape object with a `.draw()` method. 175 fill (int, optional): Fill mode or color. Defaults to 0. 176 """ 177 178 # Just calls the abstracted shape.draw method, so we only need one method to draw any future shape :) 179 Shape.draw(cls.surface, fill=fill, scale=1) 180 181 @classmethod 182 def draw_text(cls, Txt) -> None: 183 """ 184 Draw text on the screen. 185 186 Args: 187 Txt: A text object with a `.draw()` method. 188 """ 189 Txt.draw(cls.surface, scale=1) 190 191 192 @classmethod 193 def draw_image(cls, Image) -> None: 194 """ 195 Draw an image on the screen. 196 197 Args: 198 Image: An image object with a `.draw()` method. 199 """ 200 Image.draw(cls.surface, scale=1) 201 202 # Note: I planned to use the new pygame.Window for more features, 203 # but it caused issues with pybgag (web builds), so set_mode for now. 204 @classmethod 205 def __set_mode(cls) -> None: 206 """Private method to set the display mode based on flags and resolution.""" 207 window_res = cls.get_size() 208 vsync = int(cls._vsync) 209 display = cls._index 210 211 # apply the flags 212 flags = 0 213 214 if cls._fullscreen: 215 flags |= pygame.FULLSCREEN 216 flags |= pygame.HWSURFACE 217 flags |= pygame.SCALED 218 219 if cls._resizable and not cls._fullscreen: 220 flags |= pygame.RESIZABLE 221 222 cls.window = pygame.display.set_mode(window_res, flags=flags, vsync=vsync,display=display)
Handles the main game display surface and rendering.
18 @classmethod 19 def init(cls, title: str, resolution:Tuple[int, int] ,monitor=0, stretch=False, 20 dynamic_zoom=False,fullscreen=False, resizable=False, vsync=False) -> None: 21 """ 22 Initializes the main display window used by all scenes. 23 24 Args: 25 title (str): The title of the window. 26 resolution (Tuple[int, int]): The resolution of the window (width, height). 27 stretch (bool): Whether to stretch the internal surface to fit the screen. Defaults to False. 28 dynamic_zoom (bool): Whether to dynamically zoom the internal surface. Defaults to False. 29 fullscreen (bool): Start in fullscreen mode. Defaults to False. 30 resizable (bool): Allows the window to be resizable. Defaults to False. 31 vsync (bool): Enables vertical sync. Defaults to False. 32 """ 33 cls._title = title 34 cls._res = tuple(resolution) # make sure it's tuple, no need to raise an error 35 cls._width, cls._height = resolution 36 37 cls._vsync = vsync 38 cls._fullscreen = fullscreen 39 cls._resizable = resizable 40 41 cls._stretch = stretch 42 cls._dynamic_zoom = dynamic_zoom 43 44 cls._new_res = None 45 cls._last_res = None 46 cls._icon = None 47 cls._index = monitor 48 49 cls.clock = pygame.time.Clock() 50 cls.surface = pygame.Surface(resolution) 51 52 cls.set_title(title) 53 54 cls.__set_mode()
Initializes the main display window used by all scenes.
Arguments:
- title (str): The title of the window.
- resolution (Tuple[int, int]): The resolution of the window (width, height).
- stretch (bool): Whether to stretch the internal surface to fit the screen. Defaults to False.
- dynamic_zoom (bool): Whether to dynamically zoom the internal surface. Defaults to False.
- fullscreen (bool): Start in fullscreen mode. Defaults to False.
- resizable (bool): Allows the window to be resizable. Defaults to False.
- vsync (bool): Enables vertical sync. Defaults to False.
56 @classmethod 57 def set_title(cls,title: str) -> None: 58 """Class method to set the window title.""" 59 pygame.display.set_caption(title)
Class method to set the window title.
61 @classmethod 62 def set_icon(cls,icon: pygame.Surface) -> None: 63 """Class method to set the window icon.""" 64 cls._icon = icon 65 pygame.display.set_icon(icon)
Class method to set the window icon.
67 @classmethod 68 def set_res(cls, res: Tuple[float, float]) -> None: 69 """ 70 Set a new resolution (without re-sizing the window) 71 If you want to re-size the window, use the `resize` method instead. 72 73 Args: 74 res (Tuple[float, float]): The new resolution. 75 """ 76 cls._new_res = res
Set a new resolution (without re-sizing the window)
If you want to re-size the window, use the resize
method instead.
Arguments:
- res (Tuple[float, float]): The new resolution.
78 @classmethod 79 def get_res(cls) -> Tuple[float, float]: 80 """ 81 Get the base resolution. 82 83 Returns: 84 Tuple[float, float]: The main (base) resolution of the window. 85 """ 86 return cls._res
Get the base resolution.
Returns:
Tuple[float, float]: The main (base) resolution of the window.
88 @classmethod 89 def get_center(cls) -> Tuple[float, float]: 90 """ 91 Get the center point of the base resolution. 92 93 Returns: 94 Tuple[float, float]: The (x, y) center coordinates of the base resolution. 95 """ 96 return (cls._res[0] / 2, cls._res[1] / 2)
Get the center point of the base resolution.
Returns:
Tuple[float, float]: The (x, y) center coordinates of the base resolution.
98 @classmethod 99 def get_size(cls) -> Tuple[float, float]: 100 """ 101 Get the possibly scaled resolution. 102 103 If a new resolution is set, it returns that. 104 Otherwise, it returns the base resolution. 105 106 Returns: 107 Tuple[float, float]: The size of the window. 108 """ 109 return cls._res if not cls.is_resized() else cls._new_res
Get the possibly scaled resolution.
If a new resolution is set, it returns that. Otherwise, it returns the base resolution.
Returns:
Tuple[float, float]: The size of the window.
111 @classmethod 112 def is_resized(cls) -> bool: 113 """ 114 Check if the display has been resized. 115 116 Returns: 117 bool: True if a new resolution has been set, otherwise False. 118 """ 119 return bool(cls._new_res)
Check if the display has been resized.
Returns:
bool: True if a new resolution has been set, otherwise False.
121 @classmethod 122 def is_fullscreen(cls) -> bool: 123 """ 124 Check if the display has been resized. 125 126 Returns: 127 bool: True if a new resolution has been set, otherwise False. 128 """ 129 return cls._fullscreen
Check if the display has been resized.
Returns:
bool: True if a new resolution has been set, otherwise False.
131 @classmethod 132 def resize(cls, new_res) -> None: 133 """ 134 Resize the display window. 135 136 Args: 137 new_res (tuple[int, int]): The new resolution. 138 """ 139 cls.set_res(new_res) 140 cls.__set_mode()
Resize the display window.
Arguments:
- new_res (tuple[int, int]): The new resolution.
142 @classmethod 143 def get_stretch_surf(cls) -> pygame.Surface: 144 """ 145 Get a stretched version of the internal surface to the new resolution. 146 147 Returns: 148 pygame.Surface: The scaled surface. 149 """ 150 return pygame.transform.scale(cls.surface, cls._new_res)
Get a stretched version of the internal surface to the new resolution.
Returns:
pygame.Surface: The scaled surface.
152 @classmethod 153 def toggle_fullscreen(cls) -> None: 154 """Toggle fullscreen mode on or off.""" 155 cls._fullscreen = not cls._fullscreen 156 cls.set_icon(cls._icon) # re-set icon for the new display mode 157 # hack to keep the old resolution after toggling fullscreen 158 if cls._fullscreen: 159 cls._last_res = cls._new_res if cls._new_res is not None else cls._res 160 cls._new_res = pygame.display.get_desktop_sizes()[cls._index] 161 else: 162 cls._new_res = cls._last_res 163 cls.set_res(cls._new_res) 164 # second hack to fix the toggle event problem 165 pygame.event.post(pygame.event.Event(pygame.VIDEORESIZE,w=cls._new_res[0], h=cls._new_res[1])) 166 cls.__set_mode()
Toggle fullscreen mode on or off.
168 @classmethod 169 def draw_shape(cls, Shape, fill=0) -> None: 170 """ 171 Draw a shape on the screen. 172 173 Args: 174 Shape: The shape object with a `.draw()` method. 175 fill (int, optional): Fill mode or color. Defaults to 0. 176 """ 177 178 # Just calls the abstracted shape.draw method, so we only need one method to draw any future shape :) 179 Shape.draw(cls.surface, fill=fill, scale=1)
Draw a shape on the screen.
Arguments:
- Shape: The shape object with a
.draw()
method. - fill (int, optional): Fill mode or color. Defaults to 0.
181 @classmethod 182 def draw_text(cls, Txt) -> None: 183 """ 184 Draw text on the screen. 185 186 Args: 187 Txt: A text object with a `.draw()` method. 188 """ 189 Txt.draw(cls.surface, scale=1)
Draw text on the screen.
Arguments:
- Txt: A text object with a
.draw()
method.
192 @classmethod 193 def draw_image(cls, Image) -> None: 194 """ 195 Draw an image on the screen. 196 197 Args: 198 Image: An image object with a `.draw()` method. 199 """ 200 Image.draw(cls.surface, scale=1)
Draw an image on the screen.
Arguments:
- Image: An image object with a
.draw()
method.