Reputation: 3392
I defined the class of the objects fences
as follows:
class GeoFence(pygame.sprite.Sprite):
def __init__(self, rect, risk_level, *groups):
self._layer = 1
pygame.sprite.Sprite.__init__(self, groups)
self.image = pygame.surface.Surface((rect.width, rect.height))
self.image.fill(GREEN)
self.rect = rect
self.risk_level = risk_level
self.font = pygame.font.SysFont('Arial', 25)
screen.blit(self.font.render(risk_level, True, (255,0,0)), (200, 100))
Each object fence
is a green rectangle. I want to display a text inside this rectangle. The text is defined by a string risk_level
that is selected randomly from the list risks
.
all_sprites = pygame.sprite.LayeredUpdates()
fences = pygame.sprite.Group()
risks = ["HIGH","MEDIUM","LOW"]
for rect in (pygame.Rect(510,150,75,52), pygame.Rect(450,250,68,40), pygame.Rect(450,370,68,48)):
risk = risks[random.randint(0,2)]
GeoFence(rect, risk, all_sprites, fences)
This code does not fail, but the titles are not displayed anywhere on the screen.
Upvotes: 1
Views: 984
Reputation: 20468
The problem is that you're blitting the text at the coordinates (200, 100)
of the screen
surface when the sprites are created, so the text will disappear when the screen gets cleared in the next frame.
In order to blit the text on the GeoFence
objects, you need to blit it onto the self.image
at the coordinates (0, 0)
(if it should be top left aligned).
If the surface should fit to the size of the text, you can render the text surface first and use its size as the size of the self.image
surface.
import random
import pygame
pygame.init()
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
BG_COLOR = pygame.Color('gray12')
GREEN = pygame.Color('green')
FONT = pygame.font.SysFont('Arial', 25)
class GeoFence(pygame.sprite.Sprite):
def __init__(self, rect, risk_level, *groups):
self._layer = 1
pygame.sprite.Sprite.__init__(self, groups)
text_surface = FONT.render(risk_level, True, (255,0,0))
self.image = pygame.surface.Surface(text_surface.get_size())
self.image.fill(GREEN)
self.image.blit(text_surface, (0, 0))
self.rect = self.image.get_rect(topleft=rect.topleft)
self.risk_level = risk_level
all_sprites = pygame.sprite.LayeredUpdates()
fences = pygame.sprite.Group()
risks = ["HIGH","MEDIUM","LOW"]
for rect in (pygame.Rect(510,150,75,52), pygame.Rect(450,250,68,40),
pygame.Rect(450,370,68,48)):
risk = random.choice(risks)
GeoFence(rect, risk, all_sprites, fences)
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
all_sprites.update()
screen.fill(BG_COLOR)
all_sprites.draw(screen)
pygame.display.flip()
clock.tick(60)
It's also possible to pass another color to Font.render
which will be used as the background color. That would allow you to shorten the code a little bit:
class GeoFence(pygame.sprite.Sprite):
def __init__(self, rect, risk_level, *groups):
self._layer = 1
pygame.sprite.Sprite.__init__(self, groups)
self.image = FONT.render(risk_level, True, (255,0,0), GREEN)
self.rect = self.image.get_rect(topleft=rect.topleft)
self.risk_level = risk_level
If you want to center the text, create another rect for the text, set its center
coords to the self.rect.center
and then use it as the blit position for the text. The self.rect
should still be at the default position (0, 0) when you do this.
def __init__(self, rect, risk_level, *groups):
self._layer = 1
pygame.sprite.Sprite.__init__(self, groups)
text_surface = FONT.render(risk_level, True, (255,0,0))
self.image = pygame.surface.Surface(
(text_surface.get_width()+110, text_surface.get_height()+20))
self.image.fill(GREEN)
# Create the rect, but don't set the coordinates yet.
self.rect = self.image.get_rect()
# Set the center of the text_rect to the center of the self.rect.
text_rect = text_surface.get_rect(center=self.rect.center)
# Then blit the text at the text_rect and it will be centered.
self.image.blit(text_surface, text_rect)
# Afterwards set the rect to the desired position.
self.rect.topleft = rect.topleft
Upvotes: 1