 I've written a few games in pygame, but never quite finished them. Generally because the complexity of adding user interactivity for things outside the essential game play. While pygame is a sweet sprite library, it has no widget toolkit, so things like collection a string from the user, having menus, etc... are all incredibly tedious to program. Adding something like a high score screen is as much effort as game programming itself.
I've written a few games in pygame, but never quite finished them. Generally because the complexity of adding user interactivity for things outside the essential game play. While pygame is a sweet sprite library, it has no widget toolkit, so things like collection a string from the user, having menus, etc... are all incredibly tedious to program. Adding something like a high score screen is as much effort as game programming itself.
Pygtk, however, has a rich widget toolkit, but it's hard to use it from within a pygame app. This is difficult in part because Gtk needs a gtk.main loop, but a typical pygame app is using it's own loop with clock.tick(). As a result, there are threads locking each other out, and generally craziness ensues.
But, it turns out, you can embed a pygame surface within a pygtk app, and it's actually pretty easy. So you can use just the one gtk.main loop, all interupt programming, access to the whole Gtk toolkit, and also all the easy loading of images, playing of sounds, collision detection, and other sprite functionality of pygame. It's really the best of all possible worlds.
I wrote a minimal demo script to show how to do this. The "game" is just a single sprite that you can move with the keyboard. You can see the screen in the screenshot at the top of this post that there is a gtk menu being activated!
I didn't intend this to be a tutorail on pygame, but rather integrating pygame in pygtk, so all the "game" does is let you move a sprite around.
It's probably easiest to look at the whole script, but let me point out some of the steps involved. I'll assume that you've already set up a gtk.Window with your menus and such. So, the first step is to set up a gtk.DrawingArea that will become the pygame surface. It's normal code to add it to your window:
      da = gtk.DrawingArea()
    da.set_size_request(300,300)
    da.show()
    vbox.pack_end(da)
    da.connect("realize",self._realized)
def _realized(self, widget, data=None):
    os.putenv('SDL_WINDOWID', str(widget.window.xid))   
    pygame.init()
    pygame.display.set_mode((300, 300), 0, 0)
    self.screen = pygame.display.get_surface()
    gobject.timeout_add(200, self.draw)
In a real game, you'd probably put an "update" function on the timeout to do things like check for collisions, random events, and etc... (You'd also probably use a much smaller time out period than 200 milliseconds). However, our game only has one sprite, and it doesn't do anything but move so we don't need that functionality. But how do we tell it move? In pygame, every time through the main loop you pull all the events off the event stack. With pygtk, you use signals to handle the input when it occurs.
To do this, in the __init__ function for the window, we set up our pygame objects, and then connect to the key-press signal:
      #set up the pygame objects
    self.image = pygame.image.load("sprite.png")
    self.background = pygame.image.load("background.png")
    self.x = 150
    self.y = 150
    #collect key press events
    self.connect("key-press-event", self.key_pressed)
def key_pressed(self, widget, event, data=None):
    if event.keyval == 65361:
        self.x -= 5
    elif event.keyval == 65362:
        self.y -= 5
    elif event.keyval == 65363:
        self.x += 5
    elif event.keyval == 65364:
        self.y += 5
def draw(self):
    self.screen.blit(self.background,[0,0])
    rect = self.image.get_rect()
    rect.x = self.x
    rect.y = self.y
    self.screen.blit(self.image, rect)
    pygame.display.flip()
    return True
 
 
 
I have been using this method in my own games (PyGTK + PyGame), unfortunately it doesn't work with GObject introspection-based python GTK apps, as the XID of the drawables can not be retrieved anymore, as the get_xid() method is not introspectable.
ReplyDeleteVery great and kind information and beautiful blog post thanks for sharing
ReplyDeleteclipping path service
Glad to know some new thing here. Thank you so much for sharing with us
ReplyDeleteclipping path
clipping path service/Raster To vector
this is epson printer error code 0xea and epson error code 0xea
ReplyDeletethis is epson printer error code 0xf3 & epson error code 0xf3
ReplyDeletethis is epson printer error code 00041 and epson error code 00041 as well as Epson Error Code 1073
ReplyDeletethis is epson printer error code 0x9a and epson error code 0x9a wf-3640 as well as epson code 0x9a
ReplyDelete
ReplyDeletethis is brother printer error code 30 and brother printer error 30
this is brother printer error code CC4-205 and brother error code CC4-205 and also brother printer error CC4-205
this is brother printer error code 32 and brother printer error 32 and at last brother printer 32 error
this is brother printer error code 50 and brother printer error 50