Hi Sorry to not have read your example exactly.
I went curious and tried to extend pygame.Surface by my own. I made a SurfaceObject that has all the draw, transform and gfxdraw functions as its own methods (see attachment). This only works because the functions take a surface as first argument! It was a little experiment and I had to use some trickery to get it to work. Not sure if it is useful at all.
~DR0ID ERName schrieb:
Is it possible to extend the surface class? Every time I do the surface ends up dieing somehow right after it is created... I may just be doing it in the wrong way, though. The main point is to override the __str__() method, so if you know another way besides extending pygame.Surface, I'd be happy to hear it. class ExtendedSurface(pygame.Surface): def __init__(self, surface, string): pygame.Surface.__init__(surface, surface.get_size()) #The docs say to include a size, etc. but that just gives me "too many values to unpack" errors. self.string = string def __str__(self): return self.string Thanks!
#!/usr/bin/python # -*- coding: utf-8 -*- u""" TODO: doc """ __version__ = '$Id$' import pygame try: import pygame.gfxdraw except: pass import new # save a pointer to the original pygame.Surface pygame_surface = pygame.Surface class SurfaceObject(pygame_surface): u""" SurfaceObject is a Surface that has all all functions from pygame.draw, pygame.gfxdraw, pygame.transform as a own method. So instead of calling s = pygame.Surface((10,10)) pygame.draw.line(...) with this SurfaceObject one can do: s = SurfaceObject((10,10)) s.draw_line(...) The SurfaceObject might be slower than using the native functions. At the end, the SurfaceObject needs to be blitted to the screen. """ def __init__(self, size, flags=0, depth=32): super(SurfaceObject, self).__init__(size, flags, depth) # add methods from pygame.draw for name in dir(pygame.draw): if not name.startswith('__'): #new.instancemethod(function, instance, class) attr = getattr(pygame.draw, name) setattr(self, 'draw_'+name, new.instancemethod(attr, self, self.__class__)) try: # add methods from gfxdraw, new in pygame 1.9 for name in dir(pygame.gfxdraw): if not name.startswith('__'): setattr(self, "gfxdraw_"+name, new.instancemethod(getattr(pygame.gfxdraw, name), self, self.__class__)) except: pass # wrapper for functions that return a pygame.Surface # wrapper returns a SurfaceObject instaed of a pygame.Surface class Wrapper(object): def __init__(self, func): self._func = func def __call__(self, *args, **kwargs): s = self._func(*args, **kwargs) # not sure if this creates a surface that is the same a converted surface so = SurfaceObject(s.get_size(), 0, s) # transfer the content so.blit(s, (0,0), ) return so for name in dir(pygame.transform): if not name.startswith('__'): if name in ['threshold', 'average_color']: # this functions take an surf, return a non surf setattr(self, name, getattr(pygame.transform, name)) elif name in ['set_smoothscale_backend', 'get_smoothscale_backend']: # this functions take not a surface and return not a surface # this wrapper is there to just filter out the self argument of the methods class Wrapper1(object): def __init__(self, func): self._func = func def __call__(self, *args, **kwargs): return self._func(*args, **kwargs) w = Wrapper1(getattr(pygame.transform, name)) inst = new.instancemethod(w, self, self.__class__) setattr(self, name, inst) else: # return a surface w = Wrapper(getattr(pygame.transform, name)) inst = new.instancemethod(w, self, self.__class__) setattr(self, name, inst) # some methods from pygame.Surface return a Surface, they need to # be wrapped to return a SurfaceObject for name in ['convert', 'convert_alpha', 'subsurface']: orig_name = '_orig_'+name orig_func = getattr(self, name) setattr(self, name, Wrapper(orig_func)) setattr(self, orig_name, orig_func) # only allow SurfaceObject to be instanciated, even using pygame.Surface pygame.Surface = SurfaceObject pygame.surface.Surface= SurfaceObject if __name__ == '__main__': # usage pygame.init() s = SurfaceObject((400,300)) s.fill((255,0,0)) s.draw_line((255,255,0), (100,100), (400,300), 1) s.draw_circle((0,0,255), (200,200), 50) s.draw_line((255,255,255), (100,100), (300,300), 5) #s.set_colorkey((255,0,0)) #s = s.rotate(90) s2 = pygame.Surface((50,50)) s2.fill((255,255,255)) s2.draw_line((100,100,100), (0,0), (25,25), 3) # print all attributes from a SurfaceObject for i in dir(s): print i, '\t\t\t', getattr(s, i) screen = pygame.display.set_mode((800, 600)) s2 = s2.convert() # update display screen.blit(s, (0,0)) screen.blit(s2, (400,0)) pygame.display.flip() # wait for an event pygame.event.clear() pygame.event.wait()