Developing AAA Games with Stage3D @ Adobe AIR / Flash Player

Recently, I’ve been working on a larger game project which should run on the Adobe Flash and Adobe AIR platforms.

TL;DR – If you want to create 3D realtime games, use something different, don’t use Flash.

Because the preferred client technology was Flash anyway, we did some quick tests with some groups of meshes rotating around. The results were okay so after some additional tests, we gave the „OK“ to do it with Flash.

Development has started with Away3D 4.0 beta, at that time, Away3D had a lot of bugs and a lot of features were missing. Some of the bugs have been fixed by myself, others were reported and were fixed by the Away3D team.

Let me say that, although Away3D looked unfinished at that time and even nowadays lacks some features, in general, Away3D is not a bad engine and looks like it has been coded by people who know how to do it right.

But whatever improvement the Away3D team or me implemented, in the end we all had to cope with the poor Stage3D interface.

Textures

For standard textures, the size is limited to be power-of-two. If you work for mobile devices, you know for sure that you need to save memory wherever you can. POT-textures force you to insert empty areas into a texture which will eat up additional memory. As plenty of mobile devices accept NPOT-textures, this hard restriction doesn’t make sense.

You can create standard textures without mip maps. But even if you do not need them, Flash allocates the whole space for mipmaps on the GPU, always.

Recently, a new texture type became available, which is called „RectangleTexture“ (who can I blame for this name?) which supports NPOT-textures. Having this advantage now, the downside of RectangleTexture is: There is no mip map support at all.

Flash supports runtime texture compression. Not a bad thing, but this feature is not supported on mobile devices! Mobile devices badly need it while it is not so important for web, so why isn’t it available?

There is also an offline tool available, png2atf, but it takes several minutes for a single texture to be compressed.

Additionally, most of the time we cannot use them because they look so bad. At least when using alpha textures, the visual artifacts are unacceptable.

Performance

Rendering single objects with a lot of polygons works as expected, performance is good. No 3D api usually has problems rendering static meshes, so this is no surprise.

Things get worse when using more draw calls or if geometries need shader parameters. I haven’t seen any API that is slower here. Context3D.setProgramConstantsFromXXX are totally useless if you want to do something real, for example skeletal animation. Using those functions together with drawTriangles will eat up most of your precious CPU time. Not a big problem on desktop systems, but on iOS, you’ll notice how awfully slow the Context3D interface is here.

This is probably „by design“: While the GPU / DirectX / OpenGL work usually with 32 bit floating point data, Flash only supports Numbers, which are 64 bit float. So everything needs to be converted everytime you call these functions. And there is no way around it when you do for example skeletal animation.

I tried to use FlasCC to work around this problem, but guess what, there are no native calls to these functions where you can use C float data. You are forced to use ActionScript-Variants even there, so there is no win at all.

Shader Language

The language used by Adobe for shaders is called AGAL – Adobe Graphics Assembly Language.

Assembly? Yes, indeed. I’ve worked with D3D, OpenGL, NVidia Cg for 10+ years, they all offer high level shading languages. But with Adobe, you get ported back into the 1980s to fight for register usage, use mov, add, sub again. You don’t want to do that in 2014 anymore. Needles to say that it’s also quite limited in terms of available registers, number of opcodes etc.

ActionScript Language

If you create a 3D game, you need strong math classes. Unfortunately, ActionScript 3 is not the best language for this and the classes that are provided by the runtime lack a lot of features.

In ActionScript, Vector3D is not a value type but a full fledged class with all its advantages but also disadvantages.

There are only three static variables inside, one for each axis. A zero is missing. Due to the fact that all Vector3Ds are references, you can create ugly things if you don’t be careful. For example, take a look at the following code:

What actually happens here is that you invert the value Vector3D.X_AXIS because foo is only a reference. Looking to prank your coworkers? Just fool around with everyones coordinate system.

Missing operator overloading is also something that doesn’t really help to achieve code clarity.

It would be a lot easier to read:

When creating realtime applications, it is eligible to prevent any allocation at all. Unfortunately, because Vector3D is not a value type, flash doesn’t help here. Prevent use of

Because this allocates a new vector. Instead, use

This can be solved, but what if you would like to transform e.g. 10000 Vector3D objects by a Matrix3D? You’re lost. All transformation functions of the Matrix3D class return new Vector3D objects, there is no function to work on a Vector3D inplace. More Matrix3D functions act this way, for example decompose and even the position and rawData properties.

All this leads to a weak math performance of Flash in general.

More language issues are problematic, for example the lack of real inlining. The ASC2 compiler introduced an inlining feature that is so limited that it can be used only on very simple functions. It is not automatic, but must be inserted manually. If you overuse it, you’ll often end up with cryptic compilation errors like „stack underflow“. If you also use C++ sometimes, with „inlining support“ you for sure expect more than what Adobe has to offer here.

Ever tried to deploy a larger AIR app to iOS? Waiting more than 30 minutes caused us to use separate build machines to build iOS versions. They must be optimizing really hard, you may think. Would be nice if the performance would justify this, unfortunately, it doesn’t.

UI Support

With regards to Stage3D, there isn’t any that I’m aware of. There is Starling, but as long as you cannot use your UI that you designed in Flash Pro, it’s more or less useless. We had the idea to write a converter, but animated MovieClips are problematic because you won’t win any performance when rendering a MovieClip to a texture every frame. Or you’ll lose a lot of memory for sprite sheets that may become very large.

So UI with Stage2D is the current solution if you want to have a graphics artist to be able to design it.

Be warned, the 2D scanline renderer of Flash is awfully slow on mobile devices, if your artist really does a good job visually, you’ll probably end up spending days to optimize his number of display objects to something acceptable to reach at least 15 frames/sec.

Adobe decided to always render Stage2D above Stage3D. This may be useful in most cases, but imagine a 2D UI control that should display details of a 3D unit. You’ll start cuting holes into the 2D interface using masking which makes the 2D UI even slower.

Bugs

An incomplete list of some of the things that happen more or less on a daily base.

  • In Flash Pro, you better split a bigger UI into multiple SWCs and embed them so the artist can work without interrupting the coders. Randomly while compiling the main project, you’ll end up with „cannot convert foo to MovieClip“ while the Flash runtime constructs the display object hierarchy. Just re-publish in Flash Pro and pray to get it running.
  • iOS frame rate drops down heavily on every touch event because the AIR runtime searches for SimpleButton instances inside the whole display list. Adobe is aware of the issue but doesn’t fix it.
  • AIR deployment on iOS fails most of the time. Sometimes with an error message, sometimes not. Just try it again, sometimes it works. I switched to iFunBox (App/file manager for iOS devices) to prevent getting annoyed too often.
  • TextField.textWidth and TextField.textHeight may return wrong numbers if text fields use embedded fonts. Highly depends on the content.
  • Adobe Scout (realtime profiler from Adobe, part of the Adobe Gaming SDK or Creative Cloud) tracks less than 20% of the really used memory in a lot of cases. Additionally, „Other memory“ and „Other bitmap data“ do not really help identifying memory issues at all.
  • Some areas of the 2D UI are sometimes not redrawn. Doesn’t happen in all browsers and varies between different Flash player versions and also debug/release builds.
  • If you fail to set up your native extension properly, iOS version will hang in its splash screen without any useful info to debug what the problem is.

Tips & Tricks

  • Vector3D.length is slower than calculating it manually, both on Web & iOS, tested with AIR 4.0 / FP 12.
  • Vector3D.copyFrom() doesn’t copy the w component, remember this if you use Vector3D e.g. for colors
  • A static Vector3D to be used as temporary vector for calculations can be a huge speed improvement.
  • Throw away your BitmapData with dispose as soon as you uploaded your bitmap to a Texture to prevent doubled memory usage
  • To get rid of 2D/3D sorting problems, on desktop, Context3D.renderToBitmapData is fast enough to even reach 60 fps, but do not try this on mobile devices.
  • TheMiner is a good profiling tool that runs inside your Flash application.
  • Rendering a DisplayObject to a texture is costly, but reduces work on the 2D renderer and is usually a good caching solution.
  • null-out everything when you don’t need it anymore to reduce garbage collection cycles. Even remove weak event listeners.
  • Profiling Hint: Adobe Scout displays memory used by Vector.<int> and Vector.<Number> as „Other“, Vector.<Boolean> as „ActionScript objects“, Vector.<String> as both „Other“ (about 1/3) and „ActionScript Objects“ (about 2/3)

Car Radio: Android Head Unit review – Foryou Adayo AN6B01 / Nakamichi NMMC-1300 / OttoNavi K1 / Rydeen DV621 / HiTV iDroid 8000

Because I didn’t find much information about this unit on the net, I’m writing this review so others can have a look before buying.

Android Head Unit Picture

How I came to this head unit

Because I was bored by my Zenec ZE-NC3811D head unit for quite some time now, I wanted something with more features and a smoother interface and without all those tiny annoyances that the Zenec brought to me.

„Car Radio: Android Head Unit review — Foryou Adayo AN6B01 / Nakamichi NMMC-1300 / OttoNavi K1 / Rydeen DV621 / HiTV iDroid 8000“ weiterlesen

Wie gut ist Spotify Premium – Ein Test

Seit März ist Spotify nun auch in Deutschland verfügbar. Bei Spotify handelt es sich um einen Streaming-Dienst der es jedem Nutzer erlaubt, am PC kostenlos Musik zu hören. Finanziert wird das ganze durch Werbung oder optionale Gebühren von 5-10 EUR im Monat. Hat der Facebook-Zwang anfangs noch abgeschreckt, kann Spotify mittlerweile auch ohne Angst vor dem sozialen Netzwerk verwendet werden.

Schon seit Beginn war die Qualität subjektivem Empfinden nach völlig in Ordnung, die Auswahl ist groß und vor allem hielt sich die Werbung wirklich in Grenzen, mehr als bei einem normalen UKW-Sender war es sicherlich nicht.

Da ich häufig Musik höre war eine „Musikflatrate“ lange das, was ich gesucht habe. Als Vielfahrer habe ich mich schon seit Beginn immer mal wieder gefragt wie es denn wäre, Spotify auch im Auto nutzen zu können, irgendwie aber nie wirklich dazu durchringen können es auszuprobieren.

Ausgerechnet eine Werbung bei Spotify über die neue Android-App veranlasste mich dazu, mir die App dann doch mal auf einem Android-Gerät und einem iOS-Gerät zu installieren und den Test zu machen. Für 48 Stunden ist der Test nämlich kostenlos möglich, meiner Meinung nach ein wichtiges Detail, denn wer kauft schon gerne die Katze im Sack.

Die Android-App

Die Android-Variante habe ich zuerst getestet. Mit dem sofortigen Beginn des 48h-Tests sobald man sich mit seinem Handy zum ersten Mal bei Spotify anmeldet wird sich der eine oder andere sicher überrumpelt fühlen, so ging es mir jedenfalls. Denn eine Zeitspanne von 48h um Spotify auf dem Handy zu testen ist meiner Meinung nach etwas wenig, für berufstätige will die Startzeit da schon gut geplant sein um möglichst viel Testzeit zur Verfügung zu haben.

Die Android-App verhält sich im großen und ganzen so wie man es erwartet, man hat eine Liste seiner Playlisten und kann daraus Songs abspielen. Jede Playlist kann zum Herunterladen markiert werden. Schick: Das Herunterladen der Playlist läuft auch dann weiter wenn Spotify geschlossen wird, per Notification hat man den aktuellen Downloadstatus immer im Blick. Einstellmöglichkeiten gibt es nicht besonders viele, neben der Wahl der Streaming- und Downloadqualität (je Normal, Hoch, Extrem) lässt sich Spotify hier in den Offline-Modus zwingen, mit Facebook verbinden, auf lückenlose Wiedergabe mit oder ohne Crossfade einstellen und noch ein paar Kleinigkeiten. Schade: Der Ordner für die Downloads lässt sich nicht ändern, somit ist man gezwungen mit der von Spotify vorgegebenen Download-Location klar zu kommen. Der hier beschriebene Hinweis von Spotify selbst ist leider in der momentan aktuellen Android-Version der App nicht mehr möglich, warum dieses wichtige Feature entfernt wurde ist mir ein Rätsel. Insbesondere aufgrund des folgenden Bugs(?) wäre es hilfreich die Download-Location zu ändern: Wenn das Herunterladen einer Playlist abgeschaltet wird, wird bei mir der benutze Speicherplatz nicht wieder freigegeben (Spotify Version 0.5.1.15.g81977995). Ob der Speicherplatz nach einer gewissen Zeit doch wieder freigegeben wird, konnte ich bisher nicht testen, bisher bleibt der Speicherplatz jedenfalls blockiert.

Die iOS-App

Die iOS-App (getestet auf einem iPad) bringt logischerweise aufgrund des größeren Bildschirms deutlich mehr Informationen unter, die Funktionalität bleibt aber die gleiche. Etwas schade ist, das Spotify nach 10 Minuten Nichtbenutzung des Geräts aufhört, Playlisten zu syncronisieren. Der Grund ist mir nicht ganz klar. Bei einer großen Playlist und einer nicht ganz schnellen Internetverbindung ist es unter Umständen nötig, das Gerät regelmäßig zu entsperren um sicherzustellen, das auch alles syncronisiert wird. Wenn das Gerät sowieso schon zwanghaft per USB-Anschluss zur Syncronisierung gezwungen werden muss, wäre hier auch eine direkte Syncronisation zwischen PC und iOS hilfreich, dennoch lädt das Gerät alle Songs erneut aus dem Internet herunter, auch wenn sie bereits am PC lokal verfügbar sind.
Leider musste ich unter iOS das selbe Problem wie unter Android festellen: Playlisten die nicht mehr heruntergeladen werden sollen geben keinerlei Speicherplatz frei (Spotify Version 0.5.2.374.g2c5b1077).

Syncronisation zwischen Mobilgerät und PC

Befindet sich das Android-Gerät im selben WLAN-Netz wie der PC, erscheint es unter „Geräte“ auch in Spotify auf dem Computer. Von hier aus lassen sich bequem die Playlists zur Syncronisation auswählen, der Fortschritt ist jederzeit klar erkennbar und auch der auf dem Handy noch verfügbare Speicherplatz wird angezeigt. Leider erschien mein Handy nicht immer sofort in der Liste der Geräte, meist half aber ein Neustarten des Programms auf dem PC  und das Gerät war zu sehen. Unverständlich ist mir, warum eine Syncronisation für iOS-Geräte nur per Kabelverbindung möglich ist.

Spotify PremiumDas Spotify-Programm auf dem PC erschien Sekunden nach dem ersten Start der App auf dem Handy ebenfalls im Premium-Modus, die Werbebanner sind verschwunden und blendet man auch noch die Freundesleiste aus, hat man nur noch seine Playlisten sowie die Titelliste auf dem Schirm. Es wird keinerlei Werbung mehr angezeigt, auch nicht als Popup, ebenfalls ist der Musikgenuss nun komplett ungestört möglich.

Klangqualität

In der Premiumvariante bietet Spotify auch eine höhere Bitrate von bis zu 320kbit für die Musik. Laut Spotify sind noch nicht alle Songs in der hohen Bitrate verfügbar. Der verwendete Codec von Spotify ist Ogg Vorbis.

Klangqualität war mir schon immer sehr wichtig, daher wollte ich es genau wissen und habe mir ein paar Songs im Spektrogramm angesehen.

Anbei zwei Bilder des Songs „Mad About You“ von „Sting“ (Spotify: http://open.spotify.com/track/5rfIc5mdta7KLHCiPtrx4w)

Auf der linken Seite seht ihr ein Spektogramm des Songs in „normaler“ Qualität, auf der rechten Seite den selben Song in „premium“ Qualität. Es ist gut zu sehen, das die hohen Frequenzanteile  ab 16khz ganz im Gegensatz zu MP3 noch gut ausgeprägt vorliegen, die Premiumvariante hingegen beschert uns bei der offensichtlich von Spotify verwendeten Samplingrate von 44,1khz sogar Frequenzen bis zur Nyquist-Grenze von 22khz. Und falls Fragen aufkommen, ja darüber ist dann wirklich Schluss 🙂 In allen Songs die ich getestet habe waren keine Frequenzen mehr oberhalb von 22 khz zu sehen.

Verbindung zum Auto

Natürlich war mir wie bereits weiter oben erwähnt am wichtigsten, das Spotify auch im Auto klaglos seinen Dienst verrichtet.

Die Anbindung des Android-Handys über A2DP/Bluetooth Audio hat relativ problemlos funktioniert, so werden die Songs drahtlos zum Radio übertragen. Die Verbindung klappte nicht immer auf Anhieb, machmal war es nötig, Spotify nochmal zu schließen und neu zu öffnen, aber die Schuld gebe ich eher der Kombination aus Handy/Radio als Spotify selbst. Dankenswerterweise verfügen sowohl Handy als auch Radio über die optionale MP3-Fähigkeit für A2DP, so ist für die Transkodierung wenigstens ein anständiger Codec vorhanden und es muss nicht auf den SBC-Codec zurückgegriffen werden, der als einziger Codec für A2DP vorgeschrieben ist. Die Qualität ist fürs Autofahren durchaus in Ordnung, es sind auch bei leisen Passagen, bei denen man das Radio dann doch etwas lauter drehen muss (Beispiel: Albinoni, Tomaso [Composer] – Albinoni: Adagio for Strings and Organ in G minor) keinerlei Artefakte zu hören. Allerdings hat mich ein wenig verunsichert, das mir die Höhen etwas zu bissig vorkamen und ich diese sogar etwas runterregeln musste. Es wirkt so als wäre ein unschöner Equalizer auf dem Tonsignal.

Wer sich qualitativ absolut sicher sein möchte, sollte daher eher zu einem Gerät aus dem Hause Apple greifen, da Spotify an jeder iPod-Dockingstation auch kabelgebunden die Musik ausgeben kann und dann ohne erneute Transkodierung gestreamt wird. Hier kam mir der Klang insgesamt ausgewogener vor. Leider bietet Spotify aber nicht die Möglichkeiten, die man von einem iPod gewohnt ist, man kann also leider nicht am Navi Songs auswählen oder Playlisten durchsuchen. Ob das jetzt generell ein iOS-Problem ist weil nur iTunes gesteuert werden kann, oder ob Spotify noch nachbessern könnte, weiss ich leider nicht.

Bei beiden Geräten funktionierten aber zumindest die Vor/Zurück/Play/Pause Tasten, so das eine gewisse Kontrolle innerhalb einer zuvor ausgewählten Playlist gut möglich ist.

Nachteile  / Unschönheiten

Bei meinen Tests ist mir eine Kleinigkeit aufgefallen: Sobald man mit einem Account versucht, auf zwei Geräten gleichzeitig Musik abzuspielen, wird eines der Geräte gestoppt.  Auf dem Android-Handy gibt es hierzu nichtmal eine vernünftige Hinweisbox, es wird einfach die Ausgabe gestoppt ohne irgendeine weitere Information. Unter iOS gab es hierzu wenigstens einen Hinweis. Natürlich möchte Spotify damit Account-Sharing vermeiden, was ich verstehen kann, aber eine Grenze von z.B. drei Geräten wäre ja sicherlich auch möglich gewesen, zumal im Offline-Modus ja bereits drei Geräte benutzt werden können. Meine Frau kann somit zuhause keine Musik über das Internetradio hören während ich unterwegs- und nicht im Offline-Modus bin, sie bräuchte also einen eigenen Premium-Account. Es ist in diesem Fall auch nicht möglich, das  bereits spielende Gerät zum Stop zu zwingen. Falls jemand also mal vergessen sollte sein Spotify-Radio abzuschalten kann er unterwegs keine Musik mehr hören.

Mir ist zudem generell nicht ganz klar, warum die Unterstützung von anderen Geräten als PCs einen Premium-Account zwanghaft vorraussetzt, die Werbung könnte doch sicherlich auch auf anderen Geräten eingespielt werden.

Ein zweiter Punkt ist die nicht personalisierte Werbung in der kostenlosen Version. Es ist einfach etwas unschön wenn man sich gerade ein klassisches Requiem anhört und dann Werbung für ein neues HipHop-Album von Künstler X dazwischengeschoben bekommt.

Letztenendes bleibt es aber Jammern auf hohem Niveau. Wenn ich bedenke, das ich mir vor einem halben Jahr so einen Dienst nur habe träumen lasse, ist Spotify auch mit den kleineren Unschönheiten eine Bereicherung.

Fazit

Die Anbindung von Spotify ans Auto hat besser geklappt als ich erwartet hatte. Wenn ich bedenke, das ich in 48 Stunden mehr Songs gehört habe als ich für 10 EUR im Monat  bei z.B. Amazon im USB-kompatiblen MP3-Format kaufen könnte, ist der Preis wirklich angemessen und die Qualität definitiv erhaben.

Bis auf Kleinigkeiten macht Spotify zudem auf allen Geräten einen wirklich ausgereiften Eindruck. Für Leute die viel Musik hören lohnt sich die Premium-Variante sicherlich.

Ich kann jedem raten, Spotify zumindest einmal auszuprobieren, seitdem der Facebook-Zwang nicht mehr existiert sollten Datenschutzbedenken eigentlich kein Grund mehr sein. Mein Facebook-freier Account ist bisher von Freunden und „sozialen Tätigkeiten“ verschont geblieben und dient allein als Musikplayer. Ob sich die Premiumvariante lohnt, hängt einerseits von der Menge des Musikgenusses ab und zudem von den vorhandenen Geräten die Spotify unterstützen. Nicht jeder wird sich nur um Musik zu hören immer an den PC setzen wollen.