Reputation: 73
To put OOP in practice, I created my own Window class that inherits from pygame.Surface, and adds functionality. According to the following source, this is what I should do:
class MyWindow(pygame.Surface):
def __init__(self, w, h):
pygame.Surface.__init__(self, size=(w, h))
self.screens: list[Screen] = [] # For example
I tried the following code, and it seems to work fine, up until the point where display.update()
is called. This throws a pygame.error
.
myWin: MyWindow = MyWindow(200, 200)
print(myWin) # This correctly prints: <Surface(200x200x32 SW)>
pygame.draw.rect(myWin, (255, 255, 255), (90, 90, 20, 20))
pygame.display.update()
pygame.time.delay(1000)
That code doesn't even create an actual window. In contrast, the following code works just fine, instead relying on the display.set_mode()
function to initialize the Surface.
pyWin: pygame.Surface = pygame.display.set_mode((200, 200))
pygame.draw.rect(pyWin, (255, 255, 255), (90, 90, 20, 20))
pygame.display.update() # Actually shows the square
pygame.time.delay(1000)
Clearly display.set_mode()
does something that Surface.__init__()
doesn't.
TL;DR: How can I initialize an object inheriting from Surface
, in such a way that it actually shows and updates the window?
Thanks!
Upvotes: 2
Views: 784
Reputation: 7361
TL;DR: How can I initialize an object inheriting from Surface, in such a way that it actually shows and updates the window?
I'd say you can't do it in the way you think, and there is a good reason for not ever wanting to do it.
A couple of things to keep in mind:
Surface
is simply a 2D array of pixels, with convenient methods to read / edit / write the values of those pixels. Write where? To other surfaces. You can have as many surfaces you want in a game, each one storing the image of a different element of the game (your main character, an enemy, an element of the map, etc). You can write the content of a Surface on top of another Surface, to make complex images.Surface
, by itself, it has no connection with the screen (i.e. with what is shown on the window you see on your PC monitor).display
is a special Surface
, instantiated by pygame.display.set_mode()
. It is a Surface
like all the other you can create using the Surface
class, but that, and only that Surface, represents the display, i.e. what you see on your monitor.This means that a pygame.Surface
instance is never shown on the screen. To show stuffs on the screen, you need to blit the other Surfaces (i.e. copy their content) somewhere on the special display
Surface.
Now let's go back to your question. With what I have just explained in mind, you could ask: Then can I write a Surface
subclass such that each time the Surface value changes, it is automatically blit on the display
and display.update()
is called`?
Well, it will be complicated. If you use the function from pygame.draw
the Surface is an argument, so you need some good trick to let an argument understanding when it is used.
However, trust me: you don't want to do it. As soon as your game becomes a little more complex, it will be highly inefficient. The reason is that blitting and drawing requires time, so you want to optimize these operations, performing them only when needed. If you have many surfaces in your game, you want to blit them on the display
each iteration of your main loop (or each frame if you prefer) to "prepare" the new frame, and call display.update
only once.
Upvotes: 2