in KDE, Graphics View, Graphics Items, Graphics, Kinetic, Performance
on Tuesday, October 27, 2009 @ 08:59
Do you know the main advantage of a Hummer? It can go pretty much everywhere, that’s why many armies are using it. If I talk about a Hummer it is because QGraphicsView can go pretty much everywhere too. Recently I was lucky enough to get a N900 (generously given by Jesper, don’t know for how long though) so I decided to test Qt on it. I mainly work on QGraphicsView here at Qt Development Frameworks so it was a way to test the speed of my toy (:p). Since I’ve also been a KDE user and developer for quite a bit, I thought I could try KDE on it and more precisely Plasma.
So I downloaded the Maemo 5 SDK and started building KDE and Qt with it.
First thing you have to know is that scratchbox is not easy to set-up because you always face problems and compiling inside scratchbox is really slow. The link step is a bit broken and you have to specify manually where are the libs you link with (apparently it’s expected to be like that). It seems odd… Anyways, after a couple of hours I had Qt 4.6 (Fremantle branch) up and running. I was quite happy to see that it performs well (if you are using the right things). Animated tiles are running smoothly and painting demos as well (using opengl es2 graphicssystem).
After this initial success I tried KDE. This was more painful than I originally thought. Broken packages (mysql-server), out-dated packages (shared-mime-info for instance) and the worst : CMake crashed during the configure step. I solved that by downloading the 2.8 RC version that I built myself. But after a couple of hours of fighting and debugging I got this:
As you can see Plasma is running fine on this device. Of course a lot of work is needed to make it “finger” enabled (the actual applet handles are not really appropriate) but it’s a good start and Plasma is flexible enough to allow that. I have created a separate “shell” called plasma-mobile (Plasma already has the desktop and netbook shell) and I pushed that on the KDE playground. It also needs a lot of work to integrate well with the device (battery, network, profiles and so on) but the goal is to invite people to contribute to Plasma in order to offer a real alternative to the hildon-desktop. Plasma already has many many features/applets that we can just use on the N900. This also comes with a global effort to bring KDE technologies to the device as Kevin said in his blog. You can also participate in discussions on the KDE mailing-list for Maemo.
So yes Plasma is also a hummer, it runs everywhere but it’s the luxury version.
If you’ve checked out the Qt solution for the Animation API, then you’ve probably found the game called Sub-Attaq. This game was an idea I had when I started working on the Kinetic project. The idea came from a game I played 6-7 years ago but i don’t remember its name anymore. For those who don’t know, it’s a simple 2D game where you control a boat and you can drop bombs on submarines.
Anyway, the goal of this game was first to play with it, and at the end to get a high score rank for the office (competition is always good). Oops, I forgot the obvious reason : testing our API for animations. So I started writing a basic game but I was busy with 4.5.0… so I let this game as it was, just some basic game logic and couple of animations.
But some months ago, a new state machine framework popped in the Kinetic repository. I have to admit that Kent convinced me when he introduced me the framework and I had participated in some API reviews to give him feedback. Then an idea came in my mind, why not use it in Sub-Attaq? The context of this game matched well with state-charts, so why not… Then I started thinking and drawing the state chart for the whole game on my white board. After some hours of drawing and erasing, I finally managed to have a complete state chart.
I first decided to design the welcome screen (made by Andreas) and the game logic. Here is the diagram :
Then I refined the game part with this diagram that show the losing, winning, pausing and playing states:
Of course here it is pretty basic, no levels, no points management. It will come later but we have to start with something.
The next step was to create the behavior of submarines, they basically move from one edge to another and they have a return animation. Here is the chart :
We have bombs and torpedoes too. It is pretty basic. When they are launched, if they don’t hit anything, then the execution is finished. If they hit we destroy the target and finish.
The last item is the boat. It is a bit more complex because user can control it with keys, it can move right and left, and drop bombs. It has three speeds and user can decrease the speed by pressing the opposite key of the current direction and increase it by pressing the key of the current direction. Here is the boat chart :
After some drawing i ended up implementing that in Sub-Attaq. The implementation was a success, I killed lots of code, simplified the whole code base and made the code very clean. It allows you to quickly understand all behaviors by just reading the definition of all state-machines. So let’s take some examples with a classic before/after.
* Pausing the game : Before i had a boolean in my scene that i was setting to true when user was pressed P and when P was pressed again i was setting it to false and restarted all animations. I was connected to this key press action and the slot looked like this:
Now, I have defined a pause state and a play state with two transitions (that check the P key) from pause to play and play back to pause.
/*We have one view, it receive the key press event*/
QKeyEventTransition *pressPplay = new QKeyEventTransition(scene->views().at(0),QEvent::KeyPress,Qt::Key_P);
QKeyEventTransition *pressPpause = new QKeyEventTransition(scene->views().at(0),QEvent::KeyPress,Qt::Key_P);
/*Pause "P" is triggered, the player pause the game*/
playState->addTransition(pressPplay, pauseState);
/*To get back playing when the game has been paused*/
pauseState->addTransition(pressPpause, playState);
* Submarines : Before, I had to connect the submarine to the moving animation’s finished signal in order to launch the rotation animation. And after, I had to connect the rotation animation finished signal to an another slot that would run the moving animation again when the rotation was finished.
Now here is the state machine for the submarine :
/*This state is when the boat is moving/rotating*/
QState *moving = new QState(machine->rootState());
/*This state is when the boat is moving from left to right and right to left*/
MovementState *movement = new MovementState(this,moving);
/*This state is when the boat is rotating*/
ReturnState *rotation = new ReturnState(this,moving);
/*This is the initial state of the moving root state*/
moving->setInitialState(movement);
/*This is the initial state of the machine*/
machine->setInitialState(moving);
/*End*/
QFinalState *final = new QFinalState(machine->rootState());
/*If the moving animation is finished we move to the return state*/
movement->addFinishedTransition(rotation);
/*If the return animation is finished we move to the moving state*/
rotation->addFinishedTransition(movement);
/*### Add a nice animation when the submarine is destroyed*/
moving->addTransition(this, SIGNAL(subMarineDestroyed()),final);
The code when we enter in MovementState (which is a QAnimationState) is like this :
Then the animation will be played, and when it is finished, the machine will enter the rotation/return state. Isn’t it easier to read?
To conclude, I can say that if you can use the state machine approach in your project, DO IT! The code is much more clean, well defined and more readable, and avoids spaghetti code. It makes it easier to thinking of all states before coding.
For Sub-Attaq, the next step is to implement different levels, a score logic and a top ten highscore. I would like to add animations (e.g. explosions) but I need some graphics to achieve it and (cough cough) I am pretty bad at that. And I would like to have different kinds of submarines too.
I am actually in Porto (Portugal) for the Tokamak version 2.0. Tokamak is a developer meeting for the PlasmaKDE project. I arrived Friday and the first day was talks, people explaining on what they are working on for KDE 4.3. There will have some awesome features that make Plasma the best desktop ever. From my side i gave a talk about Qt Kinetic to introduce them the project. The first feedback i had was that this project is warmly welcome, and miss to plasma developers (and i guess to others). I introduced the Qt State machine framework, the Qt Animation API and talked about improvements in QGraphicsView. I had nice feedback from people and they were pretty happy about the API. I wrote all their remarks on a paper to work on them with other trolls. I have already implemented some of them inside my local copy of Qt Kinetic :D. The team is now waiting a Qt Solution in order to “kineticize” Plasma.
I have cooked a small demo showing Plasma running Qt Kinetic :
You can see an animation on the opacity during switching pictures and an another to display one day meta data behind the picture.
Here is the code for the opacity animation : QPropertyAnimation *opacityAnimation = new QPropertyAnimation(this,"opacity");
opacityAnimation->setEndValue(0.);
opacityAnimation->setDuration(1000);
opacityAnimation->start();
By the way Qt 4.5 RC is now in qt-copy and KDE trunk use it. After talking with all people here the switch is apparently nice. I have asked to all people to give a mark from 1 to 10 (ten is best) based to their user/developer experience. The average is 8 which is nice. According to Aaron Seigo the switch in Plasma was “pretty smooth” and Leo Franchi from Amarok said “it seems faster with raster graphic system”. Marco Martin added “QGraphicsLayouts start to work”. There are still some small problems with SVGs rendering in Plasma but i will sit down with Marco to fix them. It is encouraging for the final release and we will have now KDE folks reporting bugs they still have with 4.5 to make this release the best as we can.
How do you animate a widget in Qt 4? Let’s start with a bit of history….
- Qt 4.0 : QTimer provides a low level timer.
- Qt 4.2 : QTimeLine provides a duration, looping, easing and basic states
- Qt 4.2 : QGraphicsItemAnimation which is built on top of QTimeLine.
We realized that these classes were not convenient enough for doing highly animated user interfaces, so we decided to write yet another world dominating framework for animating widgets :-). After a lot of research, prototyping, API discussions and rewrites we have finally something that will dominate the world.
Initially it was our intention to release the animation framework for 4.5. Unfortunately we felt it was not ready for 4.5, so we decided to postpone it in order to give it some more love. We feel that we are getting closer now, but as a service to people that have been waiting for this we have decided to release it as a Qt Solution. We also have a secret, scrupulous plan B with this: we want you guys to give feedback (qt-solutions@trolltech.com) on it so we can improve it even more :-). It is available under the normal Qt Solution conditions, either commercial or GPL.
For you gaming enthusiasts we have made a full blown world dominating game: