Typewriter Effect Pygame
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:
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
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)
Have a question for pygame typewriting effect and the background image
Your game just exits after the first screen render. You need to add a loop to your main function to continue the game:
#Main loop
def runGame():
running = True
while (running): # main loop
global gamePad, clock, background
drawObject(background, 0, 0)
for e in pygame.event.get():
if e.type == pygame.QUIT:
running = False
all_sprites.update()
all_sprites.draw(gamePad)
pygame.display.flip()
pygame.display.update() # don't need this
clock.tick(60)
initGame()
runGame()
How do I make text appear letter by letter in a box in Pygame?
See Typewriter Effect Pygame. The basic idea is that you use a timer event (pygame.time.set_timer()
) and append the text letter by letter:
typewriter_event = pygame.USEREVENT+1
pygame.time.set_timer(typewriter_event, 100)
text = 'Hello World'
typewriter_text = ""
while run:
# [...]
for event in pygame.event.get():
if event.type == typewriter_event:
if len(typewriter_text) < len(text):
typewriter_text += text[len(typewriter_text)]
Unfortunately pygame cannot render text with line breaks. You have to render the test line by line. See Rendering text with multiple lines in pygame Typing effect in Python
you should use sys.stdout.flush()
after each iteration
The problem is that stdout is flushed with the newline or manually with sys.stdout.flush()
So the result is
import sys
from time import sleep
words = "This is just a test :P"
for char in words:
sleep(0.5)
sys.stdout.write(char)
sys.stdout.flush()
The reason why your output is buffered is that system call needs to be performed in order to do an output, system calls are expensive and time consuming (because of the context switch, etc). Therefore user space libraries try to buffer it and you need to flush it manually if needed.Just for the sake of completeness ... Error output is usually non-buffered (it would be difficult for debugging). So following would also work. It is just important to realise that it is printed to the error output.
import sys
from time import sleep
words = "This is just a test :P"
for char in words:
sleep(0.5)
sys.stderr.write(char)
Python simple typewriter effect
This is because you're declaring global line
at wrong place;
Try declaring it in loop()
as it's your main function (or initially called function) here:
import time
def typing():
for letter in line:
time.sleep(0.03)
print(letter, end='')
def loop():
global line
line ='I am gay'
typing()
print('')
line ='Are you also gay?'
typing()
print('')
loop()
loop()
DEMO https://repl.it/G7Zw Python/Pygame adding a title screen with a button
The implementation of a button is answered several times. For example Pygame mouse clicking detection, How do I detect if the mouse is hovering over a button? PyGame button class is not displaying the text or changing colour on hover or How can I add an image or icon to a button rectangle in Pygame? and myn more.
Create 2 scenes with 2 application loops. The first loop shows the title screen and waits for button 2 to be pressed. The 2nd loop is the game loop:
button_rect = pygame.Rect(x, y, width, height) # start button rectangle
abort = False
start = False
while not abort and not start:
for event in pygame.event.get():
if event.type == pygame.QUIT:
abort = True
if event.type == MOUSEBUTTONDOWN:
if button_rect.collidepoint(event.pos):
start = True
# draw title screen
# [...]
done = abort
while not done:
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# game
# [...]
Alternatively, you can combine both scenes in one loop.Add a variable
game_state
, implement event handling and draw the scenes depending on the value of game_state
. Change the game_state
when the start button is pressed:game_state = 'title'
done = False
while not done:
# event handling
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if game_state == 'title':
if event.type == MOUSEBUTTONDOWN:
if button_rect.collidepoint(event.pos):
game_state = 'game'
elif game_state == 'game':
# handle game events:
# [...]
# drawing
if game_state == 'title':
# draw title screen
# [...]
elif game_state == 'game':
# game
# [...]
Related Topics
Python, Remove All Non-Alphabet Chars from String
Should All Python Classes Extend Object
How to Flatten a Pandas Dataframe with Some Columns as JSON
What Does 'Wb' Mean in This Code, Using Python
Pairwise Crossproduct in Python
What Do Backticks Mean to the Python Interpreter? Example: 'Num'
How to Include Image Files in Django Templates
Statistics: Combinations in Python
How to Convert a Python List into a C Array by Using Ctypes
Typeerror: Got Multiple Values for Argument
Why Is the Apt-Get Function Not Working in the Terminal on MAC Os X V10.9 (Mavericks)
Difference Between Exit(0) and Exit(1) in Python
Multiprocessing:Use Tqdm to Display a Progress Bar