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.

Dienstag, 3. März 2009

QtCreator: Erster Eindruck

Eher zufällig bin ich darauf gestossen, dass heute Version 1.0 der Qt Entwicklungsumgebung Qtcreator herausgekommen ist. Ich habe es mir nicht nehmen lassen, diese gleich mal anzutesten. Erster Eindruck: Durchaus positiv.

QtCreator lässt zunächst mal vorhandene Dateien weitgehend in Ruhe, was ein Blick auf "svn diff" bestätigt. Die Oberfläche orientiert sich an anderen IDEs, ist also recht intuitiv, wenn man mit so etwas bereits gearbeitet hat.

Der QtCreator hat mein existierendes Projekt mit mehreren Unterprojekten anstandslos eingelesen, und alles richtig zugeordnet. Da gibt's nichts zu mäkeln. Bisher werden qmake Projekte eingelesen, weitere Projekttypen sind nach Angabe des Herstellers in Arbeit.

Ein deutliches Zuckerl für jemanden wie mich: Der Editor besitzt einen vi Modus. Dieser ist zwar vom vim weit entfernt, aber zumindest habe ich nicht mehr ständig i j k V :w und Ähnliches irgendwo im Programm stehen. :w ist allerdings der einzige Komandomodus Befehl, der zufriedenstellend funktioniert. Nun ja, man kann wohl nicht alles haben. Allerdings funktioniert im vi Modus auch die kontextabhängige Befehlsvervollständigung. Die einzige Funktion, die ich im vim vermisse. Wenn der vi Modus nun noch vollständig funktioniert, bin ich restlos begeistert.

Der Debugger ist aufgebaut, wie man ihn von anderen IDEs kennt. Eine Macke des Buildsystems hielt mich jedoch von einem umfangreichen Test ab: Es ist mir nicht gelungen, das Working Directory zu ändern. Da das Projekt in mehrere Teile aufgeteilt ist, ist hier das Sourceverzeichnis des Hauptprogrammes voreingestellt. Ich bräuchte allerdings das Wurzelverzeichnis des Gesamtprojektes. So werden natürlich keine Plugins und Datendateien gefunden.

Alles in allem sieht das Programm sehr annehmbar aus, ich werde dessen weitere Entwicklung aufmerksam verfolgen.

Sonntag, 15. Februar 2009

Erstes Begegnungsplugin

Nun hat das Aufbauspiel ein Plugin bekommen, um zwei sich begegnende Figuren gegeneinander antreten zu lassen. Es handelt sich in diesem Fall um ein Kampfplugin, da dies am einfachsten zu programmieren ist, und in so einem Spiel ohnehin gebraucht werden wird.

Das Plugin benutzt zwei Eigenschaften, die in den Szenariodaten festgelegt werden. Namentlich werden den Figuren Werte für "Angriff" und "Verteidigung" zugewiesen. Diese Eigenschaften sind nicht vom Programm vorgegeben, sondern erlangen nur durch ihre Verwendung im Plugin Bedeutung.

Eine für mich äußerst ärgerliche Eigenschaft von Plugins musste ich feststellen: Plugins können nicht auf Code des Programmkerns zugreifen. Nur solchen, den sie zur Compilezeit sehen.
Das heisst dann, alle benötigten Zugriffsfunktionen inline verwenden, und das Ergebnis in textueller Repräsentation zurückgeben, und dann vom Hauptprogramm auswerten lassen. Das ist sicher nicht die einzige Möglichkeit, aber die, die ich gewählt habe. Mal sehen, wie weit ich damit komme.

Ach ja, bevor ich's vergesse, das Spiel hat ein Forum bekommen: Aufbauspiel Forum
Dieses ist zwar noch vollständig inhaltsfrei, aber vorhanden. Immerhin etwas.

Freitag, 13. Februar 2009

Fortschritt bei den Objekten

Einen kleinen Fortschritt gibt es bezüglich der Objekte auf einem Feld:

  • Sie werden jetzt bei der Feldbeschreibung angezeigt
  • Objekte sind standardmäßig Feldunique, das heisst, es kann nur ein Objekt eines Types pro Feld gebaut werden. Diese Einstellung kann in der Objektdefinition überschrieben werden.
  • Das errichten eines Objektes verbraucht sämtliche übrige Bewegungspunkte der errichtenden Figur. Eine Figur, die sich diese Runde nicht mehr bewegen kann, kann so lange auch nichts mehr bauen.

Als einziges Objekt ist bisher noch "Stadt" definiert. Zum testen reicht das.

Einen seltsamen Fehler hatte ich heute. Nachdem bereits alles funktionierte bekam ich nach einer unbedeutend erscheinenden Änderung einen "Double deletion error" irgendwo in den tiefen der Qt Bibliotheken beim Löschen eines Object. Ich habe dessem Klasse daraufhin einen expliziten Destructor gegeben, genauso lehr wie der automatische, um eventuell an mehr Informationen heranzukommen. Danach war der Fehler wieder verschwunden.

Nun, vielleicht irgendwo eine falsch aufgelöste Abhängigkeit, die sich mit der Änderung des Zeitstempels der Datei erledigt hatte. Bei der Durchsicht der entsprechenden Konfiguration ist mir allerdings nichts aufgefallen. Bleibt abzuwarten, ob der nun tatsächlich weg ist, oder irgendwann wieder zutage tritt und dabei hoffentlich seine wahre Ursache verrät.

Mittwoch, 11. Februar 2009

Zur Blogparade: Warum Linux?

Kaum habe ich herausgefunden, was eine Blogparade ist, gibt es da auch schon eine, die mich interessiert. Und zwar zum Thema:


Warum nutzen Sie Linux?

Nun, zum einen natürlich, ich habe mich gut daran gewöhnt. Sicherlich bin ich kein Anwender der allerersten Stunde. Als ich das allererste mal 1996 ein Linuxsystem installierte gab es das ja bereits ein paar Jährchen. Damals auf meinem alten 486DX-II 66 mit seinen 20 MB Arbeitsspeicher war natürlich nicht alles so glänzend, wie es heute ist. Dass ich beim Kauf der Distribution einen Vermerk "Nicht für Anfänger geeignet" übersehen hatte vereinfachte die Sache natürlich nicht gerade. Aber schließlich war es installiert.

Bleibt zu sagen, als ich von Win 3.11 auf Linux umstieg habe ich erwartet, dass alles anders war. Diese Erwartung wurde erfüllt. Als ich später an eine Win98 Maschine kam habe ich erwartet, ein einigermaßen bekanntes Windows vorzufinden. Diese Erwartung wurde nicht erfüllt. Und so blieb es. Linux erfüllte meine Erwartungen, Windows nicht.

Desweiteren lernte ich natürlich die Entwicklungsumgebung kennen. Meine ersten Oberflächen mit TCL/TK, als ich später beruflich mit MFC programmieren musste, wunderte es mich nicht mehr, dass viele Windowsprogramme derart fehlerbehaftet waren. Somit wieder die Erfahrung: Linux funktioniert einfach, Windows nicht. Für mich jedenfalls.

Wo ich gerade bei einfach bin, wer sagt, dass Windows einfacher ist? Gerade wenn es Probleme gibt ist Linux rückverfolgbar und damit einige Probleme leichter zu lösen, als bei einem Windows, das alles versteckt. Es ist hier denke ich, eine Frage wie man an das System heran geht. Linux kennt eine Einstiegshürde, die inzwischen allerdings auch bereits äußerst flach ist. Danach geht es gleitend weiter, wie nah man auch immer an das System hin will.
Windows kennt eine solche Hürde ebenfalls. Aber viel weiter hinten. Jeder kann einigermaßen damit umgehen, Programme starten und routineaufgaben erledigen. Aber dann kommt lange nichts. Ich kenne bei Windowsadministratoren vorrangig zwei Typen: Die, die knapp über Normaluserlevel ihre installierten Programme streicheln, und einige, die wirklich richtig gut sind. Aber dazwischen ist so gut wie nichts.

Um zum Thema zurückzukommen: Ich bevorzuge es, mich in eine Sache so weit wie ich es brauche einarbeiten zu können, und wenn ich mehr brauche, eben mehr dazuzunehmen. Und nicht, ein "alles oder nichts" System vorgesetzt zu bekommen.

Außerdem ist Linux einfacher, wenn schnell mal eine Diagnose gefragt ist. Ich kenne kein Windows, das auf beliebigen Rechnern, möglicherweise sogar ohne Festplatten nur von einer CD startet und dabei ein vollständiges System zur verfügung stellt.

Letztlich bleibt zur Antwort, was ich schon eingangs gesagt habe: Inzwischen kenne ich mich damit aus. Deutlich besser, als mit Windows.

Dienstag, 10. Februar 2009

Aller Anfang


Wie schon dem Blogtitel zu entnehmen ist geht es hier um die Entstehung eines Aufbauspiels. Dieses wird gerade von mir programmiert. Und zwar unter dem unwahrscheinlich kreativen Namen "Aufbauspiel".

Über die erste Planungsphase ist es bereits hinaus. Der momentane Stand: Nach dem Starten hat man ein Fenster, das etwa so aussieht wie rechts angezeigt. Zwei Spieler haben jeweils eine Figur mit unterschiedlichen Eigenschaften. Das heisst, sie können sich unterschiedlich schnell über das Spielfeld bewegen. Die Figur des ersten Spielers kann zudem Städte bauen. Dies hat zwar überhaupt keine Auswirkungen (und wird momentan nicht mal angezeigt), aber er kann es. Toll gell.

Eigenschaften von Figuren, Feldern, Objekten und Szenariooptionen werden über XML Dateien eingelesen. Ich habe vor, hier möglichst wenig in den Programmcode und möglichst viel in die Szenariodaten zu stecken. Entsprechend wird die Karte über ein Plugin eingelesen, was es möglichst einfach machen soll, weitere Kartengeneratoren hinzuzufügen. Bis frühestens zur Beta reicht mir allerdings ein solcher Generator.

Dann mal sehen, was noch daraus wird. Möglicherweise kommt als nächstes ein Ressourcenmanagement. Dann könnte mit der Stadt auch was gemacht werden. Oder ein Kampfsystem. Dann wäre es einem der beiden Spieler möglich tatsächlich zu gewinnen, anstatt nur rumzulaufen. Nu ja, dann wohl demnächst mehr.