打字机效果 Pygame [英] Typewriter Effect Pygame
问题描述
这个问题真的很难问,但我知道 Stack Overflow 的你们是最聪明的人.
This question is really difficult to ask, but I know you guys here at Stack Overflow are the brightest minds.
我完全不知道为什么会出现这个问题(我对 Python 和 Pygame 相当熟悉,所以我会因为我对提高技能的热爱而收到关于如何改进代码的任何建议).
I'm totally blinded by why this issue happens (I'm fairly at Python and Pygame, so any suggestions on how to improve the code will be received with the love of improving my skills).
我正在创建的内容:这真的是一个噱头项目,我有一个 2.5 英寸的小屏幕 (PiTFT) 连接到 Raspberry Pi,代码正在创建一个打字机效果,在文本写入时在文本前面移动光标.
What I'm creating: It's really a gimmick project, I have a little 2.5" screen (PiTFT) attached to a Raspberry Pi and the code is creating a typewriter effect with a moving cursor in front of the text as it's being written.
挑战 1 每次在 pygame 中移动 sprite 时,必须重新绘制所有内容,否则会看到一条轨迹,并且由于光标在文本前面移动,因此结果如下所示:
Challenge 1 was that every time you move a sprite in pygame, you must redraw everything, otherwise you will see a trail, and since the cursor is moving in front of the text, the result would look like this:
我设法通过变黑/清除屏幕来解决这个问题.但是后来我丢失了所有以前写过的信件.所以我创建了一个列表(整个词),我用以前写的所有字符填充它.每次循环遍历循环时,我都会使用此列表来重绘所有以前的书面文本.所以现在:
I managed to solve this issue by blackening / clearing the screen. But then I lost all the previously written letters. So I created a list (entireword), which I'm populing with all the previously written characters. I use this list every time I cycle through the loop to redraw all the previous written text. So now:
如您所见,文字看起来很有趣.它应该是:
As you can see, the text looks funny. It's supposed to read:
[i] 正在初始化...
[i] Initializing ...
[i] 进入幽灵模式... []
[i] Entering ghost mode ... []
我已经花了几个小时来达到这一点 - 代码几乎完美运行!魔法发生在函数print_screen() 中,但是我的代码中是什么导致文本最后包含来自另一行的字母?:>
I've been spending hours and hours getting to this point - and the code ALMOST works perfectly! The magic happens in the function print_screen(), but WHAT in my code is causing the text to include a letter from the other line in the end? :>
非常感谢您的帮助 <3
Help is GREATLY appreciated <3
完整代码如下:
import pygame
import time
import os
import sys
from time import sleep
from pygame.locals import *
positionx = 10
positiony = 10
entireword = []
entireword_pos = 10
counter = 0
entire_newline = False
#Sets the width and height of the screen
WIDTH = 320
HEIGHT = 240
speed = 0.05
#Importing the external screen
os.putenv('SDL_FBDEV', '/dev/fb1')
os.putenv('SDL_MOUSEDRV', 'TSLIB')
os.putenv('SDL_MOUSEDEV', '/dev/input/touchscreen')
#Initializes the screen - Careful: all pygame commands must come after the init
pygame.init()
#Sets mouse cursor visibility
pygame.mouse.set_visible(False)
#Sets the screen note: must be after pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
# initialize font; must be called after 'pygame.init()' to avoid 'Font not Initialized' error
myfont = pygame.font.SysFont("monospace", 18)
#Class
class cursors(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((10, 20))
self.image.fill((0,255,0))
self.rect = self.image.get_rect()
self.rect.center = (positionx + 10, positiony + 10)
def update(self):
self.rect.x = positionx + 10
self.rect.y = positiony
#Functions
#Prints to the screen
def print_screen(words, speed):
rel_speed = speed
for char in words:
#speed of writing
if char == ".":
sleep(0.3)
else:
sleep(rel_speed)
#re-renders previous written letters
global entireword
# Old Typewriter functionality - Changes position of cursor and text a newline
#Makes sure the previous letters are rendered and not lost
#xx is a delimter so the program can see when to make a newline and ofcourse ignore writing the delimiter
entireword.append(char)
if counter > 0:
loopcount = 1
linecount = 0 # This is to which line we are on
for prev in entireword:
if prev == 'xx':
global linecount
global positiony
global loopcount
linecount = linecount + 1
positiony = 17 * linecount
loopcount = 1
if prev != 'xx': #ignore writing the delimiter
pchar = myfont.render(prev, 1, (255,255,0))
screen.blit(pchar, (loopcount * 10, positiony))
loopcount = loopcount + 1
if char != 'xx':
# render text
letter = myfont.render(char, 1, (255,255,0))
#blits the latest letter to the screen
screen.blit(letter, (positionx, positiony))
# Appends xx as a delimiter to indicate a new line
if entire_newline == True:
entireword.append('xx')
global entire_newline
entire_newline = False
global positionx
positionx = positionx + 10
all_sprites.update()
all_sprites.draw(screen)
pygame.display.flip()
screen.fill((0,0,0)) # blackens / clears the screen
global counter
counter = counter + 1
#Positions cursor at new line
def newline():
global positionx
global positiony
positionx = 10
positiony = positiony + 17
all_sprites = pygame.sprite.Group()
cursor = cursors()
all_sprites.add(cursor)
#Main loop
running = True
while running:
global speed
global entire_newline
words = "[i] Initializing ..."
entire_newline = True
newline()
print_screen(words,speed)
words = "[i] Entering ghost mode ..."
entire_newline = True
newline()
print_screen(words,speed)
#Stops the endless loop if False
running = False
sleep(10)
推荐答案
抱歉没有直接回答你的问题,因为你的代码现在对我来说太混乱了,所以我冒昧地重写了你的代码来完成你想要什么.
Sorry if I don't answer your question directly, because your code is too confusing for me now, so I took the liberty to rewrite your code to get done what you want.
这个想法是有两个精灵:
The idea is to have two sprites:
光标,a) 显示在屏幕上 b) 跟踪要写的文本和位置
the cursor, which is a) displayed on the screen and b) keeps track of what text to write and where
板,基本上只是一个呈现文本的表面
the board, which is basically just a surface that the text is rendered on
请注意 Cursor
类上的所有编写逻辑是如何进行的,我们有一个漂亮、简单且笨拙的主循环.
Note how all the writing logic is on the Cursor
class, and we have a nice, simple and dumb main loop.
import pygame
import os
#Sets the width and height of the screen
WIDTH = 320
HEIGHT = 240
#Importing the external screen
os.putenv('SDL_FBDEV', '/dev/fb1')
os.putenv('SDL_MOUSEDRV', 'TSLIB')
os.putenv('SDL_MOUSEDEV', '/dev/input/touchscreen')
#Initializes the screen - Careful: all pygame commands must come after the init
pygame.init()
clock = pygame.time.Clock()
#Sets mouse cursor visibility
pygame.mouse.set_visible(False)
#Sets the screen note: must be after pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
class Board(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((WIDTH, HEIGHT))
self.image.fill((13,13,13))
self.image.set_colorkey((13,13,13))
self.rect = self.image.get_rect()
self.font = pygame.font.SysFont("monospace", 18)
def add(self, letter, pos):
s = self.font.render(letter, 1, (255, 255, 0))
self.image.blit(s, pos)
class Cursor(pygame.sprite.Sprite):
def __init__(self, board):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((10, 20))
self.image.fill((0,255,0))
self.text_height = 17
self.text_width = 10
self.rect = self.image.get_rect(topleft=(self.text_width, self.text_height))
self.board = board
self.text = ''
self.cooldown = 0
self.cooldowns = {'.': 12,
'[': 18,
']': 18,
' ': 5,
'\n': 30}
def write(self, text):
self.text = list(text)
def update(self):
if not self.cooldown and self.text:
letter = self.text.pop(0)
if letter == '\n':
self.rect.move_ip((0, self.text_height))
self.rect.x = self.text_width
else:
self.board.add(letter, self.rect.topleft)
self.rect.move_ip((self.text_width, 0))
self.cooldown = self.cooldowns.get(letter, 8)
if self.cooldown:
self.cooldown -= 1
all_sprites = pygame.sprite.Group()
board = Board()
cursor = Cursor(board)
all_sprites.add(cursor, board)
text = """[i] Initializing ...
[i] Entering ghost mode ...
done ...
"""
cursor.write(text)
#Main loop
running = True
while running:
for e in pygame.event.get():
if e.type == pygame.QUIT:
running = False
all_sprites.update()
screen.fill((0, 0, 0))
all_sprites.draw(screen)
pygame.display.flip()
clock.tick(60)
这篇关于打字机效果 Pygame的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!