[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [pygame] ** Newbie ** Questions re: text windows and input fields



 >I am a pyGame newbie (using it about a week), writing a simple map
 >editor for an RPG-style game.  I have found pyGame incredibly easy to
 >use; it's really jumpstarted my coding.  But there is one area where I
 >need some direction.  While running my program, I need to print out
 >information, and receive text input.  I've been sendning those things
 >to the command prompt, but it's a hassle flipping back and forth from
 >my graphical game window to the text window, and vice versa.

on seeing your message i thought to myself 'hmm, i wonder how much work 
it is..'

i coded together a rough quake-style console. it works mildly well, but 
might be enough to get the job done for you. i see room for seveal big 
enhancements (and they shouldn't be hard to add if anyone's interested)

	command history buffer
	scrollback buffer
	prettier
	"erase" properly
	hookup to python interpreter :]

while not full featured, it does win points on the 'easy to use' 
category. included in the script is a small runtime test so you can see 
how to make it work (since i just typed this up quick, so no 
documentation :[)

to make it work you just pass it any events you get from pygame. it will 
filter them as appropriate. it will send a "USEREVENT" with a field 
"command" when the user has entered something. add lines to it by 
calling the "write" method.

you can easily use a different font or display more lines by changing 
the arguments passed to the constructor. the rest is fairly easy to 
customize by changing the small "customize" method.

actually, having this full featured would be a great addition to the 
pygame library. for now, this is all you get for my 'morning email 
reading experiment'.

import pygame
from pygame.locals import *

class MiniConsole:
    def __init__(self, font=None, numlines=5):
        self.screen = pygame.display.get_surface()
        if not self.screen: raise RuntimeError, "sceen not initialized"
        if font == None:
            if not pygame.font: raise RuntimeError, "no pygame.font module"
            pygame.font.init()
            font = pygame.font.Font(None, 20)
        self.font = font
        self.numlines = numlines
        self.lineheight = font.get_ascent() + font.get_descent() + 3
        size = self.screen.get_width(), self.lineheight*(numlines+2)
        self.rect = Rect((0, 0), size)
        self.visible = 0
        self.clear()
        self.customize()

    def customize(self):
        self.textcolor = 200, 255, 200
        self.bgcolor = 50, 80, 50
        self.entercolor = 255, 255, 255
        self.event = USEREVENT
        self.write('Welcome to MiniConsole...')
        self.prompt = '>>> '
        self.visiblekey = K_TAB

    def clear(self):
        self.buffer = [None for x in range(self.numlines)]
        self.entered = ''
    
    def write(self, text):
        text = text.strip()
        if not text: return
        print 'TEXT="%s"'%text
        text = self.font.render(text, 0, self.textcolor)
        self.buffer = self.buffer[1:] + [text]

    def draw(self):
        if not self.visible: return None
        self.screen.fill(self.bgcolor, self.rect)
        outline = self.rect.inflate(-2,-2).move(-1,-1)
        pygame.draw.rect(self.screen, self.textcolor, outline, 2)
        height = 0
        for line in self.buffer:
            if line is not None:
                self.screen.blit(line, (3, height))
            height += self.lineheight
        entry = self.prompt + self.entered
        img = self.font.render(entry, 0, self.entercolor)
        self.screen.blit(img, (3, height+3))
        return self.rect

    def handle(self, event):
        if not self.visible:
            if event.type == KEYDOWN and event.key == self.visiblekey:
                self.togglevisible()
                return pygame.event.Event(NOEVENT)
            return event
        if event.type == KEYUP:
            return pygame.event.Event(NOEVENT)
        elif event.type == KEYDOWN:
            if event.key == K_BACKSPACE:
                if self.entered: self.entered = self.entered[:-1]
            elif event.key == K_RETURN:
                if self.entered:
                    entered = self.entered
                    self.entered = ''
                    return pygame.event.Event(self.event, command=entered)
            elif event.key == self.visiblekey:
                self.togglevisible()
            elif event.unicode:
                self.entered += str(event.unicode)
            return pygame.event.Event(NOEVENT)
        return event

    def togglevisible(self):
        self.visible = not self.visible
        if not self.visible:
            self.screen.fill(0, self.rect)
            pygame.display.update(self.rect)




if __name__ == '__main__':
    pygame.init()
    screen = pygame.display.set_mode((640, 480))
    ball = pygame.Surface((60, 60))
    pygame.draw.ellipse(ball, (255, 0, 0), ball.get_rect(), 0)
    screenrect = screen.get_rect()
    ballrect = ball.get_rect()
    ballspeed = [2, 2]
    
    console = MiniConsole()
    clock = pygame.time.Clock()
    
    playing = 1
    while playing:
        for event in pygame.event.get():
            event = console.handle(event)
            if event.type == QUIT: playing = 0
            elif event.type == KEYDOWN and event.key == K_ESCAPE: playing = 0
            elif event.type == USEREVENT:
                message = 'YOU TYPED: "%s"' % event.command
                print message
                print >> console, message

        oldballrect = ballrect
        ballrect = ballrect.move(ballspeed)
        if ballrect.bottom >= screenrect.bottom or ballrect.top < screenrect.top:
            ballspeed[1] = -ballspeed[1]
            console.write("Vertical Bounce! %r"%ballrect)
        if ballrect.right >= screenrect.right or ballrect.left < screenrect.left:
            ballspeed[0] = -ballspeed[0]
            console.write("HorizontalBounce! %r"%ballrect)
            
        rect1 = screen.fill(0, oldballrect)
        rect2 = screen.blit(ball, ballrect)
        rect3 = console.draw()
        pygame.display.update((rect1, rect2, rect3))
        clock.tick(60)