Posts Tagged ‘ pygame

Android anyone?

android01While I’ve really been enjoying coding with Pygame and Python… one thing they don’t seem to be able to do is play well with mobile phones.  Specifically things like the iPhone and Android devices.  Everyone I show my BubblePaint Pygame program to has the same comment:  You should put that on the iPhone!  And I’d love to!  But I don’t see Python entering into the iPhone’s future anytime soon, and I have no real want to learn Objective-C or C++ for iPhone dev.  Plus, I really don’t want to have to buy a Mac just to release my iPhone apps :-S

Enter Android.  Can develop for it on the PC (plus!).  Uses Java as its programming language.  And now appears to support Python scripting!  So far so good! (well, other than the fact I signed a 2-year deal with AT&T so my wife could get an iPhone <wink> )

I’m a bit warmer to Java than other languages based on my familiarity with Processing.  But I still really don’t “know Java” (however I have to say that Processing was a gentle introduction).  So I went out this weekend and picked up these books:

Then I:

  • Installed Eclipse IDE, since the Android platform has some Eclipse-specific plugins to aid in it’s development.
  • Installed the Android SDK (thanks to this post)

And finally I:

  • Started reading the Java book.

I’m now on… day 3… of 21.  It’s going pretty fast since Java is not so unlike Python in many regards.  The only thing I find unfortunate is that the more I learn of Java… the more I miss Python.  Python’s dynamic typing is sooooo much more conducive to my brain than Java’s static typing, and the stripped down syntax of Python just makes me feel… cleaner, compared to all the brackets, semi-colons, variable casting and whatnot needed in Java.  Bah!  End rant.

We’ll see where this leads:  I really like the idea of making games on mobile devices, and Android seems like an accessible platform.  I just hope AT&T starts selling the devices soon (the emulator will only get me so far) and learning Java doesn’t  cause me to rant too much….

:-)

Updated Pygame Tablet Pressure

This blog post has its own page:  Check there for latest info.

Updated to version 1.3:  Realized that I didn’t need to track mouse position and button-presses in the Tablet class:  Pygame does all this for you.  Solves a lot of problems.  Tablet object now only returns back pressure info, which is all we really want from it anyway.  The example ‘Pressure Test’ app has been updated as well to reflect this as well.

Pygame Window Info

(This post has its own page here)

While working on my ‘Tablet Pressure‘ code, I realized I needed a way to be able to query the position of the active Pygame screen relative to the desktop. There didn’t seem to be any built-in way in Pygame to do this.

After doing some searching, I ran across Python‘s ctypes bindings. These let you tap into Windows (the OS) ‘window info’. Based on fiddling with that code, I’ve come up with a Python class that lets you query a few things:

  • The extents of the active Pygame window relative to the desktop: top, bottom, left, and right coordinates.
  • The extents of the active Pygame screen inside that window, relative to the desktop: top, bottom, left, and right coordinates.
  • The width of the window border edges, and the title bar.

Download the source here:

It comes with its own unit test: Executing from a shell will give you a floating resizable Pygame window, and a printout like this in the shell, showing its functionality:

Here’s the unit test code, showcasing its functionality:

# Unit Testing:
if __name__ == "__main__":
    """Unit Test, will print window, screen and border thicknesses to the shell."""

    pygame.init()

    # Must set this env var for PygameWindowInfo to work!
    os.environ['SDL_VIDEO_WINDOW_POS'] = "128,128"

    screen = pygame.display.set_mode((256, 256), pygame.RESIZABLE)
    pygame.display.set_caption("PygameWindowInfo v%s"%__version__)

    # Create our object:
    winInfo = PygameWindowInfo()

    # Main loop:
    looping = True
    while looping:
        # ***Must update our winInfo object during every loop*** to accurately
        #  track window and display screen position
        winInfo.update()

        screen.fill(pygame.Color("black"))

        events = pygame.event.get()
        for event in events:
            if event.type == pygame.QUIT:
                looping = False
            if event.type == pygame.VIDEORESIZE:
                WIDTH, HEIGHT = event.size
                screen = pygame.display.set_mode((WIDTH, HEIGHT), pygame.RESIZABLE)

        winPos = winInfo.getWindowPosition()
        screenPos = winInfo.getScreenPosition()

        # Print interesting data!
        print "Window -",
        for key in winPos.keys():
            print "%s: %s"%(key, winPos[key]),
        print " |  Screen -",
        for key in screenPos.keys():
            print "%s: %s"%(key, screenPos[key]),
        print " |  Title thickness: %s"%winInfo.titleThickness,
        print " |  Border thickness: %s"%winInfo.borderThickness,
        print "\n",

        pygame.display.flip()

    pygame.quit()

Enjoy!

Tablet pressure sensitivity in Python and Pygame

This blog post has its own page:  Check there for latest info.

In Pygame, tablets (or at least my Wacom Bamboo) acts just like a mouse.  But it appears that Pygame, and the underlying SDL don’t detect tablet pressure. I’ve read that starting with SDL 1.3/2.0 it will detect for tablet pressure, but until then (currently v1.2)… what options are there?  It doesn’t seem that Python itself has any built-in modules for this either (that I can find…).

After asking the user groups, I tracked down an interface into wintab api through the “Python Computer Graphics Kit” (cgkit).   The API was developed by LCS/Telegraphics and maintained by Wacom:  cgkit has a wintab wrapper (docs) that appears to hook into Wacom standards.

But even with their docs, it took me a bit of troubleshooting to turn it into something usable, but I have:  ‘tablet.py’ which contains a ‘Tablet’ class, and a ‘pressureTest.py’ Pygame app showing it off:

  • cgkit download.  Required to run tablet.py.
  • tablet.py – Module containing the Tablet class.
  • pressureTest.py – Simple Pygame example using the Tablet class.
  • Built with Python 2.6.2, Pygame 1.9.1, cgkit 2.0.0 alpha9

Details:

tablet.py is a module containing a Tablet class, that will give you tablet querying functionality in your Pygame programs.  In a nutshell, you create a Tablet object, then inside the main loop you query your Tablet.getData() method instead of pinging pygame.mouse.  That method spits out this data:

  • The currently pressed pen ‘button’ as an int.
  • x,y tablet cursor position, relative to the current Pygame screen.
  • The tablet ‘pressure’ as an int, mapped from 0-1023

Expected behavior:

  • Given the example in pressureTest.py, on my machine, the tablet maps 100% of it’s surface region into the Pygame window:  It’s impossible for me to move the cursor outside of the Pygame window using the tablet (but the mouse still has external control).
  • However, based on other users, I’ve received reports of the tabletspace->pygame screen mapping not working, and their tablet still has free run of the whole computer screen.  This would cause problems, but unfortuntealy I have no way of testing this without other tablets\computers :(  If you run into this, you can try to troubleshoot:  Go to the wintab docs.  In the Tablet class, I’m querying these Context attrs for the tablet resolution, for mapping purposes back into pygame:  Context.inextx, Context.inexty.  There are many more attrs though, and those just happened to work for me.  If you try other attrs and they solve your problem, please let me know so I can update my code.

Here’s the few lines of code you’d use to put it in a Pygame app (illustrated in pressureTest.py):

from tablet import Tablet
tablet = Tablet(screen)
# Main loop:
while looping:
    button, x, y, pressure = tablet.getData()

This is the general implementation behind capturing the tablet data (crack open tablet.py to see what’s going on).  I should point out this was all by trial and error.  There could be better\more efficient\more eloquent ways of doing this.  But, this works :)

  • the wintab module needs to know the ‘window handle’ \ ‘window id’ for the current pygame app.  This isn’t something you query, but something you set.  The Tablet object makes up a window id, and sets it as an environment var:
    • os.environ[“SDL_WINDOWID”] = str(hwnd)
  • Create a new wintab Context object that will capture our tablet data:
    • self.context = wintab.Context()
  • Define what type of data our context will return via Packet objects.  These are based on wintab constants:
    • self.context.pktdata = ( PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE )
    • It should be noted that the default values for pkdata (if you don’t define your own) are: xpos, ypos, buttons.
  • Open out context:
    • self.context.open(self.hwnd, True)
  • Then later we can query our Tablet object once per Pygame loop for Packet object data.  A LOT of packet data can be returned.  So we query the “extent” of the packets that were returned:
    • packetExtents = self.context.queuePacketsEx()
    • If the pen is away from the tablet, it will return None, so in that case, we don’t eval anything.
  • Presuming we found packet data, we the last packet list from the sub-list of packets that were returned:
    • packets = self.context.packetsGet(packetExtents[1])
  • And, we isolate the last packet in that sublist: (did I mention there were a lot of packets being returned?)
    • packet = packets[-1]
  • Based on that Packet object, we can now query it for which buttons were pressed, the x & y position, and the all important pressure data, via its attributes.
  • It’s important to note that Pygame has it’s (0,0) coordinate in the top-left corner of the screen, while the tablet has it in the bottom-left corner.  So the class does some hoop-jumping to convert the coordinates to Pygame.

The key takeaway is setting the Context.pktdata attribute:  This is the step that controls what is returned via the packets.  Depending on your tablet, a lot more info can be returned.

Bubblepaint v0.2.1 released

Find a list of all the goodness over on it’s page.

bubblePaint.0009

‘Uglyface bubbles’ made by my son :-)