2

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?

1 Answer 1

1

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))
Sign up to request clarification or add additional context in comments.

3 Comments

I wanted it to shrink in, but that leaves behind the old one as well. How do I get rid of that? (The example works, though. Thanks for that!
Oh, I see. Your code is prepared to augment the text, not for shrinking it. You have to "play" with the size and the position of the text. For the size, this part is the key: int(72*i/5), in which you could use something like: int(72+10*2)-i*2)... and similar for the position calculating previous position and size to place new text. In addition to that, the simplest is to erase and update the initial (bigger) rect.
I edited my answer to adapt the function to shrink text instead of augmenting it. Give it a try and comment!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.