knuspermagier.de

Ein L und zwei P. Philipp!

SwiftUI, die Tausendste

Es war WWDC und wie jedes Jahr verspürte ich kurz den Drang, was mit Swift zu machen. Normalerweise wird das immer sofort im Keim erstickt, weil ich immer etwas mit den ganze neuen Funktionen machen will, aber das würde bedeuten, ich müsste Betas installieren und könnte das Endprodukt erst im September auf meinem iPhone benutzen. Das schreckt mich normalerweise immer ganz gut ab.

Das gute daran ist allerdings, dass man, wenn man so mal ein paar Jahre skippt, irgendwann doch anfangen kann, etwas zu bauen und zwar einfach mit den Features aus den letzten Jahren. Ich glaube, mein letzter SwiftUI-Versuch scheiterte zum Beispiel daran, dass es keinen TextEditor gab und nur ein TextField, oder so. Gibts mittlerweile, toll.

Ich habe mich also mal kurz wieder in ein paar Tutorials begeben und versucht eine, alle werden es ahnen, App für meine Tagebuch-Webapp zu bauen, auch wenn ich mit der Webapp eigentlich zufrieden bin, aber warum was neues bauen, wenn man einfach das gleiche immer wieder machen kann.

screenshot-2022-06-08-at-23.20.24.png

Jedenfalls läuft es erstaunlich gut. Ich finde Swift allerdings wirklich sehr ekelig. Also alles so wie immer, irgendwie. Ich wünschte, jemand hätte sich überlegt, mal eine leichte und verständliche Sprache zu entwickeln, statt diesem Monster, das vor Syntax-Sugar und unverständlichen konstrukten nur so trieft. Naja.

Schauen wir mal, wie lange ich motiviert bleibe. Mein Hauptproblem gerade ist, dass ich die Webapp ja nun auf klassische Art und Weise baute, halt mit serverseitig gerenderten HTML-Views und ohne fertige REST-API. Tja. Wie ist da nun die best practise herangehensweise, wenn man doch beides braucht? Ich werde es wohl herausfinden müssen, oder einfach alles copy pasten, ist ja auch egal, hauptsache es funktioniert.

img_5498.jpeg

Seitdem es wieder Mehl gibt, verspüre ich den Drang zu backen. Gerade angesagt: Foccacia. Muss aber noch üben.

img_5451_444.jpeg

Pizza, mit Spargel! Gute Idee.

20220608-082155-pwa-1106.jpg

Ab und zu was neues im Pokédex – ein Grünfink.

Was machen eigentlich (1)

Ab und zu, meist spät in der Nacht, fällt mir ein, dass ich ab und zu ein paar obskure Schrei-Bands höre und ich frage mich, was die eigentlich in der letzten Zeit so gemacht haben. Ich sollte mir da mal eine Liste anlegen, oder sie einfach bei Spotify verfolgen.

Marathonmann

Fangen wir an mit Marathonmann. Zuerst fällt mir eine neue Single mit Sperling und Kind Kaputt ins Auge. Catcht mich nicht so richtig, dafür lerne ich aber Kind Kaputt kennen.

Abgesehen davon haben sie anscheinend ein Akustikalbum veröffentlicht, was mit ja eigentlich gefallen sollte, denn ich liebe Akustik-Versionen von Rocksongs. Leider wird hier, soweit ich das bisher mitbekam, nicht mehr geschrieen und damit geht der USP der Band komplett verloren. Schade.

Die Band mit dem wilden Gitarristen von Adam Angst

Wie hießen die gleich noch? Ich brauche etwas um das zu ermitteln und finde auf dem Weg dieses tolle Cover von Junge von Adam Angst. Nach wenigen weiteren Videos komm ich drauf: FJØRT. Leider haben sie nichts groß neues vorzuweisen. Nur eine kleine Corona-Session.

8kids

Ich fand einen relativ neuen Live-Auftritt und musste feststellen, dass ihre Drummerin gegen einen Mann ausgetauscht wurde. Außerdem gibt es keinen Bassisten, was ist denn hier los. Nach dem Samsas Traum-Konzert von letztens schon wieder eine Band ohne Bassisten!

Objects in the Rear View Mirror

Folgende Spannende Geschichte:

Ganz davon abgesehen finde ich es ganz grandios einen Song mit einem so langen Titel und einer Länge von mehr als zehn Minuten zu veröffentlichen.

Hi! Spencer
Jahresabschlusskonzert 2019 →

Ein schönes Live-Konzert von Hi! Spencer. Kann man gucken!

Kartoffeln in Stäbe schnibbeln, knapp 10 Minuten mit einem Löffel Essig im Wasser kochen; mehlen, salzen, ölen und dann 30 Minuten in den Ofen. Ich finde das Video von Pro Home Cooks dazu nicht mehr, es hat meine Selfmade-Pommes revolutioniert. Sehr lecker!

Der Bann ist gebrochen

Dereinst, als ich mal studierte im verwunschenen Winter-Wonderland Furtwangen im Schwarzwald, spielte ich ab und zu mit meinen Kommilitonen Daniel und Fabian, viele Grüße an dieser Stelle, ein uraltes Spiel: Tank Wars. Laut Wikipedia ein genreprägender Klassiker!

2008-05-29_171253.jpg
Vier Studenten und ein CRT, 29. Mai 2008.

Wie auf dieser altertümlichen Low-Megapixel-Fotografie zu erkennen, haben wir uns manchmal einen Jux draus gemacht, es standesgemäß auf einem der CRTs im Labor der Hochschule zu spielen. Es war zwar erst 2006, aber es gab auch dort schon Flachbildschirme, keine Sorge. Es gab sogar einen iMac, bei dem ich Stunden zubrachte, etwas auszudrucken, weil das “Datei”-Menü “Ablage” hieß und ich natürlich nicht auf die Idee kam, dort nach dem Drucken-Dialog zu suchen. Aber es war der einzige Rechner von dem aus der Drucker funktionierte. Glaube ich. Vielleicht ging der Drucker auch einfach auf meinem Linux-Notebook nicht und ich war mir zu fein ein Windows-Gerät anzufassen. Es ist sehr lange her.

Jedenfalls verbindet mich mit diesem Spiel ein gewisser Fluch, denn ich, der damals schon Lust auf Spielentwicklung hatte, wollte natürlich dieses grandiose und wegweisende Spiel nachbauen. So schwer kann das ja nicht sein, dachte ich mir, und produzierte sicherlich ungefähr vierhundert Java-Projekte, bei denen ich immer wieder verzweifelte. Doch warum?

Für alle, die die Wikipedia-Seite nicht gelesen haben, nochmal kurz die Grundlagen vom Spiel: Es gibt für jeden Spieler einen Panzer, der Dinge abschießen kann, die entweder die anderen Spieler kaputt machen, oder, wenn sie aufs Gelände treffen, eben dieses zerstören. Man kann nicht fahren, sondern nur den Rüssel bewegen und die Schusskraft verändern. Ich wollte diese Spielelemente nun also möglichst originalgetreu nachbauen, also auch das zerstörbare Terrain. Abgesehen davon, dass es 2006 noch nicht tausend super dokumentierte Game-Frameworks gab, wollte ich auch einfach verstehen, was da passiert, ich beschloss also, alles in Java, der einzigen Sprache, neben PHP, die ich damals konnte, umzusetzen. Mit Swing, oder wie das hieß. Ich malte also fleißig ein BufferedImage nach dem anderen und zeigte es in einem JFrame an.

Die meisten Sachen bekam ich auch hin. Diese ganze Mathe-Kacke. Eine Linie zeichnen von A nach B, Kreise malen, Winkel, Sinus und Kosinus. Damals konnte ich auch schon googeln. Ich schaffte es auch, dass das Terrain kaputt ging, wenn man daneben schoss, und baute auch so ein paar Extras ein, dass Dinge am Bildschirmrand abprallen und so Spielereien.


Was ich allerdings nie schaffte, und was mir irgendwann den letzten Nerv raubte: Es performant laufen zu lassen. Auf meinem Notebook, der 2006 quasi neu war, lief es halbwegs okay, aber auf dem etwas kleineren Rechner meines Kommilitonen ruckelte es wie verrückt. Unspielbar! Ich kam nie so richtig darüber hinweg, warum es auf Hardware mit mehreren Gigahertz nicht möglich ist ein paar tausend Pixel sechzig mal in der Sekunde neu zu malen. Mir war schon bewusst, dass das natürlich nicht auf der Grafikkarte läuft, wenn man nur einzeln ein paar Pixel in einem Bild im RAM ändert, aber es beschäftigte mich wirklich lange. Ich begann immer wieder von vorne, fand aber keine Lösung, auch meine Ansätze, herauszufinden, welche Pixel sich änderten und nur diese neu zu malen brachten irgendwie nichts.

Nach dem Studium legte ich das Projekt erstmal wieder zur Seite, ich hatte anders zu tun, als immer wieder das gleiche zu machen, ohne irgendeinen Fortschritt bei der Sache zu machen. Nun, zwölf bis vierzehn Jahre später, kam es aber zu einer unvorhergesehenen Folge von Ereignissen. Zum einen scrollte ich durch Photos.app und fand das oben abgebildete Foto und zum anderen fand ich auf Hacker News einen Blogpost von jemandem, der so eine realistische Sand-Simulation in JavaScript programmierte. Da blühte etwas in meinem Kopf auf, ich musste erneut versuchen dieses Spiel zu programmieren.

Nun wurde ich leider Krank, zwar nur eine handelsübliche Erkältung, trotzdem ganz schön foggy im Kopf, vor allem Abends, wenn ich nochmal fünf Minuten Lust habe, was zu programmieren, daher ist der Code ganz schön schlimm und enthält einige // hä Kommentare vor komischen if-Blöcken mit kopiertem und leicht angepassten Code, die man sicher hätte eleganter lösen können, aber es funktioniert halbwegs. Also das Terrain geht kaputt und man kann sich sogar bewegen, was völlig entgegen der eigentlichen Spielidee ist, aber gut. Das Schönste ist, wie das Terrain kaputt geht und herunterrieselt.

Das beste an JavaScript ist ja auch, dass ich es hier jetzt einfach embedden kann, bitte schön: Wichtig sind WASD und die Leertaste. (Natürlich nur am Desktop, außer ihr habt ein Nokia mit Tastatur)

Ja ich weiß, es fehlen weitere Mitspieler und es gibt auch keine Schwerkraft für die Panzer. Ich habe es auch Elephant THROW! genannt, und die fünfzehn Quadratpixel großen Rechtecke sind natürlich Elefanten, die Steine werfen oder sowas, denn ich finde es in dieser Zeit auch irgendwie blöd ein Spiel mit Panzern zu bauen, aber man kann auch nichts machen, wenn einen nunmal die für ein Jahrzehnt versteckte Motivation packt.

Eigentlich wäre das Projekt auch fast schon am ersten Tag wieder vorbei gewesen, denn die Auswahl des Frameworks hätte mich fast schon wieder völlig verrückt gemacht. Der Herr Jason vom Sandspiel hat das nämlich mit p5.js umgesetzt, was irgendwie so eine JavaScript-Version von Processing ist, oder so. Ich hab mir da fünf Minuten die Doku angeguckt und ich habe nicht verstanden, wie ich das schnell benutzen kann. Bei so Kram wie PixiJS fand ich keine Möglichkeit, einzelne Pixel zu setzen, was wahrscheinlich Sinn ergibt, da man das sicher nicht möchte, wenn man ein performantes Spiel bauen will. In meinem Kopf war festgesetzt, dass das Terrain aus einzelnen Pixeln besteht, die verschwinden und rieseln sollen, also brauchte ich etwas, mit dem ich die Pixel modifizieren kann. Ich landete letztendlich also beim ganz klassischen HTML Canvas-Element.

Also, da kann man natürlich auch erstmal keine Pixel setzen, sondern im Grunde ist es ein bisschen wie damals in Java, man erzeugt mit context.createImageData(width, height); einen sehr sehr langen Array, der für jeden Pixel vier Werte (R, G, B, Alpha) enthält. Was für ein riesiger Array! Am Ende spuckt man das komplette Array in den Canvas und die bunten Pixel werden angezeigt. Es gäbe zwar noch die Möglichkeit mit context.fillRect() direkt ein Rechteck malen, und immer 1x1 Pixel große Rechtecke malen, aber Stack Overflow meinte, die Methode mit .createImageData wäre schneller, was mir auch logisch erscheint, da man halt direkt ganz viele Pixel auf einmal setzen kann.

Einen weiteren Trick, den ich angewandt habe ist, einfach viel weniger Pixel zu rendern, als am Ende anzuzeigen. Intern gibt es nur 320x240 Pixel, angezeigt wird es auf 640x480. Werden diese Standard-Displaygrößen jemals aus meinem Kopf entweichen? Das gibt der ganzen Sache jedenfalls einen gewissen unscharfen Retro-Look. Jedenfalls rendert der bei mir ziemlich viele Frames, ohne größere CPU-Last zu erzeugen. Entweder liegt es nun daran, dass ich eine schnelle M1-CPU habe und seit meinem ersten Umsetzungsversuch einfach fast zwanzig Jahre vergangen sind, oder diese Canvas-Implementierung im Browser ist performanter im Pixel-Malen, als es diese JFrame-Java Geschichte damals war.


Nach dem Schreiben des letzten Absatzes wollte ich es natürlich doch genauer wissen und baute mal einen FPS-Zähler ein. 116 Frames schafft er! Im Chrome Taskmanager braucht der Tab dann etwa 30% CPU. Keine Ahnung, warum es nicht noch mehr sind, wenn er die CPU nur so gering belastet, gleichzeitig gefühlt aber auch ganz schön viel für ein paar Pixel.

Turns out, es ist immer noch super anstrengend im CPU Modus ein paar Pixel zu setzen. Ich habe also damals nicht komplett versagt. Irgendwie reicht mir das jetzt auch schon als Outcome von diesem kleinen Projekt. Mein Interesse, da jetzt alle Features des Ursprungsspiels einzubauen, oder sogar noch mehr, ist doch irgendwie ziemlich gering. Vielleicht versuche ich es in Zehn Jahren nochmal mit einer echten Game Engine und Sprites statt Pixeln.

20220514-153959-pwa-0621.jpg

Eine Heckenbraunelle!