Re: [pygame] Rendering Text By Line

2007-07-11 Thread space coyote

Or you can do word wrapping according to a specified maximum pixel width. I
made a few functions for this in a project.

Here's the code, its pretty self-explanatory.

def truncline(text, font, maxwidth):
   Truncates a single line of text to given pixel size.
   real=len(text)
   stext=text
   l=font.size(text)[0]
   a=0
   done=1
   while l  maxwidth:
   a=a+1
   stext=text.rsplit(None, a)[0]
   l=font.size(stext)[0]
   real=len(stext)
   done=0
   return real, done, stext

def wrapline(text, font, maxwidth):
   Wraps text line by word by word into multiple lines to fit given
pixel size.
   done=0
   wrapped=[]

   while not done:
   nl, done, stext=truncline(text, font, maxwidth)
   wrapped.append(stext.strip())
   text=text[nl:]
   return wrapped

#This one deals with a list of strings
def wraplines(lines, font, maxwidth):
   Wraps text lines to fit given pixel size.
   wrapped=[]

   if type(lines)==str:
   return wrapline(lines, font, maxwidth)

   for line in lines:
   nline=wrapline(line, font, maxwidth)
   for line in nline:
   wrapped.append(line)

   return wrapped

On 7/10/07, [EMAIL PROTECTED] [EMAIL PROTECTED] wrote:


 It's pretty simple to split your string on carriage returns (and/or line
 feeds), create surfaces for each line of text, and blit those surfaces
to
 the destination surface.

I'm doing something like that. I haven't yet gotten word-wrapping to work,
but the following out-of-context code does wrapping by line. It keeps
track of text sent to a class, and a list of drawing surfaces each
containing one character. When it redraws, it figures out where to place
each letter so that they're in order without overflowing the allowed
drawing area.


def AddText(self,text,newline_at_end=True):
In progress -- adding smooth word breaks.

Adds to a list of drawing surfaces each containing one rendered
letter.

self.dirty = True
text = str(text) ## Ensure format is correct.
if newline_at_end:
text += \n

self.text += text

## Add the text as rendered surfaces, one character at a time.
for letter in text:
if letter == \n:
self.text_letter_surfaces.append(None)
else:
rendered_letter = self.pen.Write(letter)
self.text_letter_surfaces.append(rendered_letter)

def RedrawText(self):
Draws all current letter surfaces, automatically wrapping text
so that text doesn't go outside the allowed area.
self.dirty = False
self.text_surface.fill((0,0,0,0))
letter_locations = []
LEFT_EDGE = 0
RIGHT_EDGE = self.cursor_rightmost_x
NEAR_RIGHT_EDGE = RIGHT_EDGE - 100
cursor = [0,0]

for letter in self.text_letter_surfaces:
newline = False
letter_locations.append((cursor[0],cursor[1]))
if letter: ## Ie. if it's not None (a newline):
## Move the cursor for the next letter.
cursor[0] += letter.get_width()
if cursor[0]  RIGHT_EDGE:
cursor[0] = LEFT_EDGE
newline = True
else: ## This is a newline marker.
cursor[0] = LEFT_EDGE
newline = True

if newline:
cursor[1] += self.spacing_between_lines
if cursor[1] + self.spacing_between_lines 
self.text_surface.get_height():
## Move everything up.
letter_locations =
[[l[0],l[1]-self.spacing_between_lines] for l in
letter_locations]
## Move the cursor back up, too.
cursor[1] -= self.spacing_between_lines

## Now, actually put the letter surfaces onto my drawing surface.
for n in range(len(self.text_letter_surfaces)):
if self.text_letter_surfaces[n]:
self.text_surface.blit(self.text_letter_surfaces
[n],letter_locations[n])

## Clean up: Delete characters that aren't visible, for next time.
top = 0 - self.spacing_between_lines
if letter_locations and letter_locations[0][1] = top:
n = 0
last = len(letter_locations)-1
while letter_locations[n][1] = top and n  last:
n += 1
self.text_letter_surfaces = self.text_letter_surfaces[n:]
self.text = self.text[n:]




Re: [pygame] Text-Based RPG

2007-06-18 Thread space coyote

On 6/18/07, Jonah Fishel [EMAIL PROTECTED] wrote:


I've been away from Python for several months. I just came back to
it, to start working on a text-based RPG. To get started, I decided
to move by rooms. I have separate text files for each major message,
to conserve file space. What troubles me is that when I tested it,
whenever I enter anything into the command line, it says 'Invalid
command' which I included as an error message. Here is where I think
the trouble is:

def command_line():
 command = raw_input(' ')
def command(command, current_room):
 if current_room == anthro_tavern:
 if command == 'north':
 print '\n\nThat room does not exist yet. Please try
again.\n\n'
 elif command == 'south':
 print '\n\nThat room does not exist yet. Please try
again.\n\n'
 elif command == 'down':
 print 'That room does not exist yet. Please try again./n/n'
 elif command == 'talk to garrick':
 speech = open('garricks_speech.txt', 'r')
 print speech.read()
 speech.close()
 elif command == 'talk to janet':
 speech = open('janets_speech.txt', 'r')
 print speech.read()
 speech.close()
 elif command == 'talk to stranger':
 print 'This feature is coming soon.'
 else:
 print 'Invalid command.'
 anthro_tavern()
 else:
 print 'Error 1: Non existent room being requested/nfrom. If
this error appears, something/nis very wrong.'
def anthro_tavern():
 text_file = open(swamp_tavern.txt, r)
 print text_file.read()
 text_file.close()
 command(command_line(), anthro_tavern)
 return current_room

anthro_tavern()

I originally had different commands for each action, with variations
on capitalization so you didn't have to enter the same command every
time, but then all it did was the message for the first 'if' line.
Does anyone see a problem with this?



Besides the suggestion to use .strip(), you could also use .split(). For
example:

a = 'say hello'
print a.split()

prints:
['say', 'hello']

Then you have a list. So you can use the first argument as the command and
have a function for each command that parses the other arguments and
produces the desired result.

So if you go:
a = 'say hello'
b = a.split()

then you can go:
if b[0] = 'say':
   say(b)

I hope you understand what I'm saying :)

Also you should look up how 'class'es work. Using them would make this
easier.


[pygame] BUG: File objects do not work in Image: Pygame 1.7.1, WinXP Pro IA32

2007-06-05 Thread space coyote

The code:
img = pygame.image.load(file('b.png'))

results in:
Traceback (most recent call last):
 File C:\Python24\a.py, line 48, in ?
   img = pygame.image.load(file('b.png'))
error: Error reading the PNG file.

I don't know if this has been fixed in Pygame 1.8. If I can get
1.8compiled, I will test it.
This feature is specified in the documents. It is a useful feature, you can
make file-like objects from anything (I wanted to use ZIP files).

Thank you,
Josh

PS: Is there anything I can to help with 1.8?