Zachary Berkowitz
Zachary Berkowitz

Reputation: 25

Text not updating within loop (within function)

I'm trying to make my own version of OLDTV in Python, but I've run into a problem. I am making an effect where the text is bigger for a moment before going to a regular size. The problem that I am running up against is that the text does not display at all. I am running Anaconda 2.7 (installed in a previous project) with the Spyder editor that comes with, if that helps.

Code:

import pygame
from pygame.transform import scale
from random import randint

def make_font(fonts, size):
    available = pygame.font.get_fonts()
    # get_fonts() returns a list of lowercase spaceless font names
    choices = map(lambda x:x.lower().replace(' ', ''), fonts)
    for choice in choices:
        if choice in available:
            return pygame.font.SysFont(choice, size)
    return pygame.font.Font(None, size)

_cached_fonts = {}
def get_font(font_preferences, size):
    global _cached_fonts
    key = str(font_preferences) + '|' + str(size)
    font = _cached_fonts.get(key, None)
    if font == None:
        font = make_font(font_preferences, size)
        _cached_fonts[key] = font
    return font

_cached_text = {}
def create_text(text, fonts, size, color):
    global _cached_text
    key = '|'.join(map(str, (fonts, size, color, text)))
    image = _cached_text.get(key, None)
    if image == None:
        font = get_font(fonts, size)
        image = font.render(text, True, color)
        _cached_text[key] = image
    return image

pygame.init()
screen = pygame.display.set_mode((640, 480))
real = 0
guess = 0
score = 0
i = 0
gameRunning = False
runEnd = False
clock = pygame.time.Clock()
done = False

font_preferences = [
        "Arial",
        "Times New Roman",
        "Papyrus",
        "Comic Sans MS"]

def endRun(score):
    global gameRunning
    global runEnd
    global i
    screen.fill([255, 255, 255])
    text = create_text(str(score), font_preferences, 72, (0, 0, 0))
    screen.blit(text,
        (320 - text.get_width() // 2, 240 - text.get_height() // 2))
    gameRunning = False
    runEnd = True
    i = 0


def genNext():
    screen.fill([255, 255, 255])
    global real
    gen = randint(1, 2)
    if gen == 2:
        ref = 0
    else:
        ref = 1
    rand1 = randint(1, 6)
    rand2 = randint(1, 6)
    words = ["Red", "Orange", "Yellow", "Green", "Blue", "Purple"]
    if ref == 1:
        if rand1 == rand2:
            real = 0
        else:
            real = 1
        displayWord = words[rand1-1]
        displayCol = rand2
    elif ref == 0:
        real = 0
        displayWord = words[rand1-1]
        displayCol = rand1
    return ReturnValue(displayWord, displayCol)

def displayWordCol(word, col):
    colVal = [(255, 0, 0), (255, 128, 0), (190, 190, 0), (0, 255, 0), (0, 0, 255), (128, 0, 255)]
    for i in range(10, 5):
        text = create_text(word, font_preferences, 72, colVal[col-1])
        scale(text, (text.get_width() * i/5, text.get_height() * i/5))
        screen.blit(text, (320 - text.get_width() // 2, 240 - text.get_height() // 2))
        pygame.display.update()
        clock.tick(60)


def checkNext(real, guess):
    global score
    if real == guess:
        score = score + 1
        e = genNext()
        displayWordCol(e.y0, e.y1)
    else:
        endRun(score)

def homeScreen():
    screen.fill(0)
    text = create_text("OpenTV", font_preferences, 72, (100, 100, 100))
    screen.blit(text,
        (320 - text.get_width() // 2, 240 - text.get_height() // 2))

class ReturnValue:
  def __init__(self, y0, y1):
     self.y0 = y0
     self.y1 = y1

homeScreen()


while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
        if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    if gameRunning == True:
                        guess = 0
                        checkNext(real, guess)
                elif event.button == 3:
                    if gameRunning == True:
                        guess = 1
                        checkNext(real, guess)
        if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RETURN:
                    if gameRunning == False:
                        gameRunning = True
                        score = 0
                        e = genNext()
                        displayWordCol(e.y0, e.y1)
                if event.key == pygame.K_ESCAPE:
                    if gameRunning == True:
                        endRun(score)
                    elif gameRunning == False:
                        done = True


    if runEnd:
        i = i + 1
        if i == 120:
            homeScreen()
            runEnd = False

    pygame.display.flip()
    clock.tick(60)

The part that is causing trouble is the displayWordCol function. Is there something wrong with my code, or should I switch to IDLE and paste in my code?

Upvotes: 2

Views: 175

Answers (1)

Kalma
Kalma

Reputation: 147

I think the main problem is using scale() to scale rendered text. As far as I know, scale() is for images.

Try this as a mere example (you can adapt it to your needs afterwards).

def displayWordCol(word, col):
colVal = [(255, 0, 0), (255, 128, 0), (190, 190, 0), (0, 255, 0), (0, 0, 255), (128, 0, 255)]
    for i in range(10):
        text = create_text(word, font_preferences, int(72 *i/5), colVal[col-1])
        #scale(text, (text.get_width() * i/5, text.get_height() * i/5))
        screen.blit(text, (320 - text.get_width() // 2, 240 - text.get_height() // 2))
        pygame.display.update()
        clock.tick(60)

Another possible problem is that you might need to erase the screen before blitting the word in every loop cycle (not sure which effect you are looking for).

Finally, using pygame is almost always a good thing to use "dirty" rects, erasing and updating only the parts of the screen that have actually changed.

Regards!

EDIT: Try this as well. I added erasing the screen before blitting. I guess this effect is what you were looking for. I also added "dirty" rects management as an example.

def displayWordCol(word, col):
    colVal = [(255, 0, 0), (255, 128, 0), (190, 190, 0), (0, 255, 0), (0, 0, 255), (128, 0, 255)]
    regular_size = 72
    cicles = 20
    size_gap = 5

    initial_size = regular_size + cicles * size_gap
    text = create_text(word, font_preferences, int(initial_size), colVal[col - 1])
    pos = (320, 240)
    rect = pygame.Rect(pos[0] - text.get_width()/2, pos[1] - text.get_height()/2, text.get_width(), text.get_height())

    screen.fill(pygame.Color("white"))
    pygame.display.update()
    for i in range(cicles):
        text = create_text(word, font_preferences, int(initial_size - i*size_gap), colVal[col-1])
        screen.fill(pygame.Color("white"), rect)
        screen.blit(text, (pos[0] - text.get_width()/2, pos[1] - text.get_height()/2))
        pygame.display.update(rect)
        clock.tick(60))

Upvotes: 1

Related Questions