I'm developing a real-time rogue-like game during my spare time, using Python and libtcod, to learn programming (and have some fun). I would like to create some sort of mouse-friendly GUI, just like in Goblin Camp.

This game is 90% mouse-driven, with menus, scrollbars, buttons etc. As a total noob with graphical interfaces, I just can't figure out how to do this. Example: How to display the name of a monster when the cursor is over it? I tried some ways, which more or less worked, but were always awful, impossible to maintain, hard to scale, and resource-consuming.

Is there a "simple" way to have something more like an object.OnClick() ?

  • \$\begingroup\$ I'm not sure how to answer your question, but your english is quite good. I've seen much worse (sometimes from native speakers!) \$\endgroup\$ – thedaian Jul 6 '11 at 14:25
  • \$\begingroup\$ Is the problem related to the fact that you have to display text in a limited space? Or is a problem of how to organize the software so you can code entities that can react to mouse events in general? \$\endgroup\$ – FxIII Jul 6 '11 at 14:47
  • \$\begingroup\$ Organization problem. When I click on that (ascii) mob, or that button, I don't want to cycle through all objects to figure out which one is under my mouse. I want the object to tell me "you clicked on me!" \$\endgroup\$ – Simon Cambier Jul 6 '11 at 15:14

If you simply need to do an Object.onSomething() probably you need to write a reactor over a object data model.

What I mean? Put every relevant objects into a container make this container available to everyone. This container will implement the method

def castEvent(self, eventName, args, kargs):

In this method you iterate the containing object looking for the method "does%s" % eventName. something like:

for item in self.items:
    f = getattr(item, "does%s" % eventName, lambda *x, **k : False)

if f evaluates True using the parameters passed to the function then you call the "do%s"%eventName with the same parameters:

for item in self.items:
    f = getattr(item, "does%s" % eventName, lambda *x, **k : False)
    if f(*args, **kargs):
        f = getattr(item, "do%s" % eventName, lambda *x, **k : False)
        f(*args, **kargs)   

Every time you need to send an event - say Click - you simply need to:


every object interested in Clicks has to provide a

def doesClick(self, x, y):

that manage the click events returning False or

def doesClick(self, x, y):
def doClick(self, x, y):

The first returning whether (x,y) hits the object and the second doing the click routine.

You can implement the first in a generic superclass and let the clickable classes to extend.

This is a very basic implementation whit a lot of room for improvements.

| improve this answer | |
  • \$\begingroup\$ Thank you! That wasn't exactly what I was looking for, but its a really better written system than the one I tried. I guess I've still a lot to learn in Python... \$\endgroup\$ – Simon Cambier Jul 7 '11 at 4:04
  • \$\begingroup\$ @simcamb have you troubles with the integrationton? \$\endgroup\$ – FxIII Jul 7 '11 at 9:32
  • \$\begingroup\$ @Fxll I'm working on it right now, I understand how it works, but I don't get the use of lambda (I only know it works like a "one line function") in *args. \$\endgroup\$ – Simon Cambier Jul 7 '11 at 9:39
  • \$\begingroup\$ If a method does not exist for item, getattr(item,"method",x) returns x. In this case x is a function with a generic signature that returns false. \$\endgroup\$ – FxIII Jul 7 '11 at 9:51
  • \$\begingroup\$ @Fxll Right, that was obvious. I didn't read it right, thanks again. \$\endgroup\$ – Simon Cambier Jul 7 '11 at 10:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.