Thursday, May 16, 2013

Pygame Subset for Android - Soft Keyboard

The guys over at pygame.renpy.org have out-done themsleves with their work on the pygame subset for android development. It can be a bit tricky at first if you're not familiar with ant builds or android development, but for the most part they've made it pretty simple to pick up. If I can figure it out, anyone can do it. So first let me just say thanks to all who have worked on the project.

That being said, there are a number of things I wish worked better. Since the pygame mixer wasn't included, the subset allows you to take advantage of the android mixer. Unfortunately the android mixer isn't quite as full-featured in it's implementation here. The soft-touch keyboard is in the same boat. You can import the android subset, and even have the app call the keyboard, but to my knowledge (and this may be completely wrong) you can't actually watch for these key events. I've tried a multitude of methods and searched for hours on how to correctly do this with the pygame subset for android. I've found absolutely nothing that can show me how to correctly implement this.

So what I ended up doing was writing my own soft-keyboard function. I've tested it and it works great with android apps & games.

Here's basically how it works:

def makeKey(x, y, letter):
   global keyArray
   temp = pygame.image.load('key.png')
   if letter == 'enter':
     temp = pygame.image.load('longkey.png')
   limage = pygame.transform.scale2x(temp)
   lrect = limage.get_rect()
   lrect.topleft = [x,y]
   keyArray.append((limage,lrect,letter))
#map out whole keyboard using makeKey()
def makeKeyboard(x,y):
   letters = ['q','w','e','r','t','y','u','i','o','p','a','s','d','f','g','h','j','k','l','z','x','c','v','b','n','m','enter']
   x_move = 0
   y_move = 0
   for i in letters:
     if i == 'a':
       y_move = 40
       x_move = 0
     if i == 'z':
       y_move = 80
       x_move = 0
     makeKey(x+x_move, y+y_move, i)
     x_move+=40
#draw keyboard and write in letters
def drawKeyboard(color,font,surface):
   global keyArray
   for i in keyArray:
     surface.blit(i[0],i[1])
     drawText(i[2],color,font,surface,i[1].center[0],i[1].center[1],True)
#used for drawing text onto the key surface
def drawText(text, color, font, surface, x, y, center):
   textobj = font.render(text, 1, color)
   textrect = textobj.get_rect()
   textrect.topleft = (x, y)
   if center:
     textrect.center = (x, y)
   surface.blit(textobj, textrect)


Then you can do something like this to implement it:

def main():
   #keyboard start coord
   startKey_x = screen.get_size()[0]/2
   startKey_y = screen.get_size()[1]/2

   #create images and rects for keyboard
   makeKeyboard(startKey_x,startKey_y)

   #temp string for testing
   clickedLetters = ""

   clock = pygame.time.Clock()

   while 1:
     clock.tick(60)
     global MOUSEDOWN
     global keyArray

     for event in pygame.event.get():
       if android:
         if android.check_pause():
           android.wait_for_resume()
       if event.type == pygame.QUIT:
         terminate()
       if event.type==pygame.MOUSEBUTTONDOWN:
         MOUSEDOWN=True
         for i in keyArray:
           if i[1].collidepoint(event.pos):
             if i[2] == 'enter':
               pass
             else:
               clickedLetters+=i[2]
       if event.type==pygame.MOUSEBUTTONUP:
         MOUSEDOWN=False
     drawKeyboard(black,font,screen)
     drawText(clickedLetters, black, font, screen, (800/2), (480/4), True)
     pygame.display.flip()


here's an example implementation

So right before the game loop, you create the keyboard. The makeKeyBoard function just needs a starting position and it will create each key and give it it's own rectangle, image and coordinate.

Inside the main loop, under the event listener, you have it watch for mousebuttondown events. When the app is run on android, this equates to a screen press. It uses the event position to determine if there was a collision with a keyboard rectangle. You can map these collisions to any functions you want. You'll notice my keyboard only has letters and the enter key, but you could set up a full keyboard in much the same way.

This likely isn't the best way to implement a soft-keyboard, but it works which is more than I can say for the android soft-touch keyboard using the pygame subset. If anyone else has a better way to do this, or they managed to figure out how to implement the android soft-touch keyboard, I'd love to hear from you. Especially if you figured out the android soft-touch. I'd love to see how you get the events into python.

-Newt

No comments:

Post a Comment