0
votes

I am trying to achieve the following using pygame: printing a changing text part of a sprite and update the sprite every frame. The sprite is a simple transparent rectangular area surounded by red edges. At the center of that area a number is printed and that number change over time. I also want to use the dirty rectangle method.

I haven't managed yet to make it work in my game but I have reproduce the scenario in the following sample (you can run it as is):

import pygame
from pygame.locals import *

class Sprite(pygame.sprite.Sprite):
        def __init__(self, group=None):

            pygame.sprite.Sprite.__init__(self, group)
            self.counter = 0

            self.image = pygame.Surface((100,100)).convert_alpha()
            self.image.fill((0,0,0,0))
            pygame.draw.rect(self.image, (255,0,0), [ (0,0), (100,100) ], 1)
            self.rect = self.image.get_rect()

            self.myfont = pygame.font.SysFont("monospace", 15)
            text = str(self.counter)
            label = self.myfont.render(text, 1, (255,0,0))
            self.image.blit(label, self.rect.center)

        def update(self):
            rect_save = self.rect
            self.image = pygame.Surface((100,100)).convert_alpha()
            self.image.fill((0,0,0,0))
            pygame.draw.rect(self.image, (255,0,0), [ (0,0), (100,100) ], 1)
            self.rect = self.image.get_rect()
            self.rect.x = rect_save[0]
            self.rect.y = rect_save[1]

            text = str(self.counter)
            label = self.myfont.render(text, 1, (255,0,0))

            self.image.blit(label, self.rect.center)


Quit = False

pygame.init()
window = pygame.display.set_mode((640, 480))
render = pygame.sprite.RenderUpdates()

sprite = Sprite(render)
BUG = False
if BUG:
    sprite.rect = (300,300)


while not Quit:
    for event in pygame.event.get():    
        if event.type == QUIT:
            Quit = True
        if event.type == KEYDOWN:
            sprite.counter += 1

    background = pygame.Surface( window.get_size() )
    background.fill( (0,0,0) )
    render.clear( window, background )

    render.update()

    dirty = render.draw(window)
    pygame.display.update( dirty )
#end while

pygame.quit()

In the code example I have defined a BUG variable to trigger the problem I encounter. If I set the BUG to False my sprite is rendered as wanted in the top left corner of the screen with the text updating when hitting a key. However when I set BUG to True the sprite is rendered at the right position on the screen but the text is not there anymore.

How can I make that second case work as expected ?

Thanks

Note: the following post didn't help solving my problem Python pygame writing text in sprite

1
when you use render.update(), the update() function of sprite (object of your user defined Sprite Class) is called. Now as there in so counter incrementation in there, the counter doesn't get updated. Changes: instead of 'counter += 1', write 'sprite.counter += 1'. - GLaDOS
My mistake, thank you for that! I have corrected and slightly edited the code. Now it reproduce exactly what i experience in the full game. simply change the "BUG" variable from True to False to trigger my problem. - Guillaume.P

1 Answers

0
votes

Solution of the BUG problem is:

You need to understand the meaning of

self.image.blit(label, self.rect.center)

This won't work if you are trying to blit text on the surface which isn't positioned at (0,0). Why? Because you aren't blitting text directly on the display. You are blitting it on the surface. You need to provide coordinates respective to the surface and not to the display.

This worked before as your surface was positioned on the display at (0,0). Now as you have changed the position of your surface to (300,300), self.rect.center is now (350,350). It should be (50,50) as your surface (width,height) is (100,100).

So now keep the BUG True and change that statement to:

self.image.blit(label, (50,50))

If you want better positioning, use:

text = str(self.counter)
label = self.myfont.render(text, 1, (255,0,0))
text_rect = label.get_rect()
text_rect.center = (50,50)

self.image.blit(label, text_rect)