{"id":59715,"date":"2023-07-30T08:46:00","date_gmt":"2023-07-30T06:46:00","guid":{"rendered":"https:\/\/www.herr-rau.de\/wordpress\/?p=59715"},"modified":"2023-08-31T17:23:17","modified_gmt":"2023-08-31T15:23:17","slug":"ein-spiel-in-android-programmieren","status":"publish","type":"post","link":"https:\/\/www.herr-rau.de\/wordpress\/2023\/07\/ein-spiel-in-android-programmieren.htm","title":{"rendered":"Ein Spiel in Android programmieren"},"content":{"rendered":"<div style='text-align:right;'><small>(<a href='https:\/\/www.herr-rau.de\/wordpress\/2023\/07\/ein-spiel-in-android-programmieren.htm#comments'>3 Kommentare.<\/a>)<\/small> <\/div>\n<p><a href=\"https:\/\/www.herr-rau.de\/wordpress\/2020\/01\/programmierhormone-und-der-weihnachtlich-neujaehrlichen-komplex.htm\">Schon vor ein paar Jahren<\/a> hatte ich ein Spiel-Grundger\u00fcst in Java programmiert, erst in BlueJ, dann in Greenfoot, das sind zwei Entwicklungsumgebungen f\u00fcr die Schule. Aus einer Laune heraus wollte ich das jetzt f\u00fcr Android haben. <a href=\"https:\/\/www.herr-rau.de\/wordpress\/2018\/11\/dillingen-2018.htm\">2018 hatte ich eine Fortbildung in Dillingen<\/a> dazu gemacht, das wollte ich auch mal umsetzen. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Der aktuelle Stand<\/h2>\n\n\n\n<p>Im Spiel bewegen sich bis zu vier Spielerinnen und Spieler in einem Verlies oder H\u00f6hlensystem, das nach und nach aus verschiedenen Pl\u00e4ttchen aufgebaut wird. Man kann nur auf ein anliegendes Feld ziehen, wenn es zu diesem eine direkte Verbindung gibt. Eine Spielerin startet den zentralen Server (dort werden die Informationen verwaltet, wer gerade wo steht), alle melden sich bei diesem Server an; wenn die vorgesehene Spielerzahl erreicht wird, beginnt das Spiel. Der Server kann unter Greenfoot, BlueJ oder Android laufen, und Clients (das sind die Programme der Mitspielenden) gibt es ebenfalls f\u00fcr alle drei. Hier im Screenshot sieht man zwei Clients und einen Server gleichzeitig auf den drei Entwicklungsumgebungen laufen:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"700\" height=\"745\" src=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/crawlspace_screenshot-700x745.png\" alt=\"\" class=\"wp-image-59760\" srcset=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/crawlspace_screenshot-700x745.png 700w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/crawlspace_screenshot-282x300.png 282w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/crawlspace_screenshot-141x150.png 141w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/crawlspace_screenshot-1443x1536.png 1443w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/crawlspace_screenshot.png 1920w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/figure>\n\n\n\n<p>Ein kurzer Film (45 Sekunden), unscharf aber ausreichend, demonstriert das Prinzip: <\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"704\" style=\"aspect-ratio: 754 \/ 704;\" width=\"754\" controls src=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/crawlspace_demo.mp4\"><\/video><\/figure>\n\n\n\n<p>(Bin schon dabei, mir eine ordentliche Box f\u00fcr solche Aufnahmen zu basteln.)<\/p>\n\n\n\n<p>Die IP-Adresse des Servers k\u00f6nnte man vielleicht auch \u00fcbers Programm herausfinden lassen. Man kann das auch \u00fcbers ganze Internet und nicht nur im lokalen LAN spielen, wenn man wei\u00df, was man tut und im Router einen Port freigibt. Im Moment ist die Kommunikation v\u00f6llig unverschl\u00fcsselt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wie es weiter gehen k\u00f6nnte<\/h2>\n\n\n\n<p>Noch ist das gar kein Spiel, nicht mal eine Spieledemo, eher ein Proof-of-Concept f\u00fcr mich selber. Zu einem Spiel fehlt ja vor allem ein Spielziel, und danach die Feineinstellung bei Schwierigkeitsgrad und Belohnung. Und nat\u00fcrlich Ton und feinere Grafik.<\/p>\n\n\n\n<p>Man k\u00f6nnte weiter in die Richtung gehen, von der her kommend ich das Spiel gedacht habe: das Brettspiel <em><a href=\"https:\/\/boardgamegeek.com\/boardgame\/472\/dungeonquest\">DungeonQuest<\/a><\/em>. Da legt man kleine Papppl\u00e4ttchen vor sich und versucht, in die Mitte des Spielfeld zu kommen, wo man so kurz wie n\u00f6tig bleibt, um dem Drachen den Schatz zu rauben, ohne ihn aufzuwecken, und rechtzeitig vor Sonnenuntergang wieder zum Ausgang zur\u00fcckfindet. Bei dem Spiel gibt es Fallgitter, die den Weg hinter einem versperren, Drehkorridorteile, Fallgruben und Br\u00fccken als Hindernisse, Schatzkammern und Monster. Ein sehr lustiges Spiel, aber mit wenig Interaktion zwischen den Spielerinnen und Spielern; man k\u00e4mpft jeweils mehr mit dem H\u00f6hlensystem als gegeneinander. Das k\u00f6nnte man bei der Computerversion anders machen.<\/p>\n\n\n\n<p>Oder man k\u00f6nnte mehr Richtung <em><a href=\"https:\/\/en.wikipedia.org\/wiki\/Spy_vs._Spy_(1984_video_game)\">Spy vs. Spy<\/a><\/em> gehen (1984, es gibt auch eine moderne Version). Das war ein Spiel f\u00fcr den Commodore 64, basierend auf den gleichnamigen Mad-Magazin-Figuren. Zwei Spione durchsuchen ein Geb\u00e4ude mit verschiedenen R\u00e4umen nach irgendwas und k\u00f6nnen dabei in den M\u00f6beln in den R\u00e4umen verschiedene Fallen hinterlassen, auf die die jeweils andere Figur beim Durchsuchen dann st\u00f6\u00dft. Bei meinem Spiel hie\u00dfe das zum Beispiel: ein langer Druck auf die Position, an der man sich gerade befindet, hinterl\u00e4sst dort eine &#8211; aus einem Vorrat ausw\u00e4hlbare? &#8211; Falle, die zum Beispiel L\u00e4hmung f\u00fcr eine kleine Weile bewirkt, oder Teleportation an einen anderen Ort, oder die Drehung des Pl\u00e4ttchens um 90 oder 180 Grad, oder das Erscheinen eines Monsters. Die Fallen sieht man auf dem eigenen Bildschirm, aber die andere Spielerin kriegt diese Hinterlassenschaften nat\u00fcrlich nicht angezeigt.<\/p>\n\n\n\n<p>Oder man k\u00f6nnte das als Solospiel ausbauen und ein <em>Rogue-like<\/em> machen: Zufallsgenerierte Stockwerke, in die man hinabsteigen kann. Dort dann vor allem Sch\u00e4tze und Tr\u00e4nke und Waffen und Monster.<\/p>\n\n\n\n<p>Oder man reduziert die Spielfl\u00e4che auf 5&#215;6 Felder und l\u00e4sst eine Art Strategiespiel daraus werden, wo man einander jagt oder ausweicht. Dann vielleicht rundenbasiert statt Echtzeit?<\/p>\n\n\n\n<p>Vermutlich werde ich nichts davon machen. Ab jetzt w\u00fcrde n\u00e4mlich die eigentliche Arbeit anfangen, der Entwurf geht schneller.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"700\" height=\"200\" src=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/crawlspace_tiles2.png\" alt=\"\" class=\"wp-image-59866\" srcset=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/crawlspace_tiles2.png 700w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/crawlspace_tiles2-300x86.png 300w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/crawlspace_tiles2-150x43.png 150w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Erfahrungen bei der Entwicklung<\/h2>\n\n\n\n<p>Die Spiellogik habe ich schnell heruntergetippt, das Spielprinzip ist einfach und ich habe es ja schon mal programmiert. Diesmal habe ich das sogar noch einfacher gehalten, nicht so viele Klassen angelegt wie sonst und nicht schon vorab Erweiterungsm\u00f6glichkeiten eingeplant. Mehr Arbeit haben zwei andere Punkte gemacht, die bei Android anders laufen als bei meinen bisherigen Arbeiten: Die Netzwerkverbindung und die Grafik. &#8211; Ab hier wird es technisch, aber auch nicht sehr.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Client-Server-Programmierung<\/h4>\n\n\n\n<p>Echte Programmierer wissen, welches Framework man f\u00fcr welche Aufgaben nutzt, man muss nicht alles selber programmieren. Aber dazu bin ich zu weit weg von der Entwicklung. Ich habe meine selbstgeschriebenen Klassen f\u00fcr Server und Clients, alle schon so angelegt, dass ich sie bequem f\u00fcr neue Projekte erweitern kann. Nur dass das Programmieren f\u00fcr Android Probleme mit sich bringt, die man sonst nicht so hat. <\/p>\n\n\n\n<p>Kurzer \u00dcberblick zu Threads: F\u00fcr die meisten Aufgaben, die einem in der Schule unterkommen, schreibt man ein Programm, und das l\u00e4uft dann der Reihe nach ab, und wenn es l\u00e4uft, l\u00e4uft es, und wenn es fertig ist, ist es fertig. Nur manchmal m\u00f6chte man ein Programm, das sich sozusagen zweiteilt, oder noch weiter aufteilt, wobei die einzelnen Teile parallel oder quasi-parallel und relativ unabh\u00e4ngig voneinander arbeiten. (<a href=\"https:\/\/www.herr-rau.de\/wordpress\/2015\/12\/threads-i-allgemeines-und-erstes-java.htm\">Der erste von drei Eintr\u00e4gen zu Threads.<\/a>) Das passiert im Hintergrund ohnehin oft, wenn man mit Benutzeroberfl\u00e4chen arbeitet, also etwa Buttons, die man dr\u00fccken kann. Denn was auch immer das Haupt-Programm gerade tut, ein Nebenprogramm l\u00e4uft immer und schaut nach, ob nicht gerade ein Knopf gedr\u00fcckt worden ist. <\/p>\n\n\n\n<p>Man braucht diese Parallelit\u00e4t auch, wenn man eine Client-Server-Struktur programmiert. Das Programm muss ja gleichzeitig Nachrichten aus dem Internet verwalten und verarbeiten <em>und<\/em> normal weiter laufen. In meinem bisherigen Java ging das: <em>Versuche Verbindung zu Server aufzubauen<\/em>, und weil das immer eine wackelige Sache ist, wird man au\u00dferdem gezwungen, was geschehen soll, wenn das nicht klappt. <kbd>Try\/catch<\/kbd> hei\u00dft das: <em>Versuche es erst einmal, und wenn es nicht klappt, st\u00fcrze nicht gleich mit Fehlermeldung ab, sondern nimm die Reservel\u00f6sung f\u00fcr den Notfall.<\/em> In Android muss man das auch machen, aber das reicht noch nicht: Vieles, was absehbar l\u00e4nger dauern <em>k\u00f6nnte,<\/em> wie der Versuch einer Kontaktaufnahme \u00fcber Internet, <em>muss<\/em> au\u00dferdem in einem eigenen Thread laufen, der unabh\u00e4ngig vom Hauptthread ist. Ansonsten passiert n\u00e4mlich das, was viele am Smartphone kennen: der Hauptthread ist mit irgendeiner Aufgabe besch\u00e4ftigt und das Ger\u00e4t reagiert nicht auf Ber\u00fchrungen, sanftes Tippen, immer w\u00fctender werdendes Fingerstakkato.<\/p>\n\n\n\n<p>Wenn ich eine <code>NetworkOnMainThreadException<\/code> vermeiden will, muss ich also die Serversachen mittels <code>AsyncTask<\/code> auslagern. Das ist in den neuesten Versionen zwar auch schon wieder als <code>deprecated<\/code> markiert, also: \u00fcberholt, bitte nicht mehr benutzen; aber noch l\u00e4uft alles.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Besonderheiten bei der grafischen Benutzeroberfl\u00e4che<\/h4>\n\n\n\n<p>Zu einer Benutzeroberfl\u00e4che geh\u00f6ren \u00fcblicherweise Buttons, Texteingabe- und Textanzeigefelder und so weiter. In Greenfoot gibt es so etwas gar nicht, da gibt es nur die Klasse<code> Actor,<\/code> die erzeugt so etwas wie Sprites. In BlueJ habe ich mit Java Swing gearbeitet. Das ist das, was man vor Java FX hatte.<\/p>\n\n\n\n<p>In Android Studio ist das wieder anders. Man kann die GUI-Elemente entweder programmatisch anlegen, also im Programmcode, <em>Erzeuge einen Knopf und setze die Breite auf 100.<\/em> Nahegelegt wird aber, eine Art integrierten grafischen Oberfl\u00e4cheneditor zu verwenden, auf dem man mit Drag-and-drop Elemente platziert. Da werden Breite und H\u00f6he und Farbe und Beschriftung eines Buttons festgelegt und dessen Position. (Die ist aber auch wieder schwieriger, weil Smartphones unterschiedliche Bildschirm-Seitenverh\u00e4ltnisse haben.) Der Generator erzeugt eine &#8211; auch manuell bearbeitbare &#8211; XML-Datei mit den Objektbeschreibungen. Das hat den Vorteil, dass man die ganze Oberfl\u00e4chengestaltung leicht kopieren und wiederverwenden oder weitergeben oder aus dem Web herunterladen kann. Au\u00dferdem bleibt der eigentliche Javacode dann \u00fcbersichtlicher, weil man da diese ganzen Angaben eben nicht machen muss.<\/p>\n\n\n\n<p>Es gibt jetzt aber das Problem, dass ich von einem selbst angelegten Thread aus nicht auf die GUI-Elemente zugreifen kann: <code>Only the original thread that created a view hierarchy can touch its views.<\/code> Der Haupt-Thread soll wieder stabil laufen, ohne dass andere Threads reingr\u00e4tschen. Die L\u00f6sung: Wenn man in einem solchen manuell angelegten Thread doch auf den Haupt-Thread mit den GUI-Elementen zugreifen will, benutzt man dazu die Methode <code>runOnUiThread<\/code>(Runnable).<\/p>\n\n\n\n<p>Man merkt: Diese Threads machen alles etwas schwieriger.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Activities und Lebenszyklus<\/h4>\n\n\n\n<p>Activities: Das sind die verschiedenen <em>Screens<\/em> der Anwendung. Eine Activity zum Anmelden, eine Activity f\u00fcr das eigentliche Spiel, zum Beispiel. Typisch f\u00fcr eine App ist, dass man als Benutzer innerhalb einer App zur\u00fcckbl\u00e4ttern kann zur letzten Activity. Was geschieht dann mit der Activity, die man gerade verlassen hat? Was geschieht, wenn man die App schlie\u00dft, zu einer anderen wechselt, das Handy sich abschaltet? Das sind Fragen zum Lebenszyklus einer App, die man sonst nicht hat. Damit habe ich mich noch kaum besch\u00e4ftigt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Zukunft<\/h2>\n\n\n\n<p>Und jetzt w\u00e4re ich dann soweit, dass ich mein altes Storyworld-Projekt f\u00fcr Android umsetze. (Blogeintr\u00e4ge <a href=\"https:\/\/www.herr-rau.de\/wordpress\/2016\/02\/sunless-sea-fortsetzung.htm\">hier<\/a> und <a href=\"https:\/\/www.herr-rau.de\/wordpress\/2017\/03\/storyworld-ein-java-projekt-fuer-die-10-klasse.htm\">hier<\/a>.) Das m\u00fcsste sich vom Format her besonders gut eignen, und die Spiellogik kann ich ja \u00fcbernehmen, muss nur die grafische Oberfl\u00e4che anpassen, zugegeben keine kleine Aufgabe bei diesem Spiel, aber ohne echt anspruchsvolle Programmierung dabei &#8211; keine Threads, kein Server.<\/p>\n\n\n\n<p>Ich bin zwar als App-Entwickler angemeldet und habe schon eine App ver\u00f6ffentlicht, aber das ganze in den Shop zu kriegen, ist nochmal viel Aufwand und dauert auch eine Weile. Wenn ich also mal mit einer Klasse oder einem Kurs daram herumbastle, wird die Einreichung als App vermutlich zu lange dauern, so dass sich das nicht lohnt. Aber denkbar ist es schon.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>(3 Kommentare.) Schon vor ein paar Jahren hatte ich ein Spiel-Grundger\u00fcst in Java programmiert, erst in BlueJ, dann in Greenfoot, das sind zwei Entwicklungsumgebungen f\u00fcr die Schule. Aus einer Laune heraus wollte ich das jetzt f\u00fcr Android haben. 2018 hatte ich eine Fortbildung in Dillingen dazu gemacht, das wollte ich auch mal umsetzen. Der aktuelle [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":59760,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[25,313],"tags":[227,233],"class_list":["post-59715","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-informatik","category-tagebuch","tag-informatik","tag-programmierprojekte"],"jetpack_featured_media_url":"https:\/\/www.herr-rau.de\/wordpress\/archiv\/crawlspace_screenshot.png","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/posts\/59715","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/comments?post=59715"}],"version-history":[{"count":3,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/posts\/59715\/revisions"}],"predecessor-version":[{"id":59868,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/posts\/59715\/revisions\/59868"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/media\/59760"}],"wp:attachment":[{"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/media?parent=59715"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/categories?post=59715"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/tags?post=59715"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}