Tales from the debugging land

February 21, 2010

Here’s a funny bug I wanted to share with you (where “you” means all audience with bare minimum C++ understanding). I’ve been working today to add a putter interface to Kolf 2. (Attention: There are three Kolfs at the moment. I did previously explain why.) After fixing one or two crashes and fighting against Qt’s partly abstruse event forwarding (why do I have to setAcceptHoverEvents() in order to get mouseMoveEvent()s?!?), everything worked as it should, though there was one problem left: A mouse move event needed around 1 second to be processed. Callgrind to the rescue!

clear-priorities

Okay, I admit that I had not expected the result to be so very clear. Let’s have a look at that method then:


void Kolf::SimplePutter::updateAppearance()
{
  if (!m_activeView)
    m_lineItem->hide();
  else
  {
    m_lineItem->show();
    //calculate line
    QPointF lineEnd = m_cursorPosition;
    for (int i = 0; i < m_direction; ++i)
      rotateBy90Degrees(lineEnd);
    //update line
    m_lineItem->setLine(QLineF(QPointF(), lineEnd));
  }
}

Looks quite compact, doesn’t it? Hm, rotateBy90Degrees is called multiple times, perhaps that’s the bottleneck:

void rotateBy90Degrees(QPointF& p)
{
  qreal x = p.x();
  p.rx() = p.y();
  p.ry() = -x;
}

Doesn’t look like it could be any more efficient. But even if it was unefficient, m_direction always has a value smaller than four, because everything else is nonsense. Anyway, let’s have a look at what value is in m_direction:

qDebug() << m_direction; //just before the for loop
//output:
135552768
135552768
135552768
135552768
135552768
135552768
135552768

A quick look in the constructor… Bah, I hate you, C++! Not only do you initialize int member variables with random values, but you also initialize them with random values that are always dividable by four so I don’t notice!

Advertisements

The semester is nearly finished; Tuesday is the last exam (on quantum field theory). So finally I have some time for hacking. In the last few months, aside from some personal stuff, hacking almost exclusively meant Palapeli for me. I’m currently working on the design of the next version of Palapeli (with GHNS and puzzle piles, if everything works out), but that’s not what I’m hacking on right now.

In Kolf 2, I’ve decided some time ago to abandon the third spatial dimension and completely return to the classic Kolf feeling. This big change means exchanging the Open Dynamics Engine by a 2D physics engine. There seems to be only one good 2D physics engine around, Box2D. Incidentally, Box2D switched to CMake just two weeks ago.

After only some hours, I had some first prototypes of how I could implement the current Kolf-NG on top of Box2D. In order to get a clean design, I chose not to rewrite Kolf-NG from ODE to Box2D, but to create a complete new Kolf, with big parts of code being adapted from Kolf-NG. Now there are three Kolfs in KDE’s SVN:

  • trunk/KDE/kdegames/kolf: quite stable and shipping, home-grown 2D physics engine
  • trunk/playground/games/kolf-ng quite unstable, external 3D physics engine
  • trunk/playground/games/kolf2 mostly just a testcase at the moment, external 2D physics engine

Now probably you want to build and try Kolf 2 (read: the testcase which will become Kolf 2 at some point). This is quite tricky, because the CMake-based Box2D has not yet had a stable release, so you’ll have to checkout the development version from this SVN url. Even worse, you have to apply this patch against the SVN checkout to have Kolf 2 find the installed Box2D library. Even worse, you’ll need to apply the following patch against the Kolf 2 checkout to have the test-case work properly. (I did not commit this because I usually forget to remove such stuff again.)

diff --git a/kolf2/base/scene.cpp b/kolf2/base/scene.cpp
index db7fa83..c68ce8d 100644
--- a/kolf2/base/scene.cpp
+++ b/kolf2/base/scene.cpp
@@ -30,7 +30,7 @@ static const int MillisecondsPerStep = 1000.0 * SecondsPerStep;

 Kolf::Scene::Scene(QObject* parent)
        : QGraphicsScene(parent)
-       , m_world(new b2World(b2Vec2(0, 0), true)) //parameters: no gravity, objects are allowed to sleep
+       , m_world(new b2World(b2Vec2(0, -100), true)) //parameters: no gravity, objects are allowed to sleep
        , m_objectFactory(new Kolf::ObjectFactory(this, m_world))
        , m_simulationTimerId(startTimer(MillisecondsPerStep))
 {

And even then, you will only see two colliding rectangles. I hope to get the gameplay and course loading working as in Kolf-NG by the end of next week (modulo the terrain). Still, the door is open to great features such as Kolf 1 compatibility.

Kolf: Call for help

January 9, 2010

The other day, Aaron wrote about the quest of "identifying projects in need". This reminded me that I have one project that it is in need: Kolf 2. About one year ago, I’ve put on myself the burden to rewrite KDE SC’s only sports game. I had big aims, 3D support (besides the classical 2D mode) being the most prominent one.

Over the course of the last year, quite some progress has been made on physics simulation, the implementation of 3D terrain, and a course editor interface. Some nice structures are in place, but big parts are still missing. Also, a weak spot in the design have been identified: It is not possible to allow 2D and 3D views at once. Period. For example, a 2D view does not represent any notion of height, which is important to determine the reachability of certain points of a map.

With real-life workload on one side and Palapeli’s feature request list on the other side, not much time is left for Kolf. This is a call for help: Are you a Qt/KDE developer, and would you like to help Kolf reach the next level of pure awesomeness? The following problems are waiting for fresh minds to be solved:

  • Remove the 3D stuff (this should get you familiar with the codebase), and exchange the 3D physics engine by a 2D one.
  • Finish the terrain drawing tool.
  • Finish the other parts of the course editor (like: adding/removing objects, creating new courses).
  • Write new object types.
  • Find a better solution for the user interface building. (The current Kolf::GameUI has been written at a time when my knowledge of how to properly use the XMLGUI framework was quite limited.)

If you’re interested, find the source code here. My mail address can be found in there, do not hesitate to approach me with any questions you have. I can comment on any design choices and review new designs you might come up with (using my experiences from previous Kolf development).

What’s a clear sign of craziness? Scheduling a project to be finished in two weeks, and then completely rewriting it.

Long story short Short story long: I’ve noticed that I’ve (effectively) only seven to eight days left until university courses start again. This is not enough time to get Kolf 2 into a state that allows us to release it. The editor is (from a user’s perspective) nearly useless (though many important foundations have been laid), the terrain has weird collision bugs (I hoped that these problems stop with usage of an external physics engine *sigh*), we’re lacking good textures and of course courses (pun intended).

So, we’ve (more or less) decided to not release Kolf 2.0 with KDE 4.4. I’m not sure about when Kolf 2.0 will first appear. We might do some preview releases before the KDE 4.5 alpha/beta cycle starts, but that has not been decided yet.

Instead, I’m doing something that could be achieved in seven to eight days of intense work. Some months ago, I wrote libpala, a new library as a foundation for Palapeli (my jigsaw puzzle game). Unfortunately, libpala is so different from the old libpalapelibase that I effectively have to rewrite the whole game. Still, this task is much easier than getting Kolf 2 ready, and I’m confident to get everything finished in time to get Palapeli included in KDE 4.4.

Here’s your chance to help KDE: I need some quick opinions on the design of a widget, for which I’ve made a mockup.

Basic situation: Kolf needs a new configuration interface for its texture blender. The task of this texture blender is to create a texture for a given heightmap. It uses several base textures and inserts these base textures into the result at different height ranges. For example, low heights might be painted with a water texture, medium heights with a grass texture, and high heights with some stone texture. That’s what the interface looks like currently:

Current state of the texture blender (click to enlarge)

Current state of the texture blender (click to enlarge)

On the left side is a list of all base textures. Each base texture has three values (out of a range from 0 to 255, where 0 is the lowest height level, and 255 is the highest one). The left and right value are the minimum and maximum height where this base texture is used. The middle value is the height where the base texture is inserted in the texture in a completely unaltered manner. (I call this “median height” from now on. Above and below this height, the texture is darkened and lightened to create a depth impression.) Everyone here should agree that this configuration interface is completely obscure (would you have guessed that you have to click on the textures to edit these heights?) and much too techy.

Gladly, one of our artists has proposed a new interface, and I have made a simple mockup (only for the left side, the texture preview at the right which will stay there):

Mockup for the new texture blender (click to enlarge)

Mockup for the new texture blender (click to enlarge)

This design is based on a layered “stack” of base textures (at the left). The higher a base texture is in this stack, the higher are the heights at which this base texture is used. One can drag the textures along the vertical axis to re-order them. The right side is the actual height range selection. The first, third and fifth marker stand for the aforementioned median heights, while the second and fourth marker denote the area where one texture is gradually replaced by the next one.

One special note: The textures on the left axis are not on the same height as the median markers on the right axis. This is intentional because this restriction might cause texture images on the left axis to overlap, which is something which I want to avoid.

Here is my RFC: What do you like and dislike this mockup? Do you have further ideas on how I can improve this interface? How should user interaction be implemented? I have some basic ideas for the last point, but am eager to hear your ideas and do not want to bias you. Apart from the obvious mouse interaction (i.e., dragging the base textures to reorder them, and dragging the markers to change the height ranges), the user needs to be able to add new base textures, and delete base textures from the stack. Also, keyboard control might be good for accessibility and convenience.

Many of you may already have dealt with property editors. These are generic widgets that display properties of some object, and allow to edit them. I’ll also have to do one of these property editors for Kolf as an addition to the already available graphical interface, which can only be used to edit geometrical properties, not behavioral ones.

Of course, I want to reuse existing code to get Kolf ready soon, so I had a look around for other property editors. Below is a selection from what I found. The first one is the widget property editor of Qt Designer, the second one is used in Step (a physics simulator from kdeedu) to display and edit the physical properties of some body, and the third one is from Rocs (a graph-editing application which Tomaz Canabrava is working on).

propertydialogs-qtdesigner

propertydialogs-step

propertydialogs-rocs

As you can see, each of those editors looks (and probably also behaves) differently. This indicates that there is no library-based generic property editor. This is the first RFC: Am I wrong? Is there a generic property editor widget somewhere in Qt or kdelibs? And before I forget it, here’s the second RFC: Are there any other property editors which I’ve forgotten, and which might be worth to look at?

Now that the option of using a library-based property editor is out, it seems like I have to create one. And this means that more investigation about the pros and cons of the existing property editors is needed.

Let’s begin with the last picture. It is actually a detail from a screenshot that Tomaz published in a blog entry yesterday. In the same post, he indicated that this interface is “less than ok, it’s really ugly.” It’s easy to see that Rocs’s property editor is the odd one out in the above gallery. While the other dialogs use a single list/tree view to display all properties, the Rocs dialog uses widgets arranged in something that looks similar to a QFormLayout (though it also has a list view for something called “dynamic properties”).

Let’s move on: Step’s dialog is plain and simple. After my fancy, the structure is not totally clear because it contains too less lines. Step’s dialog also has something which only a physical simulation program needs: units. (Not visible in the screenshot: The unit disappears while editing the value.) In these two regards, the Designer dialog is the complete opposite: It uses colors and lines very extensively, can group properties (although only by class, not by type), can also add dynamic properties (the green plus button at the top), has sorting and filtering, and uses a tree model for complex properties. Qt shows off what can be done with its generic frameworks.

From these three samples, the Designer dialog is closest to what I want to have. I’m not sure whether the coloring is compatible with our HIG, and I don’t know whether it is possible to easily add support for own data types (which Kolf uses plenty of, because Qt’s geometry data structures cannot be applied to a 3D space). I haven’t had time yet to read into the code for these property editors.

Last but not least, the third RFC: Is anyone here interested to collaborate with me on a generic property editor dialog for KDE applications? I have the following requirements:

  • It has to read and write QObject’s meta properties, which requires it to cope with QVariant values and such correctly.
  • I need to be able to add support for new data types inside an application that uses this dialog, preferably in a very straight-forward manner.
  • Optionally, I would like to be able to group properties by type (e.g. “shape”, “position”, and “behavior” for Kolf objects).

Of course, this list can be extended to meet your requirements if you want to use this property dialog in one of your applications. If you’re interested, please get in touch with me. You should be able to find my mail address easily (e.g. in the license headers or in the about box of kdiamond, palapeli or kolf-ng).

Over the last weeks, I’ve put together a new tiny component framework for Kolf, which degrades the main window to a kind of interface server where games insert their UI components. Today, I was finally able to kill all the old components and port everything to the new system. This is not exciting because it does not show off yet, but here’s something screenshot-friendly: I’ve killed the “New game” dialog and built a “New game” widget instead:

The new "New game" widget

As you see, all interface in Kolf is now concentrated in the mighty tab widget in the center (with the only exception being dock widgets). If a game is currently in progress, the “New game” widget also opens as a tab, allowing you to continue to play your game if you decide not to start a new game.