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)
class 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.

window = None

The main display window

surface = None

The main display surface

clock = None

The main display clock

@classmethod
def init( cls, title: str, resolution: Tuple[int, int], monitor=0, stretch=False, dynamic_zoom=False, fullscreen=False, resizable=False, vsync=False) -> None:
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.
@classmethod
def set_title(cls, title: str) -> None:
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.

@classmethod
def set_icon(cls, icon: pygame.surface.Surface) -> None:
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.

@classmethod
def set_res(cls, res: Tuple[float, float]) -> None:
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.
@classmethod
def get_res(cls) -> Tuple[float, float]:
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.

@classmethod
def get_center(cls) -> Tuple[float, float]:
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.

@classmethod
def get_size(cls) -> Tuple[float, float]:
 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.

@classmethod
def is_resized(cls) -> bool:
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.

@classmethod
def is_fullscreen(cls) -> bool:
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.

@classmethod
def resize(cls, new_res) -> None:
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.
@classmethod
def get_stretch_surf(cls) -> pygame.surface.Surface:
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.

@classmethod
def toggle_fullscreen(cls) -> None:
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.

@classmethod
def draw_shape(cls, Shape, fill=0) -> None:
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.
@classmethod
def draw_text(cls, Txt) -> None:
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.
@classmethod
def draw_image(cls, Image) -> None:
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.