views:

90

answers:

5

I'm currently making a function using pygame that draws a message on the screen, adding one character each frame (i.e. The Hunt for Red October). I know that I could simply copy (or pass) gradually bigger slices from the original string, but I know that it would be very resource-intensive. Is there a better way to do this?

Code, using gradually bigger slices:

def full_screen_dialog_tt(thesurface, thefont, theclock, message, thebeep):
 i = 0
 while(i < len(message)): # Initialize the string display
  theclock.tick(60)
  thesurface.fill((0, 0, 0))
  thesurface.blit(thefont.render(message[i]+"_"))
  pygame.display.flip()
  thebeep.play()
 while(1): # Whole string is here now
  theclock.tick(60)
  for event in pygame.events.get():
   if event.type == MOUSEBUTTONDOWN: return
+4  A: 

In a place where you are intentionally slowing down the game (for the text fade-in) - does it really matter? You could pass the whole string, and change the display routine to display one more letter in every frame.

relet
The frame-rate that I'm passing to `pygame.clock.tick` is the same 60 that I'm passing to it in the game's main loop. The text isn't "faded" in; it's supposed to look like it's being typed in (either by a keyboard or maybe a slow terminal). As a matter of fact, I may actually have to **raise** the frame-rate for this segment if I find that it takes forever for long messages to type out - though I'm not sure how many computers could handle it. I guess that if I assumed that there won't be any window manipulation, then I could just blank the surface once.
Bushman
A: 

This should work:

>>> o = 'This Is'
>>> s = ''
>>> for i in o:
...     s += i
...     print(s)
...
T
Th
Thi
This
This
This I
This Is
Zonda333
That's not really different from creating gradually longer slices of the original string. And I don't see any pygame in it. :)
jellybean
-1. This creates an extra string object in every iteration. It's not a big issue in such a small program but it's a common Python anti-pattern and should be avoided.
Noufal Ibrahim
Yeah, that's what I'm trying to avoid. Truth be told, I'm almost tempted to just convert the string into a 1-character-per-element list.
Bushman
A string can be used as a 1 character by element list.
Noufal Ibrahim
A: 

You can access a single character from a string using indexes:

>>> s = 'string'
>>> s[2]
'r'
SilentGhost
A: 

Can't you just print the characters one at a time displaced without clearing the background? You can get the character using slicing.

Noufal Ibrahim
Well, I can't just distribute Courier along with the program, and without having a known font to work with, I don't know how many pixels wide or tall it is.
Bushman
The `Font` object can tell you that http://www.pygame.org/docs/ref/font.html#pygame.font.Font. Also, you can distribute a sheet of characters in a custom font along with your game. A Lot of them do that. Read it in as a sprite sheet and render them onto the screen rather than fonts.
Noufal Ibrahim
+1  A: 

Assuming you're having a screen object available, this might work:

import time
text = 'The Hunt for Red October'
myfont = pygame.font.SysFont("arial", 16)
for index, ch in enumerate(text): 
    letter = myfont.render(ch, True, (0, 0, 0), (255, 255, 255))
    screen.blit(letter, (index * 20, 20))
    time.sleep(1)
jellybean
I'm already using `pygame.clock` for the timing (`clock.tick(framespersecond)` to be exact).
Bushman
Ok, you added the code after my response
jellybean