Montag, 24. August 2009

Exotische Linuxprogramme

Auf ubuntublog.ch wird gerade die Frage gestellt: Exotische Linux-Applikationen gesucht. Dabei ist "exotisch" über "wenig bekannt" definiert. Mit dieser Definition könnte ich hier Werbung für meine eigenen Programme machen. Nun, warum auch nicht?
Jedenfalls weiss ich nichts davon, dass eines davon weit verbreitet wäre. Falls doch, he Leute, es schadet nichts dem Autor auch mal eine Rückmeldung zu geben, wenn euch ein Programm gefällt. Gerade bei kleineren Sachen hebt das die Motivation, und erhöht die Chanzen auch noch mehr davon zu hören. Es gibt keinen Grund, mit Anerkennung schwäbisch umzugehen.

Was es von mir an die Öffentlichkeit geschafft hat, ist bei freshmeat zu ersehen. Mit ausnahme des Projektionsrechners, der sich in der Weltenbastlercommunity eine Zeitlang einer gewissen Bekanntheit erfreute. Auch wenn er meines Wissens nie auf einem anderen, als dem meinen Rechner gelaufen ist. Wenn schon nichts anderes, als exotisch ist dieses Programm auf jeden Fall qualifiziert.

Nun, was sind exoten, die ich selbst verwende? Als jemand, der selbst für Geschäftskommunikation vim und TeX verwendet, bevorzuge ich ausgereifte Programme, die nicht alle halbe Stunde gepacht werden müssen. Die meisten davon haben es an sich, dass sie zumindest irgendwann recht bekannt waren.

Zu erwähnen ist vielleicht der Data Display Debugger, ein Debuggerfrontend, das, wie der Name schon sagt, Daten graphisch aufzubereiten und anzuzeigen. Ich sah noch keinen Debugger, der in diesem Bereich an den DDD auch nur annähernd hinkommt. Als Frontend ist der DDD ursprünglich mal für den gdb geschrieben worden, kann aber mittlerweile mit vielen anderen Backends umgehen. Wenn jetzt noch das Zusammenspiel mit Qt besser funktionierte (siehe unten), so wäre ich restlos zufrieden.

Konfigurationsmöglichkeiten

Zur Zeit bin ich immer noch dabei, mich mit Objekten, deren Anzeige und Konfiguration zu beschäftigen. Objekte in diesem Sinne ist alles, was auf dem Spielfeld steht, und nicht bewegt werden kann. Wenn es bewegt werden kann, so ist es eine Figur.
Nun hatte ich ja schon die Möglichkeit, ein Bild anzuzeigen und Klickgebiete zu definieren, die ein Script auslösen. Mein erster Zusammenstoß mit QtScript. Yea.
So auf Anhieb fand ich allerdings keine sinnvolle Möglichkeit, über das Script Werte einzugeben und zu verändern. Was tun? Selbst eine Eingaberoutine schreiben? Ach was. Zu was gibt es denn in Qt die schönen UiTools. Also Widgets zur Laufzeit beschreiben und anzeigen können. Also werden zusätzlich zum Hintergrundbild nun so schöne ui Dateien übertragen, mit Anzeigeposition und diese dann auf dem Bild platziert. Das ergibt zusammen mit der Möglichkeit, diese dann in den Scripts zu verwenden recht flexible Möglichkeiten für den Szenariobauer.

So langsam frage ich mich, ob es überhaupt ein Qt Modul gibt, dass in diesem Programm nirgends Verwendung findet. Nun, für das SQL Modul sieht es bisher nicht so aus. Auch OpenGl habe ich bisher nicht verwendet, könnte jedoch noch kommen. Ansonsten, ach ja, ActiveQt wird es mit hoher sicherheit auch nicht hinein schaffen. Sonst will ich da mal nichts ausschließen.

Montag, 10. August 2009

Umfangreiche Debuggingsession


Mit neuen Features gehen neue Fehler einher. Das ist so weit nichts neues. Tippfehler sind da die einfachsten, die erkennt der Compiler, und sie sind schnell behoben.
Gelegentlich bringen neue Features auch Fehler ans Licht, die schon länger existieren, aber bisher nicht zuschlugen. So einen hatte ich jetzt. Besonders unangenehm: Ein Fehler der meistens auftritt, aber nicht immer.

Es war klar, dass dieser irgendwie mit der Datenübertragung zusammenhängen muss. Allerdings sahen sowohl Server, als auch Client Code korrekt aus. Also hole ich Wireshark raus (Schlimmes Hackerprogramm. Ich fühle mich ja ach so böse.) und schneide die Kommunikation mit. Sieht alles ganz gut aus. Das in Frage kommende Datum - ein Bild - ist zu groß für ein Datenpaket, wird daher aufgeteilt. Dieses Vorgehen ist integraler Bestandteil von IP, und sollte daher kein Problem darstellen.

Doch was ist das? Meine Fehlerausgabe reklamiert unerkannte Daten, die genau so aussehen, wie die des zweiten Paketes. Ist nun IP kaputt? Kann doch nicht sein, dann würde ja viel mehr nicht funktionieren.

Die Lösung brachte ein Blick in die Qt Dokumentation. Ich verwende zum einlesen die QIODevice::readLine Funktion. Funktioniert meistens. Die liest eine Zeile, und eine Zeile endet mit '\n'. So weit so gut. Aber eine Zeile endet auch bei: "The end of the device data is detected."
Und das ist eine race condition. Wenn ich es schaffe readLine aufzurufen, bevor das zweite Paket ankommt, wird der Inhalt des ersten Paketes als vollständige Zeile zurückgeliefert.

Race Conditions sind recht unangenehme Fehler. Sie lassen sich fast nur durch hinzufügen eines zusätzlichen Endkriteriums beseitigen. Ich war ja der Meinung, '\n' sei ein solches Kriterium, ich übertrage das Bild ja nicht umsonst Base64 codiert. Ist es aber nach obiger Definition nicht.

Also brauche ich ein weiteres Ende Signal. Das Problem ist, dass ein solches Signal sich in der gesamten Datenübertragung auswirkt, deren allergrößter Teil bereits funktioniert hat, und funktionierenden Code lasse ich gerne stehen.
Hilft aber nichts, wenn es sein muss, wird eben ein Endesignal übertragen, dass dann auf der anderen Seite abgefangen werden will.

Nebeneffekte des Ganzen:


  • Ein paar kleinere Bugs konnten in diesem Prozess ebenfalls eliminiert werden.
  • Die Anzahl der ASSERTs ist merklich angestiegen.
  • Note to self: Dinge die begründet an einer Stelle anders gemacht werden, als überall sonst, dürfen gerne eine Kommentarzeile bekommen. Beim Aufräumen im Code ist sonst ein solcher Grund nicht immer im Hinterkopf präsent und es gibt gar wunderliche Effekte.


Ps.: Qt macht mir das Debuggen nicht gerade leicht. Immernoch halte ich DDD für den Besten mir bekannten Debugger. Aber wenn die Datenaufschlüsselung so aussieht wie in obigem Bild, werde ich daraus nicht wirklich schlau.

Sonntag, 9. August 2009

Objekte anzeigen


Das nächste implementierte Teil ist die Darstellung von Objekten. Und die Vorbereitung zur Konfiguration der selbigen.
Momentan lässt sich ein Bild für das Objekt definieren, und darauf "heisse" Bereiche.  Für diese heissen Bereiche sind momentan zwei unterschiedliche Möglichkeiten vorgesehen: Einmal wird ein einfacher Text angezeigt, mit der anderen Aktion ein Script ausgeführt.
Noch zu erledigen ist eine Rückmeldung an den Server, dass da was gemacht wurde.

Die Scriptausführung funktioniert noch nicht, wird ein heisser Bereich angeclickt sieht das momentan so aus, wie in obigem Bild dargestellt. Das Hintergrundbild ist das, was ich momentan für das Objekt "Stadt" hinterlegt habe. Die Übertragung des Bildes vom Server an den Client ist identisch der für Figurenbilder beschriebenen.

In diesem Bereich auf der TODO Liste:

  • Rückmeldung an den Server
  • Ausführung von Scripts
  • Teilbilder (Sprites) nachladen

Und bessere Bilder, aber das hat Zeit. Zu Testzwecken reicht das, was ich schnell fabrizieren kann vollständig aus. 

Sonntag, 5. Juli 2009

Bilder

Ein weiter wichtiger Schritt in Richtung des fertigen Spieles ist vollzogen: Es können individuelle Bilder für die Spielfiguren angelegt und angezeigt werden. Anstatt der bisher der Enfachkeit halber verwendeten schwarzen Kreise. Ist kein Bild vorhanden, so werden diese immernoch verwendet.

Die Bilder müssen serverseitig vorhanden sein. Übertragen zum Client werden sie in zwei Schritten.

  1. Name und MD5 Summe werden zum Client geschickt. Dies kann vom Client verwendet werden, um einen Cache anzulegen. Gegenwärtig macht der Client dies noch nicht.
  2. Das Bild selbst wird auf Anforderung, Base64 codiert, übertragen.

Ein Cache für die Bilder ist angedacht. Ebenso natürlich Bilder für Objekte, welche bisher noch überhaupt nicht dargestellt werden, sondern nur in der Feldbeschreibung auftauchen.

Als weitere kleine Änderung werden die Felder nun als Hexfelder angezeigt, nicht mehr als versetzte Quadrate.

Freitag, 29. Mai 2009

Nun ein Netzwerkspiel.

Nach über einem Monat bin ich mit dem Spiel nun wieder genau da, wo ich schon mal war. Was nicht heisst, dass sich nichts getan hätte.
Ich habe das Spiel aufgeteilt in einen Client und Server. Und damit kann ich nun das machen, was schon mit dem Monolithen möglich war. Blos halt über's Netz.
Beim auseinanderdröseln war der Server relativ schnell fertig. Der Client hat etwas länger gebraucht, alles rauszuschmeissen, was der nicht mehr braucht, und trotzdem noch zu funktionieren. Der größte Teil der Zeit ging auf die Kommunikation zwischen Beiden drauf. Das Protokoll ist größtenteils Asynchron, auf Anfrage wird synchronisiert, bis die Anfrage abgehandelt ist, um dann wieder in den asynchronen Modus überzugehen.

Momentan räpresentiert ein Client genau eine Spielpartei, vergeben wird in der Connectreihenfolge. Dies muss natürlich noch geändert werden, aber vorerst ist dieses Verfahren ausreichend.

Nach einem Monat dem vormaligen Stand hinterherrennen, ist es nun gut, dass jeder Fortschritt wieder ein echter Fortschritt sein wird. Es ist also alles, wie es schon mal war, nur weiter.

Sonntag, 8. März 2009

Eine Ressourcenverwaltung

Länger habe ich jetzt schon nichts zum Spielfortschritt geschrieben. Es ist halt ein reines Hobbyprojekt, da kann immer alles Mögliche dazwischen kommen.
Nun aber gibt es einen entscheidenden Fortschritt, und zwar ist eine Ressourcenverwaltung implementiert. Konkret verdeutlichen lässt sich dies anhand eines Beispieles:
So steht in der Objektdefinitionsdatei:

<objekt id="s">
<name>Stadt</name>
[...]
<produktion>
<ressource trigger="Rundenende" name="Nahrung">
<menge>3</menge>
<braucht>
<feldtyp>b</feldtyp>
</braucht>
</ressource>
[...]
<figur trigger="Rundenbegin" typ="b">
<braucht>
<ressource name="Nahrung">
<menge>6</menge>
<verbraucht />
</ressource>
</braucht>
</figur>
</produktion>
</objekt>

Hierdurch gibt es im Spiel ein Objekt mit dem Namen Stadt, welches am Ende der Runde des besitzenden Spielers drei Ressourcen mit dem wunderhübschen Namen "Nahrung" produziert. Sind davon sechs vorhanden werden diese in eine Spielfigur vom Typ 'b' umgewandelt. Die Definition dieser Figur steht an anderer Stelle.
Sechs scheint nicht viel, und für ein Spiel dieses Typus reichlich wenig. Jedoch befinde ich mich ja in früher Testphase, und da will ich möglichst wenig Wartezeit haben, bis ich sehe, ob das auch funktioniert. Eine Runde Wartezeit brauche ich jedoch, da natürlich auch getestet werden muss, ob der Zustand "kann nicht produzieren" richtig erkannt wird.

Beim Programmieren der Figurenerstellung kam mir das Qt Framework entgegen, mit seinem Signal Slot Mechanismus. So kann ich beliebige Objekte Figuren erstellen lassen, ohne diese Pointer auf Karte und Spieler mitschleppen lassen zu müssen.
Ein Schönheitsfehler ist noch, das Ressourcen auf einem Feld gesamt gezählt werden, nicht objektspezifisch. Was aber vorerst keine großartig schädlichen Auswirkungen haben sollte.

Bleibt noch, eine nette Figuren und Objektdefinition aufzubauen, dann kann schon fast gespielt werden.