Empathy And Other Miniature Pygame Hacks

January 30th 19:01
by why

You know, you don’t have to finish a game or a project for it to be worth it. Before you throw all the time into writing your own protocols and scrabbling together a client/server and doing all the art… why not do something primitive to get your act together?

That’s not a stunning monologue or anything. It’s just an introductory paragraph and segue into this series of experimental games done by JP LeBreton. His experiments are short. Nice and digestable. I really like this one pictured above called Empathy.


To bring it up on Ubuntu:

 $ apt-get install pygame subversion
 $ svn checkout http://vectorpoem.googlecode.com/svn/trunk/ vectorpoem
 $ cd vectorpoem/empathy
 $ PYTHONPATH=../shared python empathy.py

~300 lines. Move the mouse around. Spacebar to reset. Escape to quit.


Of special interest is how concise and nicely commented the code is where he builds the polygon shape outlining the lighted area.

 def update(self):
   # clear list from last frame
   self.points = []
   x, y = 0, 0
   angle = 0
   for i in range(LIGHT_CIRCLE_VERTICES):
     # determine circle edge point
     angle += math.radians(360.0 / LIGHT_CIRCLE_VERTICES)
     x = self.loc.x + math.cos(angle) * self.radius
     y = self.loc.y + math.sin(angle) * self.radius
     end = Vector2D(x, y)
     # trace to edge point
     trace = tile.Trace(self.loc, end, world)
     if trace.hit is False:
       self.points.append(end)
     else:
       self.points.append(trace.hit_loc)
       # add a point along edge of hit tile for proper "shadow" shape
       # turn angle into a normal
       angle_vec = Vector2D(math.sin(angle), math.cos(angle))
       # next point in direction of that normal is the correct one?
       next = trace.hit_tile.nearest_point(trace.hit_loc, angle_vec, trace.hit_line)
       self.points.append(next)
   self.polygon = Polygon(self.points) 

See think about this: the tile.Trace method determines if there are any walls in the way. Knowing that, can you see how the trace object is used to cut off light at the wall?

Now begin the comments …

18 comments

ehird

said on January 30th 13:17

Y’know, even the hyper-compact game libs have always seemed verbose to me. I mean, it’s such a perverse step up from console utilities. It doesn’t feel fun any more.

_why

said on January 30th 13:31

I know I know. “Concise” might be a stretch. But I’m torn. Do things need to be dumbed down or do we need to evolve? Things are probably due for change. The ideals of Julien Léonard still strike me as a good way to go.

ehird

said on January 30th 16:22

I think a lot of the blame lies in the languages. They’re so suited to sequential I/O&execution that making them do fancier stuff gets kludgy.

A language designed to escape this could be interesting.

andy

said on January 30th 17:06

like a functional language?

ehird

said on January 30th 17:40

andy: Solves the execution side, not the I/O side. (Scheme just does it in the regular way, and Haskell just makes the ordering explicit.)

JP

said on January 30th 21:38

Wow, thanks for the look – wasn’t expecting people to try and run this stuff!

“Y’know, even the hyper-compact game libs have always seemed verbose to me.”

Anything verbose – like Vector2D, trace, tile – is probably my own code, and I’m still relatively new to programming. Almost nothing in that sample calls PyGame, the module I’m using to draw graphics, get input etc.

ehird

said on January 31st 10:40

JP: I wasn’t referring to your code as much as pygame :) I really like Empathy!

omouse

said on January 31st 12:34

time to evolve. you can’t expect everything to be doable in less than 100 lines. it’s time to start looking at the Smalltalk way of managing code, where code is relatively small and you don’t see the code of a whole class at once. check out the browser in Squeak to see what I’m talking about.

ehird

said on January 31st 15:18
you can’t expect everything to be doable in less than 100 lines.

Well, I can… There are environments which produce compact, readable code in their niches, but unifying them all proves nontrivial.

You’d think it’d be pretty easy.

failrate

said on January 31st 17:09

I’m finding some success using generators. Like, right now I’m making a little point and click game that uses a set of finite state machines. The programming in AS3 is simple, but verbose. I was going to use Ragel for the FSM , but even that seemed like too much gun. So, I just wrote a little language spec and a compiler that turns my little language into the complete AS3 code (lines of code I would never want to hand-type, y’know).

Granted, the little language has few applications outside of this project, but DSLs don’t have to be generic languages. The extra information I would normally have to supply to a full language are supplied by he context of the project and code generator. Which means, a more concise language. LISP programmers generally do the same thing with macros. First, they write the macros to write their program, then they write the program :)

omouse

said on January 31st 22:22

I just found a suitable quote from Ted Nelson, ‘The problem is not software “friendliness.” It is conceptual clarity. A globe does not say “good morning.” It is simple and clear, not friendly.’

ehird, this is what you want. Clarity in concept and you want it all to work in a cohesive, unified way. 1000 lines isn’t painful when it functions well and the flow can be found easily or you have a tool that can organize it into small chunks for you (again, take a look at how Squeak does this with classes and their methods).

ehird

said on February 1st 09:33

> I just found a suitable quote from Ted Nelson, ‘The problem is not software “friendliness.” It is conceptual clarity. A globe does not say “good morning.” It is simple and clear, not friendly.’

I don’t feel that that quote is particularly relevant (and don’t put much stock in Ted Nelson).

> ehird, this is what you want. Clarity in concept and you want it all to work in a cohesive, unified way. 1000 lines isn’t painful when it functions well and the flow can be found easily or you have a tool that can organize it into small chunks for you (again, take a look at how Squeak does this with classes and their methods).

I’m not sure we’re thinking along the same track. I’m complaining about the paradigms that most languages today use – they’re not built for things that aren’t sequential.

koning_robot

said on February 2nd 05:14

I think ehird wants stuff like this to be more declarative: instead of having to update the screen every once in a while, it’d be less clunky if you could just declare a bunch of constraints and let the “framework” figure out how and when to update what.

See the SICP chapter (or even just its introduction) on this. See also declarative programming on Wikipedia.

_why

said on February 2nd 10:18

The further abstracted you are from the actual math and detailed concepts, the more control you lose. Like, in this case, JP needs to come down into trigonometric functions in order to mess with circles. That’s just the reality of it. His polygon is inherently complex. Look at the image: it can have twenty or thirty sides, some curved and some at sharp angles. All have to be built from the triangles inside a circle. That’s trig.

This example is going to be awfully hard to abstract. Even if you were able to boil up some kind of an language that could cut down JP’s code, I’d wager that the language would have to be designed with JP’s specific experiment in mind. And you can’t anticipate all of JP’s future experiments. Either you give him all the primitives he needs or you end up limiting his experiments.

I think JP’s doing good. I mean if he really is “relatively new to programming” then that’s a bit of proof that Pygame is actually a rather good medium.

failrate

said on February 3rd 01:17

PyGame is definitely a great dev environment, especially when compared to an environment like Panda3d. Panda has a great feature set, but does annoying things like having gigantically long method names and lots of boilerplate initialization steps. Of course, you could just go in and write a better interface, but that’s time and effort that should be going into making your game or art project.

j`ey

said on February 3rd 05:06

“scrabbling together a client/server and doing all the art… why not do something primitive to get your act together”
whistles

gymbrall

said on February 21st 23:23

_why said:
“This example is going to be awfully hard to abstract. Even if you were able to boil up some kind of an language that could cut down JP’s code, I’d wager that the language would have to be designed with JP’s specific experiment in mind. And you can’t anticipate all of JP’s future experiments. Either you give him all the primitives he needs or you end up limiting his experiments.”

Half the people who come to your blog either don’t understand this or don’t believe it. They think general and specific aren’t really mutually exclusive and that 1,000,000 monkeys typing at a keyboard really will eventually produce the complete works of Shakespeare.

koning_robot

said on March 2nd 08:46

Don’t jump to conclusions gymbrall. First, a million monkeys will indeed produce the complete works of Shakespeare eventually. How you can deny this is beyond me. (Unless you’re being realistic, in which case “eventually” means something else entirely and it becomes highly unlikely. In reality, getting a million monkeys to type on keyboards is highly unlikely to begin with.)

Second, yes, general and specific are mutually exclusive. That’s why well-designed systems will provide multiple levels of abstraction so that you can pick and choose the appropriate level for each task.

JP’s experiment is kinda sorta like ray-tracing and it wouldn’t surprise me if people have treated it as such before. All you really care about is where each ray ends. The rest is noise.

I’m not saying it’s appropriate here or that I’d be capable of abstracting this well; just that it’s conceivably a useful way to model what’s going on here. If properly done, such an abstraction wouldn’t limit you any more than Arrays and Hashes limit the way you work with scalars.

Comments are closed for this entry.