Search code examples
pythonpygameinfinitesurface

Is there a way to have an infinite surface size along the width or the height in pygame?


this is a short question I was just wondering in I could have a pygame.surface() with an infinite width.


Solution

  • Simple answer

    It is not possible to have infinitely big surfaces with pygame.

    Complex Answer

    It is not possible, because surfaces in pygame are storing data for every pixel in them. In reality you can't have infinitely big objects, they are only theoretically infinite, but there is an alternative that would work. Don't make infinitely big surface, make it expandable.

    Example Implementations

    This is the simplest one that came to my mind.

    def resize_surface(surf, size):
        ret = pygame.Surface(size)
        ret.blit(surf)
        return ret
    

    But it is a bad solution - it will generate extra unnecessary pixels and you can't have negative positions.

    What you can do is split whole space into chunks, where every chunk is something containing surface and coordinate. Surfaces have to be same size.

    Example code:

    import pygame
    
    
    class Space:
        chunck_size = (30, 30)
        
        def __init__(self):
            self.map = {}
        
        def set_at(self, x, y, color):
            cx, cy, rx, ry = self.get_real_pos(x, y)
            
            if (cx, cy) not in self.map:
                self.map[cx, cy] = self._generate_surface()
            
            self.map[cx, cy].set_at((rx, ry), color)
        
        def get_at(self, x, y):
            cx, cy, rx, ry = self.get_real_pos(x, y)
            
            if (cx, cy) not in self.map:
                self.map[cx, cy] = self._generate_surface()
            
            return self.map[cx, cy].get_at((rx, ry))
            
        def get_real_pos(self, x, y):
            chunck_x = (x - x % self.chunck_size[0]) // self.chunck_size[0]
            relative_x = x - chunck_x * self.chunck_size[0]
            
            chunck_y = (y - y % self.chunck_size[1]) // self.chunck_size[1]
            relative_y = y - chunck_y * self.chunck_size[1]
            
            return chunck_x, chunck_y, relative_x, relative_y
        
        def _generate_surface(self):
            return pygame.Surface(self.chunck_size)
    
    

    Results:

    >>> s = Space()
    >>> s.set_at(100, 100, (255, 100, 0))
    >>> s.get_at(100, 100)
    (255, 100, 0, 255)
    >>> s.set_at(-100, 0, (100, 0, 0))
    >>> s.get_at(-100, 0)
    (100, 0, 0, 255)
    >>> s.get_at(-1000, -1000)
    (0, 0, 0, 255)