Thursday, December 31, 2009

CMake and Git

This week the Intensity Engine has undergone a minor 'reboot': I moved it from SCons to CMake, and from bazaar+Launchpad to git+GitHub. The reasons are as follows.

SCons is a really cool tool, especially for Python lovers like me, but CMake's ability to produce 'native' project files and makefiles is quite important. Basically, on Windows it is easier to make proper builds and installers if you use a Visual C++ project file, as opposed to SCons. I wasn't fully aware of this when I started the Intensity Engine a year and a half ago (being a Linux guy). Also, this will help on OS X, as CMake can produce Xcode project files. So, it made sense to move to CMake.

Moving from bazaar to git was for related reasons. While bazaar works well in my experience, on both Linux and Windows, more than one person has told me it is very problematic for them on OS X. So, since working on OS X is very important to us, and also since in general people seem to prefer git, the switch was done. Basically, I prefer bazaar, but my personal preference isn't enough of a reason to stick with it. Anyhow, after finishing the move, I admit it is nice how fast git is, and GitHub has some nice features as well.

So, the overall goal with these changes is to allow more people to more easily use and contribute to the Intensity Engine. The project is growing, in both lines of code and users, and it makes sense to use the best tools for the most people.

For people currently compiling from source, the COMPILE.txt file explains how to get the source using git and compile it using CMake. If you have any trouble, as usual feel free to ask for help on IRC (#syntensity on FreeNode) or on the forum page.

Thursday, December 24, 2009

Slower Languages for Faster Code

This post is both an update on performance improvements in the engine, and a general comment about how slower languages can lead to faster code, in a somewhat ironic way.

So, the next game (codename 'swarm') has really pushed the Intensity Engine to new limits: the map is huge, both in terms of raw size (4096 cube units on each side, so imagine something like 500x500x500 meters), geometry (the compressed binary octree is 1.1MB), entities (about 1,000 of them), and includes several new gameplay elements (new bot types, new plot triggers and items, etc.).

So, it initially ran very slowly, which was not really surprising. At first glance, this could lead someone to speculate that the engine, with its approach of doing as much as possible in a script language - JavaScript on Google V8 - simply isn't a good idea. After all, Cube 2, the engine we are a mod of, is written entirely in C++ (well, with cubescript in a very, very minor role), and therefore our engine should be much slower than where we started from. So didn't we just make things slower, needlessly?

First of all, that isn't an apples-to-apples comparison, simply because Cube 2 can't run the new gameplay elements that we have. But more importantly to the current topic, if you did mod Cube 2 to run the new gameplay elements, it would almost certainly run this map more slowly. That seems strange at first, but it really isn't. The reason is that, while code-for-code JavaScript is slower than C++ (even with the best JavaScript engines like V8), using JavaScript lets you implement optimizations that don't make sense in C++.

For example, if you have a fixed engine written in C++, you can of course tune it quite a lot, but there are additional things you can do if each map/game/level can customize things through scripts. For example, the swarm map has a lot of mapmodels, and the profiling tool reported that they were in fact a significant factor in slowing down the frame rate. Since the code that renders them is a script, I was able to easily customize it to run faster, by applying some heuristics that work well in this map (like certain ways of deciding when not to render a mapmodel). Those tricks might not work well in other maps, but that is exactly the beauty of a secure scripting language - each map can have its own scripts, downloaded on demand with the map. Also, I customized how physics for collision checks and so forth is done, and various other things.

Basically, you don't want to download a whole new engine for each map. But that is what modding the C++ code would require. With a script language, on the other hand, you can code a lot of optimizations and distribute them with the map, in an easy way. So you end up being able to optimize a lot more.

(There is another factor here, of lesser importance, but also worth mentioning: It is also simply easier to write those optimizations in a script language than C++, because script languages are faster to code with.)

Of course, C++ has its place - the core engine has to be written in C++. Even Java or C# wouldn't be possible, because while being slower by a factor of 2 is fine for 95% of applications, that is not the case with game engines. Half the frame rate is not acceptable! But on top of a 'core' C++ engine, I believe it really makes sense to integrate a script language, as we do, and not just because it lets you run more types of games, but also for performance.

Anyhow, to get back to the swarm game, at this point performance is good: On my not-powerful-at-all machine I get 60fps in the slower areas, dropping perhaps to 50fps with a lot of action. But in most of the map the frame rate is actually much higher. So, the optimization phase is almost over. What is left is to write the scripts for the final boss battle, and then to do a lot of playtesting and tweaking of the gameplay.

Friday, December 18, 2009

Adding Plot Elements

I made a small video to demonstrate how plot elements are added to Syntensity games:

Plot elements are things like doors that need to be opened somehow, or platforms that appear so you can cross otherwise impassable areas. They are typically used in single-player games like Doom. Note that in Syntensity they function in multiplayer mode as well (there is no 'singleplayer mode' or 'multiplayer mode' in Syntensity - all games are always multiplayer-ready. But you can also play them locally with just one player, if you want).

As the video shows, when in edit mode you can see some visualization hints, like effects connecting doors and platforms to the triggers that activate them. The visualization hints show both what is connected to what and in what direction.

There are some other features of plot elements not shown in the video:
  • You can have multiple triggers for a door or a platform, so the player(s) need to trigger them all before it opens.
  • A trigger can also be defined to hold an item. In that case, to open the thing it is connected to, the player must reach the trigger, at which point they get the item, and then they must bring it to the right place.

Wednesday, December 16, 2009

Community Update: Ubuntu Lobby

One of our community members, TheAncientGoat, has been working on a nice Ubuntu-themed map:

Besides looking cool, the map includes some web pages, of the Ubuntu homepage etc. (for which you need to enable the experimental web browser plugin). With the web pages updating live, it can be a nice way to keep up to date on Ubuntu news for people inside Syntensity.

Definitely an interesting project to watch.

Friday, December 4, 2009

Media Plugins

I've been working on media plugins recently, here are short videos of the results:

That is the VLC media player, playing on a surface inside a Syntensity map. Note that sound works, but I didn't record it for this video.

And this video shows embedded web browser windows that you can interact with. The plugin for that might be useful for other projects, so I spun it off as a separate project, Qtonium. The name is inspired by Awesomium and Berkelium, two projects doing similar things.

As to why a new project and not to use Awesomium or Berkelium: Awesomium is apparently going closed-source, or at least that is the only way I can interpret their taking down the code and mentioning 'new licensing terms coming soon'. Berkelium is open source, but it is unclear if it is functional or useful outside of Sirikata, the project in which it is being developed and used.

And in any case, both are based on the approach of taking Chromium and hacking it to work in an embedded manner. In Qtonium I took a very different approach: No C++ at all, and no hacking of a massive and rapidly-changing codebase. Instead, PyQt is used in a straightforward manner, that is, Qtonium is written in Python. It's dependencies are Qt and PyQt.

The only downsides I can see to the Qtonium approach are:
  • Qt WebKit isn't a complete browser, just a 'widget'. For example, when embedding Chromium as a whole, you get plugins (Flash, etc.), caching, various default behaviors (handling page load errors, etc. etc.). That stuff is obviously useful, so this is a clear downside. But the cost (hacking Chromium) is also very high in my opinion. In any case, over time those things can be implemented in Qtonium if people want.
  • Qtonium doesn't share Chromium's separate process security model. This is true at the moment, but it would actually be very simple to adopt, due to Qtonium being written in Python, and Python 2.6's improved support for handing separate processes. In fact if you look at the code, how to do this becomes quite obvious.

Note that this is part of the approach of having all plugins be Python modules. Those modules can of course load C++ code if they need to (like Qtonium loads Qt through PyQt), so this isn't a limitation, but actually the hope is that a lot of things can be done with pure Python (including ctypes). That way, plugins don't need to be compiled, and it's generally very easy to make them work on multiple platforms. C++ plugin systems tend to be much more complex to work with.