Wordy private beta

So wordy is out for private beta. Lets see if you guys find it meaningful or at least fun…

Important: please don’t link to the binary from this page

Beta reports

If you have something you can’t communicate via twitter (please don’t use email!), you can use the comment section on this page. Before you do however, please check the “known issues” section to save us all extra work.

Known issues

beta v0.1

  • The Swedish dictionary sucks (please recommend a better one instead of whining)
  • Virtual keyboard sometimes refuses to go away
  • No network gaming :(
  • Menus and buttons are ugly as hell

WP7 style busy indicator for MeeGo

As you might have noticed, both cuteBrain and AirControl try to mimic the WP7 user interface. This is mainly an experiment for me to see how far I can go with this idea (and when will the Ovi QA team draw the line Blinkar ).

Anyway, one component that the cuteBrain is currently missing is the WP7 style busy indicator (or ProgressBar as they for some reason call it), the original of which can be seen in the video below (the tiny dots on top at 0:40) :

 

The QML version

Thanks to @kypeli, we already have a QML version of this component here. Still, I wanted to create my own version and hopefully learn something in the process. After some late nigth hacking, I actually ended up with two versions:

Version 1

Both versions use the animation component to modify to X-value of the dots. The first version uses one such component per dot:

// note: tuned for a 360x630 display
import QtQuick 1.0

Item {
    id: work_
    property int size: 10
    property bool working: false
    property color color: "green"

    height: size
    visible: working

    Repeater {
        model: 5

        Rectangle {
            id: rect
            color: work_.color
            width: work_.size
            height: work_.size

            property int factor: work_.size * 1.75
            property int me: (index - 2.5) * factor
            property int x0: - factor * 3 - me
            property int x1: work_.width + factor * 3 - me

            SequentialAnimation {
                running: work_.working
                loops: Animation.Infinite
                PropertyAction { target: rect; property: "x"; value: - work_.size }  // invisible
                PauseAnimation { duration: 200 + 100 * index }
                NumberAnimation {
                    target: rect; property: "x"; from: x0; to: x1
                    duration: 3000
                    easing.type: Easing.OutInExpo
                }
                PauseAnimation { duration: 2000 - 100 * index }
            }
        }
    }
}

Version 2

The second version uses a single animation component and then uses the outcome to manually calculate position of each dot. This is probably less efficient than the first version (unless animation objects are heavy weight in QML, which I don’t think they are):

import QtQuick 1.0

Item {
    id: work_
    property int size: 10
    property bool working: false
    property color color: "green"
    height: size
    visible: working

    property real val_
    property int factor_: work_.size * 1.75
    property real mul_: factor_ / work_.width

    SequentialAnimation {
        running: work_.working
        loops: Animation.Infinite
        NumberAnimation {
            target: work_; property: "val_"; from: 0; to: 1
            duration: 5000
        }
        PauseAnimation { duration: 3000 }
    }

    function ease( t) { /* this is probably all wrong :(  */
        if(t > 0.5) t = 0.5 + (t - 0.5) * (t - 0.5) * 2;
        else if(t > 0) t = 2 * t * t;
        t = t * 4 - 1.5
        if(t > 1.0) return t - 0.5
        else if(t < 0.0) return t + 0.5
        else return 0.5;
    }

    Repeater {
        model: 5
        Rectangle {
            id: rect
            color: work_.color
            width: work_.size
            height: work_.size
            property int me: (2 - index) * factor_
            x: ease(work_.val_ - (2 - index) * mul_) * work_.width - me
        }
    }
}

As you can see, both versions are significantly shorter than kypeli’s original code.

Youtube or it never happened…

When run on PC, the results looks something like this (version 1 on top), which I admit is not very sexy but that wasn’t really the goal of this exercise:

 

Note that I have intentionally made the dots larger than they are on WP7. There are also some minor visual problems that I need to take care of…

My MeeGo projects [update 1]

A couple of months ago, Nokia send me and large number of other amateur/pro developers each a N950 on loan so we could do some serious MeeGo coding. So what do I have to show for so far? Well, not much at the moment but I have a couple of interesting projects in the pipeline…

 

The published stuff

These humble apps are what I have published on Ovi Store or on Nokia developers forums so far:

image image image image
SystemInfo SensorInfo CuteBrain AirControl
System information tool Sensor information tool Memory game Soundboard example
(and don’t you dare mention fart app!)

 

[update 1] Then I put together this measuring app in a few hours:

cutemeter2
cuteMeter
Simple digital ruler

 

I also did a quick and dirty mini-port of sdlcave to Harmattan, in case you missed that Ler

image
sdl cave
Old N900 game?

 

The current projects

These are projects on my current TODO list. Not all will be released of course. Note that the extremely ugly mock up graphics will be cleaned up if ever released Blinkar 

 

image image image image
MeeGoSweden app TågInfo Unnamed QML game “Pling”
Community app, probably will have to scrap this one :( Swedish real-time train information app Wait for it… Otomota clone and more

 

VemRingde: “Who is calling” Swedish app. I am currently stuck trying to figure out how I access phone and call log functions from Qt.

 

And then we have the library projects which take most of my time right now:

image image
SDL42 library Audio42 library
Simple scene-graph game engine on top of SDL Real-time audio synthesis library for N9

 

Then there are these projects, which I hope to finish as soon as the above libraries get stable enough:

What Use Notes
DrumPad Virtual drums real-time sound generation, multi touch
MPU Music “programming” audio “programming” app with its own powerful “audio CPU“
Thememin42 Theremin app more real-time noise…
SameSame Same Game clone Port from J2ME

 

The future projects

These are on my “maybe later” list. That is, what I would love to do but will probably never have the time for Ledsen

What Use Notes
LightSaber time waster real-time sound generation + sensors
Unnamed guitar app Play guitar real-time sound generation, multi touch, possibly using acceleration sensors
Brickade2 Lights off clone Port from J2ME
Unnamed game1 RTS mini game Probably a port of my Android game “Domi”
Unnamed game 2 Tower defense game  
Unnamed game 3 Hitori clone  
Unnamed game 4 Puzzle game Lets call it a Jewel-like puzzle game…

 

Well, that’s about it! Now, I would love to see what everyone else on #N950Club are doing with their phones.

Image manipulation with J2ME, part 5

Ok, this will be a very short post about addition of a single function to imagelib. But first, please note that Imagelib has moved to a new home: You can find the latest version of imagelib at Nokia Developer Forums (NDF). You are welcome to examine the source code, discuss it with others and even make changes.

Performance issues

Due to lack of GPU and/or slow virtual machines, J2ME phones are generally slow at drawing images on the screen. This usually leads to bad performance in, for example, games.

Images with transparent backgrounds are especially slow on J2ME phones that lack real GPUs. I have therefore added a simple function that removes the transparent pixels from images. This should hopefully lead to better performance:

Image ImageUtils.setBackground(Image src, int color)

I have also extended the imagelib demo with a performance test for transparent / opaque images. I used the following test image (which is actually the spritesheet from SameSame):

icons

On a Sony Ericsson W890 (unfortunately, the only working J2ME I have right now) I get the following numbers:

Original transparent image Opaque Image Opaque Image on GPU
drawing time for N images [ms]

260

85

85

 

While we are at it, lets also benchmark the difference between ImageUtils.moveToCPU() and ImageUtils.moveToGPU(). This is what I got on a 200×247 image on the same phone:

Original image [as returned by Image.createImage() ] Moved to CPU Moved to GPU
drawing time N images [ms]

1500

1500

1300

 

tl;dr summary

  1. If you don’t need transparent images, don’t use them as they are much slower than opaque images. To create an opaque image from a transparent one, use ImageUtils.setBackground()
  2. If you explicitly move your images to GPU, you will achieve slightly better drawing performance.

The new code has been committed to NDF repository. Have fun!

Leaderboards are (mostly) back online…

As you might have noticed, the leaderboards for SameSame, Brickade2 and my new MeGoo toy game “CuteBrain” have been down for a couple of days. After some heavy re-writing of the server code, they are now back online and should work without any problems [until the next time Google screws up]..

The Technical stuff

If you are interested in the technical details, please read on. If you are not, you can safely ignore the rest of this post.

 

Why the leaderboards stopped working

The leaderboards are organized as tables in a database running on Google’s cloud computing service, the App Engine. I pay nothing for these particular servers since the amount of computation needed for the leaderboards is (was) well below Google’s daily free quote.

However, a few weeks back Google changed they way they compute their free quota. With the new system, you would get up to 50.000 database fetches for free. Above that you would have to pay Google. While 50.000 may sound a lot, it is actually an extremely small number. In fact, due to Google’s very inefficient database implementation, it is barely enough to look up a single players position in the leaderboard:

SELECT COUNT(*) from samesame_table where score > your_score

Sine this table has around 60.000 entries, the database will have to iterate over 60.000 rows to compute your position. With the new quota system, one such lookup is already above your daily free quota.

 

How we fixed the leaderboard

With the new quota system, the leaderboards would have cost us around USD 3.000 / year to run. This is simply too much for a hobby project. Besides, you can buy and run your own server for much less.

A much cheaper solution was to re-write the leaderboard software to avoid the expensive database operations. This is exactly what we did:

Use Memcache instead of Datastore

To avoid the expensive database operations, we added the a caching mechanism where common queries are stored to avoid further database lookups. So Instead of always doing a database lookup like this

// SELECT COUNT(*) from samesame_table where score > your_score
PersistenceManager pm = ...
Query q = pm.newQuery(SameSame.class, “this.score > score”);
q.setResult(“COUNT(*)”);
q.declareParameters(“Long score”);
Object count = q.executeWithArray(your_score);

We would do something like this

import com.google.appengine.api.memcache.*;
...
MemcahceService service = MemcacheServiceFactory.getMemcacheService();
Object count = service.get(“your_position_” + your_score); // is it already cached?

if(count == null) {
    PersistenceManager pm = …
    Query q = pm.newQuery(SameSame.class, “this.score > score”);
    q.setResult(“COUNT(*)”);
    q.declareParameters(“Long score”);
    Object count = q.executeWithArray(your_score);

    service.put(“your_position_” + your_score, count); // save it for later use
}

Limit Datastore use even further

With the Memcache, once the caches are filled the number of database accesses will decrease significantly. Our next problem was that since the free quota was set so extremely low, it was not even enough for a single database query. Hence we could never get as far as filling the cache with data.

A small hack we used to get past this was to limit the query size to a subset of the database. Since the rows are fetched in batches of 100, we limited the query size to 99:

Query q = pm.newQuery(SameSame.class, “this.score > score”);
q.setRange(0, 99);
...

While this is not always correct, it was the only way to get thing working. With this hack in place, we can now (barely)run the servers within the free quota Ler

 

Cleanup your database!

We have also added a daily cron job which cleans the database by removing the lowest ranking entries. This will hopefully shrink the SameSame table a bit since there are a number of total n00b scores in there Blinkar

 

Client side changes

A new client app will be introduced soon, which will refuse to submit your score to leaderboard if your score is very low or if it has not increased since the last update.

 

Lessons learned

If there is anything to be learned from all this is that you should never trust your cloud provider. They can screw up and they can screw up badly, and they have no problems charging your credit card for their mistakes.

The leaderboards are down

Sorry everyone, all leaderboards (and some other on-line functions) are currently down. The problem is not at your end. It is not even at my end. It is at Google’s who once again has screwed up badly.

 

Google?

Yes, the leaderboards run on Googles cloud computing service, which they call App Engine.

To make a *very* long story short, Google is changing their payment system and their latest changes seem to have broken something in their quota system because they claim that the very first leaderboard access that one of you guys made today has filled my entire quota for 24 hours:

gapps_crap

 

Until Google resolves this problem the leaderboards are disabled.

RIP dmr

/*
 * This is a tribute to Dennis Ritchie (aka dmr),
 * creator of UNIX and C, who passed away this week.
 */
#include < stdio.h >

int main(void)
{
    printf("Hello, Heaven!!\n");
    return(0);
}

A friendly remainder to SameSame players around the world…

I am very happy that people are still playing SameSame. And to show you my appreciation I have added the global scoreboard and a lot of new levels lately.

I am however a little annoyed by the amount of SPAM on the scoreboard. Please do not use an URL as your player-id. If you do that, your score will be removed. The server has a function to detect and remove all such spam, it can even blacklist your IP. If I see more spam, I will have to turn on the anti-spam function.

Thank you in advance,
AV

SystemInfo, a simple MeeGo utility

I have had my N950 for exactly two weeks and despite being on vacation and all that I already have a number of interesting projects going on for it :)

Let publish our first MeeGo app

Just to test the waters I wrote and published a very simple app called “SystemInfo”, which is a simple utility app for showing various types of informations about your new shiny MeeGo device :) I sent the binaries to Nokia for publishing and got it accepted after about 48 hours.

My N950 just got its Store software activated and when I logged in I noticed my little app right on the front page:

Store page with my SensorInfo app
Sample app screenshot

Where to get it

When I have more time, I will write more about the whole experience. For now you can find the app source code (C++ and QML) on the Nokia developers site (GPPLv3) and the binaries on the Nokia Ovi Store.

Power of QML: here is a minimal twitter app [updated]

Few days ago, I received a Nokia N950 developer phone from Nokia (thanks guys!). This is what I found on the box:



The N950 is a prototype/developer device for those who want to write apps for Meego/Maemo/Harmattan/Qt and the upcoming Nokia N9. The text on the box is a QML application for twitter. You can run this code on the phone, but you can also run the code on PC:

“I just launched my #n950 #NokiaDevkit”

If you write in your username and password and press “Send to twitter” [but make sure you read the security warning on the end of this post first] , you will see this appearing on your twitter account:



“I’ve just unboxed my #NokiaN950 Developer Device”

The code snippet is of course there to show developers the power of QML. I have played a little with QML since I got the phone and while things are still at beta state, I have to admit that QML is very powerful. It is also extremly simple to integrate QML and C++.

Security warning!!

In order to keep the code simple, Nokia has moved out the twitter API logic to their own web server. When you press “Send to twitter”, the app will actually send your username/password to a server in Finland (not nokia.com) which will take care of the rest. Are you comfortable with sending your twitter credentials to an unknown server, in plain?

If not, I suggest you do as I did: change your password to something stupid, send the tweet and then change back to your real password.

Next Page »

Switch to our mobile site