Python Forum
Pygame writing using fonts and labels
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Pygame writing using fonts and labels
#1
Hello,

I have created a game which has an error in the display of the label when I want to close the pygame window, my pygame window is not the problem as it closes fine but I have come across an issue in the output of the label. I have abstracted the code down to deal with the problem at hand. Can someone please point out my mistake.

import pygame
import time

#pygame initialisation
pygame.init()

def cover(BACKGROUND, screen):
    # This is a library function built in which displays the selected shape - this case a rectangle
    pygame.draw.rect(screen, BACKGROUND, (0, 0, 640, 80))
    
def font():
    #set font for later on use for declaring a window
    Select_Font = pygame.font.SysFont('arial', 70)
    return Select_Font

#Set Colours
Colour_Countdown = (0, 255, 0)
BACKGROUND = (0, 0, 0)

#pygame window setting
screen_size = (640, 640)
screen = pygame.display.set_mode(screen_size)

#setting font for test
LabelFont = font()


#code with possible error
cover(BACKGROUND, screen)
label = LabelFont.render("Closing in ...", 1, Colour_Countdown) #print ("Closing in ...")                                                                                                                                                                                   screen.blit(label, (20,-5))
screen.blit(label, (20,-5))
pygame.time.wait(1000)
cover(BACKGROUND, screen)
label = LabelFont.render("3", 1, Colour_Countdown) #print ("3")
screen.blit(label, (20,-5))
pygame.time.wait(1000)
cover(BACKGROUND, screen)
label = LabelFont.render("2", 1, Colour_Countdown) #print ("2")
screen.blit(label, (20,-5))
pygame.time.wait(1000)
cover(BACKGROUND, screen)
label = LabelFont.render("1", 1, Colour_Countdown) #print ("1")    
screen.blit(label, (20,-5))
pygame.time.wait(1000)
pygame.quit()
Thanks for the long running support
Reply
#2
I just get a blank screen with your program. I also do not get an error at all.

Ideally you should have a main game loop and use a ticks from the game to determine seconds. This i believe is what you are trying to accomplish?

import pygame as pg
import random
 
pg.init()
 
screen = pg.display.set_mode((800,600))
screen_rect = screen.get_rect()
clock = pg.time.Clock()
done = False
 
class Number:
    def __init__(self, number):
        self.timer = 0.0
        self.delay = 1000
        self.number = number
        self.new_num()
 
    def new_num(self):
        self.image, self.rect = self.make_text('Closing in {}'.format(self.number), (255,0,0), screen_rect.center, 75, 'Ariel')
        self.number -= 1
 
    def make_text(self,message,color,center,size, fonttype):
        font = pg.font.SysFont(fonttype, size)
        text = font.render(message,True,color)
        rect = text.get_rect(center=center)
        return text,rect
 
    def update(self): 
        if pg.time.get_ticks()-self.timer > self.delay:
            self.timer = pg.time.get_ticks()
            self.new_num()
        if self.number < 0:
            return True

    def draw(self, surf):
        surf.blit(self.image, self.rect)
 
num = Number(3)
 
while not done:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            done = True
    screen.fill((0,0,0))
    close = num.update()
    if close:
        done = True
    num.draw(screen)
    pg.display.update()
    clock.tick(60)
In this way you can also change the number in the parenthesis to increase it.
Recommended Tutorials:
Reply
#3
Here my example.
import os
import pygame
from types import SimpleNamespace
from pygame.sprite import Sprite, Group

# Wrap pygame builtin colors into namespace.
color = SimpleNamespace(**pygame.color.THECOLORS)

# Interface
class Scene:
    def __init__(self, manager):
        self.manager = manager

    def on_draw(self, surface): pass
    def on_event(self, event): pass
    def on_update(self, delta): pass

    def on_quit(self):
        self.manager.quit()

# Handles what scene is active
class Manager:
    def __init__(self, caption, width, height, center=True, flags=0):
        if center:
            os.environ['SDL_VIDEO_CENTERED'] = '1'

        # Basic pygame setup
        pygame.display.set_caption(caption)
        self.surface = pygame.display.set_mode((width, height), flags)
        self.rect = self.surface.get_rect()
        self.clock = pygame.time.Clock()
        self.running = False
        self.delta = 0
        self.fps = 60

        self.scene = Scene(self)

    def mainloop(self):
        self.running = True
        while self.running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.scene.on_quit()
                else:
                    self.scene.on_event(event)

            self.scene.on_update(self.delta)
            self.scene.on_draw(self.surface)
            pygame.display.flip()
            self.delta = self.clock.tick(self.fps)

    def quit(self):
        self.running = False

class Label(Sprite):
    def __init__(self, text, font, color, position, anchor="topleft"):
        Sprite.__init__(self)
        self._text = text
        self._font = font
        self._color = color
        self._anchor = anchor
        self._position = pygame.Vector2(position)
        self.render()

    def render(self):
        self.image = self._font.render(self._text, 1, self._color)
        self.rect = self.image.get_rect(**{self._anchor: self._position})

    def set_text(self, text):
        self._text = text
        self.render()

class Timer:
    def __init__(self, interval, callback, user_data=None):
        self.tick = pygame.time.get_ticks() + interval
        self.interval = interval
        self.callback = callback
        self.user_data = user_data

    def expire(self, ticks):
        if ticks > self.tick:
            return True

        return False

    def update(self, ticks):
        if ticks > self.tick:
            self.callback(self)
            self.tick += self.interval

class CountDown:
    def __init__(self, count, update_callback, callback, interval=1000):
        self.timer = Timer(interval, self.timer_update)
        self.count = count
        self.callback = callback
        self.update_callback = update_callback

    def timer_update(self, timer):
        self.count -= 1
        if self.count < 1:
            self.callback()
        else:
            self.update_callback(self)

    def update(self, ticks):
        self.timer.update(ticks)

class MainScene(Scene):
    def __init__(self, manager):
        Scene.__init__(self, manager)
        position = manager.rect.centerx, 20
        self.font = pygame.font.Font(None, 32)
        self.label = Label("Welcome", self.font, color.dodgerblue, position, "midtop")
        self.quit_label = None
        self.quit_countdown = None
        self.sprites = Group(self.label)

    def on_draw(self, surface):
        surface.fill(color.black)
        self.sprites.draw(surface)

    def on_quit(self):
        if self.quit_countdown is None:
            self.quit_countdown = CountDown(5, self.update_countdown_label, self.manager.quit)
            self.update_countdown_label(self.quit_countdown)

    def on_update(self, delta):
        ticks = pygame.time.get_ticks()
        if self.quit_countdown:
            self.quit_countdown.update(ticks)

    def update_countdown_label(self, countdown):
        text = "Closing in ... {}"
        if self.quit_label:
            self.quit_label.set_text(text.format(countdown.count))
        else:
            self.quit_label = Label(text.format(countdown.count), self.font,
                              color.firebrick, self.manager.rect.center, "center")
            self.quit_label.add(self.sprites)

if __name__ == "__main__":
    pygame.init()
    manager = Manager("Countdown Example", 800, 600)
    manager.scene = MainScene(manager)
    manager.mainloop()
99 percent of computer problems exists between chair and keyboard.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020