Python / Pygame - 创建“结束学分”,就像电影结束时那样

时间:2016-03-22 20:27:13

标签: python pygame

我正在尝试使用pygame创建像电影结尾那样的“结束信用”。我已经使用python搜索其他方法来实现这一点,但我还没有找到任何方法。

我几乎用以下代码实现了这一点:http://pastebin.com/nyjxeDYQ

#!/usr/bin/python
import time
import threading
import pygame
from pygame.locals import *

# Initialise pygame + other settings
pygame.init()
pygame.fastevent.init()
event_get = pygame.fastevent.get
pygame.display.set_caption('End credits')
screen = pygame.display.set_mode((1920, 1080))
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((255, 255, 255))
fontsize = 40
font = pygame.font.SysFont("Arial", fontsize)
x = 0

def main():
    global x
    credit_list = ["CREDITS - The Departed"," ","Leonardo DiCaprio - Billy","Matt Damon - Colin Sullivan", "Jack Nicholson - Frank Costello", "Mark Wahlberg - Dignam", "Martin Sheen - Queenan"]

    going = True
    while going:
        events = event_get()
        for e in events:
            if e.type in [QUIT]:
                going = False
            if e.type in [KEYDOWN] and e.key == pygame.K_ESCAPE:
                going = False

        # Loop that creates the end credits
        ypos = screen.get_height()
        while ypos > (0 - len(credit_list)*50) and x == 0: # Loop through pixel by pixel, screenheight + height of all the textlines combined
            drawText(credit_list,ypos)
            ypos = ypos - 1
        x = 1

    pygame.quit()

def drawText(text,y):
    for line in text:
        text = font.render(line, 1, (10, 10, 10))
        textpos = text.get_rect()
        textpos.centerx = background.get_rect().centerx
        background.blit(text, (textpos.x,y))
        y = y + 45

    # Blit all the text    
    screen.blit(background, (0, 0))
    pygame.display.flip()
    time.sleep(0.0001) # Sleep function to adjust speed of the end credits

    # Blit white background (else all the text will stay visible)
    background.fill((255, 255, 255))
    screen.blit(background, (0, 0))
    pygame.display.flip()

if __name__ == '__main__': main()

问题是滚动文本是闪烁的。这是因为我使用time.sleep() - 函数来控制滚动的速度。当我使用0.04秒这样的值时,它运行得很好,但是文本移动得太慢而且仍然有一些闪烁。当我使用更低的值,例如:0.001秒时,文本以我喜欢的速度移动,但还有更多的闪烁。

我可以使用另一个值来调整滚动速度:要移动的像素数。但是当我将其设置为高于1的任何值时,滚动就不再平滑了。

有谁知道这个问题的解决方案?我不一定要使用pygame,但我必须使用python。

非常感谢提前!

阿尔布雷希

1 个答案:

答案 0 :(得分:1)

以下是您应遵循的一些简单规则,可以帮助您解决问题:

  • 每帧不要多次拨打pygame.display.flip()
  • 请勿使用time.sleep()来控制应用程序中某些内容的速度
  • 使用Clock来控制帧速率

这是一个清理过的,最小的工作示例:

#!/usr/bin/python
import pygame
from pygame.locals import *

pygame.init()
pygame.display.set_caption('End credits')
screen = pygame.display.set_mode((800, 600))
screen_r = screen.get_rect()
font = pygame.font.SysFont("Arial", 40)
clock = pygame.time.Clock()

def main():

    credit_list = ["CREDITS - The Departed"," ","Leonardo DiCaprio - Billy","Matt Damon - Colin Sullivan", "Jack Nicholson - Frank Costello", "Mark Wahlberg - Dignam", "Martin Sheen - Queenan"]

    texts = []
    # we render the text once, since it's easier to work with surfaces
    # also, font rendering is a performance killer
    for i, line in enumerate(credit_list):
        s = font.render(line, 1, (10, 10, 10))
        # we also create a Rect for each Surface. 
        # whenever you use rects with surfaces, it may be a good idea to use sprites instead
        # we give each rect the correct starting position 
        r = s.get_rect(centerx=screen_r.centerx, y=screen_r.bottom + i * 45)
        texts.append((r, s))

    while True:
        for e in pygame.event.get():
            if e.type == QUIT or e.type == KEYDOWN and e.key == pygame.K_ESCAPE:
                return

        screen.fill((255, 255, 255))

        for r, s in texts:
            # now we just move each rect by one pixel each frame
            r.move_ip(0, -1)
            # and drawing is as simple as this
            screen.blit(s, r)

        # if all rects have left the screen, we exit
        if not screen_r.collidelistall([r for (r, _) in texts]):
            return

        # only call this once so the screen does not flicker
        pygame.display.flip()

        # cap framerate at 60 FPS
        clock.tick(60)

if __name__ == '__main__': 
    main()