30 March 2006

It runs on steam!

We've been quite busy with PyWeek. This time, the voted theme is "It runs on steam!", so we are doing a side scroller with a steam powered flying machine. The goal is to navigate the rickety air craft from one side of the level to the other, while avoiding a multitude of obstacles and enemies. It's past the halfway point of the competition already, and there' still much to be done. Hopefully I'll have enough free time to code everything in.

26 March 2006

Week of Unproductiveness

I've had a nasty flu for the last week or so, and unfortunately I haven't gotten much done. PyWeek started last night with the theme "It run on steam!", so that'll occupy all of my time next week. Hopefully my fever goes down enough that I'll be able to concentrate on the competition.

I'm sorry for the lack of updates, I'll make a proper post after I have some more energy.

15 March 2006

Opioid2D Status Update

I've been quiet for a few days, so here's a brief feature checklist on how Opioid2D is coming together.
  • Rendering engine: 100% done.
  • Scene engine: 85% done. Still missing state transitions and a couple of callbacks, but otherwise all the important functionality from pygext has been translated.
  • Sprite engine: 90% done. Nothing fancy here, so it has been straightforward to re-implement. Added very basic physics on top of the pygext API (velocity, acceleration, friction).
  • Action system: 60% done. The base classes need some more tuning, and then I'll get to work on implementing all the different actions from pygext.
  • Event handling: 90% done. Needs support for multiple states.
  • Keyboard handling: 95% done. Needs testing and might require some small tweaks.
  • Mouse handling: 10% done. Barely started with this, but should be a quick job.
  • Collision detection: Not started yet, but I'm going to start implementing this tonight. The plan is to start with simple radius-based collision detection (as in pygext) and then expand it to (convex-) polygonal collision nodes and add optional multi-sampling for fast moving entities.
  • Particle engine: Not started yet, but should be very straightforward to translate from pygext's implementation.
  • Large sprite support: Not started yet. Sprites are currently constrained to a maximum size of 512x512 by the rendering engine.
  • Camera system and scrolling: Not started yet.
  • GUI framework: Not started yet.
I'd like to get the first release out within two weeks, but I'm afraid PyWeek will interfere with the schedule somewhat. So, a more realistic release date for the first public beta of Opioid2D might be in the middle of April.

11 March 2006

First Benchmarks!

While these are very rough and preliminary benchmarks, I'm very happy with the results so far. I'll the pain I've suffered with C++ seems to have paid off. ;) This is a simple sprite benchmark that has static sprites with no logic or movement. It's purpose is to test the raw output of the rendering pipeline. 85fps is the limit, as the renderer is synced to vertical refresh.

sprites 1000 5000 10000 15000
pygext ~35fps ~7fps ~3fps ~2fps
pygext + psyco ~60fps ~13fps ~6fps ~4fps
Opioid2D 85fps 85fps ~70fps ~45fps

EDIT: To be fair, the difference isn't all C++ vs. Python related. Opioid2D uses smarter algorithms in the rendering engine, which help a lot too.

09 March 2006

Object Identity Crisis

Opioid2D has progressed pretty nicely, and I now have working C++ code for displaying an O2D-sprite on screen via a Python API. While writing the sprite test, I came upon a very unfortunate "feature" of SWIG that I wasn't aware of before. As this was the first time I've really used SWIG, I wasn't really sure how the class wrapping mechanism works. It turns out that SWIG creates a "shadow" object in Python, which has a pointer to the live C++ object and the problem is that, as far as I know, SWIG doesn't do any tracking between the two, so once the C++ object is passed to the framework machinery, it pretty much becomes detached from its Python twin.

I have a cunning theory on how to solve this pretty transparently, but this will slow down development somewhat until I can design and implement a working solution. I guess I could go read on the Python extension API and write my own wrappers in C, but that seems a bit daunting at this point, compared to the relative ease that SWIG has provided. We'll see...

07 March 2006

Goals of the Pygext Rewrite

The rewrite of pygext will change enough things, that I thought renaming might be appropriate to lessen confusion (especially since the original Python-pygext will stay around and updated for a good while still). The new working title for the framework is Opioid2D (or the Opioid2D Game Engine), abbreviated O2D.

  1. Speed. As I wrote in my last post, performance is one of the most essential things in a game framework. The general guideline in O2D is that all the code that gets called at every screen update should be on the C++ side. Using C++ also allows the rendering pipeline to contain more logic without adding overhead, so O2D will have better texture packing, and sprites will be rendered in batches using OpenGL arrays.
  2. Maintainability. On the other hand, everything that is NOT speed critical should be written in Python instead of C++, for easier debugging, fixing and extending. The O2D implementation will have three tiers: The core written in C++, a SWIG wrapper exposing the core API to Python and a very-high-level Python API that calls the wrapper.
  3. Minimalistic High Level API. The pygext API was huge and cluttered with things you rarely need. The O2D high level API will concentrate on the bare essentials, which leads to the next point.
  4. Better Documentation. When I started developing pygext, it was supposed to be for my own use only. While it's slowly starting to have an adequate level of documents, the messy and large API makes writing documentation a pain. The O2D API is being documented constantly as I write it, and being much leaner, having good documentation coverage takes a lot less work.
  5. Smaller Footprint. O2D aims to have all calls to SDL and OpenGL inside the C++ core, so I can drop all dependencies to Pygame, PyOpenGL and Numeric. This is done mainly to reduce the size of standalone executable distributions of games made with O2D.

On Performance

Having spent a lot of time with Python in the last couple of years, I've often come across the claim that while Python is not nearly as fast as C, it is, more often than not, fast enough. I agree that this is generally true, and I was gladly surprised on how far I could go with pygext using pure (psyco-accelerated) Python for everything (of course, pygame and pyopengl called SDL and OpenGL in the background).

Games are a pretty different kind of beast when it comes to optimization, and a somewhat generic game framework even more so. They can never really be "fast enough". There are two main goals that improving the framework performance attains: 1) You can put more stuff on the screen. More enemies, more particles, more background layers OR 2) Your game will have lesser system requirements, allowing you to reach a wider audience.

That is the line of thought that convinced me to try and rewrite the core of pygext using C++ instead of Python. I'm only a few days in, but things are progressing pretty nicely so far. I'll post some benchmarks as soon as all basic funtionality has been re-implemented.

05 March 2006

Of Python and C++

I did some experimenting today with both Boost.Python and SWIG, and SWIG will be the wrapper of choice, at least for now. Boost might be better for some things, but the whole installation and configuration step was a huge hassle and ultimately I didn't get it to work properly on my setup. SWIG on the other was usable right away, and after a brief read through the basic documentation, I had a working version of my C++ extension.

Python has proved to be an excellent prototyping tool for the C++ extension. I'm currently developing the extension in tandem with a pure Python version so that, whenever I'm about to implement a new class, I add it to the pure Python version first and test it. This way I can verify all architectural and algorithmical ideas before writing them in C++. I'm also writing the prototype in "C++ style" so that each dynamically created object has .new() and .delete() methods (and my tests track memory allocation issues), and I use 'this' instead of 'self' etc. This makes writing the C++ code based on the Python prototype very straightforward and fast. So, even though I'm pretty much writing all the code twice, I think I'm still making faster progress compared to trying to write the whole thing directly in C++.

04 March 2006

Boost.Python vs. SWIG

I found this comparison between Boost and SWIG an interesting read. Although, it is a couple of years old, so I don't how relevant it is with new versions of but Boost and SWIG. Pretty much all the links I found from Google were pretty old, so I guess I'll just have to try both of them myself. The general consensus seems to be that Boost has more features and is often more convenient, but when problems come up, they are much more difficult to debug compared to SWIG.

A Short Introduction

Opioid was the moniker chosen for our team in the first PyWeek competition and since then we've continued using the name and gathered a couple of additional friends to the bunch. We currently have a couple of open source game projects under way, which we hope will provide us with enough team working experience and proper tools so that we can start looking at some more "serious" game development (probably portal games at first).

On the tools side, our current focus in on Python, using pygame, pyopengl and pygext. Prototyping is on the way to add C++ to the mix too.

As for the current events, three Opioid members (including me) are currently taking part in the shmup dev horizontal scroller competition, and later this month, the full team will take part in PyWeek #2.

I'll add some info about our current open source game projects in future posts. Stay tuned!