In Ausgabe 11/2012 zeigten wir Ihnen, wie Sie mit dem App Game Kit unkompliziert ein Android-Spiel erstellen. Zu diesem Kit existiert jedoch auch ein Konkurrenzprodukt: Monkey Coder. Wir stellen den Monkey vor.
Während auf der einen Seite das App Game Kit sehr beliebt ist, hat auf der anderen Seite auch die Programmiersprache Monkey unter Smartphone-Spieleentwicklern eine treue Anhängerschaft gefunden. Doch welche der beiden Sprachen ist besser für den persönlichen Geschmack geeignet? Welche für Anfänger, welche für Fortgeschrittene? Dies werden wir im folgenden Artikel untersuchen, indem wir das Spiel vom letzten Mal („Apple Shooter“) erneut entwickeln – diesmal in der Programmiersprache Monkey. Optimalerweise haben Sie hierfür bereits den Workshop zum App Game Kit aus der Ausgabe 11/2012 durchgearbeitet. Dort wurde besprochen, wie Spiele im Allgemeinen aufgebaut sind, und wie diese mit dem App Game Kit im Speziellen ihre Umsetzung finden. Geübt wurde dies anhand eines Spieles, bei dem Äpfel durch Touch-Bewegungen auf dem Bildschirm abgeschossen werden – unserem „Apple Shooter“ (Abbildung 1 und 2). Wir werden nun diese Spielidee ebenfalls mit Monkey umsetzen – auf diese Weise sehen Sie die Unterschiede zu der internen Konzeption des App Game Kits.

Installation und Vorarbeiten
Zunächst einmal muss die Demo-Version von Monkey heruntergeladen und auf einem Windows-PC entpackt werden [1]. Deren Einschränkung besteht darin, dass sie ausschließlich HTML5-Spiele für den Browser generieren kann. Für Testzwecke und zum Durcharbeiten dieses Workshops ist dies vollkommen ausreichend. Wer die Vollversion besitzt (Kostenpunkt: 99 Euro), kann mit Monkey zusätzlich das eigene Spiel – unter anderem – als Android-APK-Datei exportieren. Die HTML5 und Android-Variante sehen dabei exakt gleich aus und verhalten sich auch identisch, obwohl für sie derselbe Programmcode geschrieben wurde (das App Game Kit ist übrigens ebenfalls in der Lage, ein identisches Spiel ohne Mehraufwand für verschiedene Betriebssystem-Plattformen zu generieren).
Während das App Game Kit über viele eingebaute, vom Hersteller mitgelieferte Funktionen verfügt, ist das Konzept von Monkey ein anderes: Dieses verfügt zwar über eine ausgeklügelte Sprache, doch die Anzahl der bereits enthaltenen Befehle ist eher überschaubar. Doch in diese Nische sind ein paar Fans der Sprache gesprungen: Dritte Entwickler, die nicht zum Hersteller gehören, haben den Sprachumfang durch selbstgeschriebene externe Bibliotheken (so genannte Module) erweitert. Für unser Apple-Shooter-Spiel ist es daher nötig, dass wir diese zusätzlichen Module installieren.
Laden Sie hierzu die erforderlichen ZIP-Dateien ([2], [3], [4]) herunter. Entpacken Sie die Datei autofit.zip
in das modules
-Unterverzeichnis von Monkey. Das hierbei automatisch erstellte Verzeichnis autofit2
benennen Sie danach in autofit
um. Aus diddy.zip
ist nur der Ordner diddysrcdiddy
nach modules
zu entpacken, nicht die Verzeichnishierarchien oberhalb – ansonsten findet Monkey später dieses Modul nicht. Für Fontmachine erstellen Sie den Unterordner fontmachine
und entpacken das zugehörige ZIP dort hinein. Nun sollten sie im Verzeichnis modules
die folgenden, neuen Unterverzeichnisse vorfinden (zusätzlich zu den vom Hersteller bereits mitgelieferten Modulen): autofit
, diddy
und fontmachine
.
Quellcode zum Download
Den Quellcode zum hier vorgestellten Spiel finden Sie unter Link 5 auf der Android-User-Homepage zum Download.
In dem Ordner bananas
ihrer Monkey-Installation werden die Quellcodes selbstentwickelter Spiele (wie auch die vom Hersteller mitgelieferten Beispiele) abgelegt. Erstellen Sie dort für unser Spiel das Unterverzeichnis AppleShooter
. Innerhalb von diesem ist nochmal der Ordner AppleShooter.data
anzulegen. Dort wird unsere App später nach Spielegrafiken, Sounds und Schriftarten suchen. Die Spielegrafiken und Sounds (welche bereits beim Workshop zum App Game Kit zu ihrem Einsatz kamen) kopieren Sie von der Android-User-Homepage in das AppleShooter.data
-Unterverzeichnis. Nun fehlt uns noch eine Schriftart, um später die erreichten Punkte und verbleibende Anzahl in Sekunden anzuzeigen. Hierfür ist aus modulesfontmachinesample programsample02.data
das Unterverzeichnis SportsFont
als Ganzes nach bananasAppleShooterAppleShooter.data
zu kopieren.
Die Umsetzung in Monkey
Die eigentliche Programmierumgebung (Abbildung 3) startet nach einem Doppelklick auf monkey.exe
. Mit File | New legen Sie ein neues Projekt an. Wählen Sie hier als Zielverzeichnis bananasApple Shooter
aus, der zu vergebende Dateiname für unseren Programm lautete AppleShooter.monkey
. Nun kopieren Sie den Quellcode am besten aus dem Download [5] oder schauen sich Listing 1 an. Doch was bedeuten all diese Zeilen? Hierfür wollen wir uns erstmal den Grundaufbau eines Monkey-Spieles anschauen (Abbildung 4):
Beim Start der App wird der Methodenblock OnCreate()
aufgerufen. Dieser kümmert sich um alle einmaligen Aktionen, die als Initialisierung des Programms nötig sind – in der Regel also das Laden von Spielgrafiken und -sounds in den Speicher. Danach wird von nun an in einem bestimmten, vom Programmierer festgelegten Intervall (zum Beispiel 10 Mal pro Sekunde) das Unterprogramm OnUpdate()
aufgerufen. Dort legt der Entwickler alle Befehle ab, welche die eigentliche Spielsteuerung übernehmen. Das Spiel wertet hier beispielsweise Benutzerinteraktionen (wie das Berühren des Bildschirms) aus oder prüft, ob eine Änderung des Spielzustands eingetreten ist. Wenn noch genug Prozessorzeit vorhanden ist, ruft die App nach OnUpdate()
automatisch OnRender()
auf. Dieses Unterprogramm ist für das Neuzeichnen des Bildschirms verantwortlich. Es werden also die (gegebenenfalls zuvor von OnUpdate
veränderten) Spielvariablen wie die aktuelle Punktzahl, der derzeitige Spielzustand oder die Position der Spielfigur ausgelesen, und anhand dieser die dazu passenden Zeichenbefehle aufgerufen. Falls Sie ein rasantes Action-Spiel geschrieben haben, welches 60 Mal pro Sekunde OnUpdate
aufruft, kann es auf langsamen Smartphones der preiswerteren Klasse nun passieren, dass diese zu langsam sind, um jedesmal OnRender()
im Anschluß zu starten. Das ergibt in diesem Fall, dass Ihr Spiel auf solch einem Handy mit einer niedrigeren Framerate als den angestrebten 60 Herz ausgegeben wird. Monkey strebt dann aber trotzdem an, zumindest OnUpdate()
60 Mal pro Sekunde zu durchlaufen, damit zumindest der Spielablauf nicht unter den Beschränkungen des Geräts leidet. Hinter dieser Konstruktion steckt auch der moderne Ansatz, Spiellogik und graphische Ausgabe voneinander zu trennen. Dies erleichtert unter anderem ebenfalls eine spätere Wartung des Programmcodes. Werfen wir nun einen Blick darauf, wie die konkrete Umsetzung der Apple-Shooter-Spielidee aus Heft 11/2012 in Monkey aussieht. Den Quellcode ( Ausschnitt) zeigt Listing 1.
Listing 1
Der Quellcode
#ANDROID_APP_LABEL="Apple Shooter" #ANDROID_APP_PACKAGE="com.AppleShooter" #ANDROID_SCREEN_ORIENTATION="landscape" Import mojo Import autofit Import diddy Import fontmachine Function Main () New AppleShooter() End Class AppleShooter Extends App Field Spielstatus:String Field ApfelPositionX, ApfelPositionY:Int Field SpielerHatZeitBis, Punkte, SekundenUebrig:Int Field PunkteSchriftart:BitmapFont Field Hintergrundbild:Image Field GameOverSchriftzug:Image Field KnopfNeuesSpiel:Image Field ApfelBild:Image Field TitelLogo:Image Field Schuss:Sound Field Explosion:Sound Field DrueckenTon:Sound Field GameOverSFX:Sound Method OnCreate () SetUpdateRate(10) SetVirtualDisplay (800, 480) Seed = RealMillisecs() SetChannelVolume(1,1) Hintergrundbild = LoadImage("hintergrundbild.png") GameOverSchriftzug = LoadImage("gameover.png") KnopfNeuesSpiel = LoadImage("knopfNeuesSpiel.png") ApfelBild = LoadImage("apfel.png") TitelLogo = LoadImage("titellogo.png") PunkteSchriftart = New BitmapFont("SportsFont/SportsFont.txt", True) Schuss = LoadSound ("schuss.wav") Explosion = LoadSound ("explosion.wav") DrueckenTon = LoadSound ("knopfGedrueckt.wav") GameOverSFX = LoadSound ("gameover.wav") PlayMusic("hintergrundmusik.mp3") Spielstatus = "Anfangsbildschirm" StartwerteFuerSpielSetzen () End Method StartwerteFuerSpielSetzen () ApfelPositionX = 300 ApfelPositionY = 70 SpielerHatZeitBis = RealMillisecs()/1000 + 20 Punkte = 0 End Method OnUpdate () If Spielstatus="Anfangsbildschirm" Or Spielstatus="Game Over" If ( (TouchHit() > 0) And (VTouchX() >= 250) And (VTouchY() >= 350) And (VTouchX() <= 550) And (VTouchY() <= 450) ) PlaySound(DrueckenTon,1) StartwerteFuerSpielSetzen() Spielstatus="Action!" Endif Return Endif If Spielstatus="Action!" SekundenUebrig = SpielerHatZeitBis - RealMillisecs()/1000 If SekundenUebrig = 0 PlaySound(GameOverSFX,1) Spielstatus="Game Over" Else If (TouchHit() > 0) PlaySound(Schuss,0) If ( (VTouchX() >= ApfelPositionX) And (VTouchY() >= ApfelPositionY) And (VTouchX() <= ApfelPositionX + 199) And (VTouchY() <= ApfelPositionY + 200) ) PlaySound(Explosion,1) ApfelPositionX = Floor( Rnd(1,600) ) ApfelPositionY = Floor( Rnd(1,280) ) Punkte = Punkte + 50 Else Punkte = Punkte - 50 Endif Endif Endif Return Endif End Method OnRender () UpdateVirtualDisplay Cls 0, 0, 0 DrawImage(Hintergrundbild,0,0) If Spielstatus="Anfangsbildschirm" DrawImage(TitelLogo,60,140) DrawImage(KnopfNeuesSpiel,250,350) Else PunkteSchriftart.DrawText("Punkte: " + Punkte,0,0) PunkteSchriftart.DrawText("Zeit: " + SekundenUebrig + " Sekunden",0,40) Endif If Spielstatus="Action!" DrawImage(ApfelBild,ApfelPositionX,ApfelPositionY) Endif If Spielstatus="Game Over" DrawImage(GameOverSchriftzug,100,150) DrawImage(KnopfNeuesSpiel,250,350) Endif End End
Mit einem Druck auf F5 können Sie das Spiel nun als HTML5-Version in einem Internet-Browser testen. Mit der Vollversion ist es möglich, das eigene Smartphone per USB-Kabel an den Computer anzuschließen, und nach Drücken von Run direkt darauf das Spiel auszuprobieren. Ebenfalls kann sie eine komplette APK-Datei generieren, um die eigene Kreation an Dritte weiterzugeben. Für einen Test reichen jedoch im Prinzip die Demoversion und ein Internet-Browser aus. Das Spiel läuft also nun – doch was hat es mit den Inhalten der Codezeilen (Abbildung 5, Listing 1) auf sich?
Zeile 1-3 legt Android-spezifische Angaben fest, wie beispielsweise den Namen des Spiels in der App-Übersicht, oder dass es im Landscape-Modus dargestellt wird. Anschließend werden alle benötigten Module (Zeile 5-8) importiert, damit uns auch die Befehle zur Verfügung stehen, die wir brauchen. Die Funktion Main() markiert nun den eigentlichen Beginn des Programms – diese startet unseren Programmkern, indem das Objekt AppleShooter
erschaffen wird (Zeile 11). Doch was beinhaltet dieses überhaupt? Dies wird ab Zeile 14 definiert: Hier deklariert der Ausdruck extends App
, dass für unseren „Apple Shooter“ der Aufbau der Klasse App
Pate stand – und diese schreibt unter anderem die Methoden OnCreate()
, OnUpdate()
und OnRender()
vor.
In den Zeilen 15 bis 29 werden alle benötigten Variablen definiert und ihr Typ festgelegt (also beispielsweise, ob es sich um eine Zeichenkette oder eine Zahl handelt). Die nun folgende Methode OnCreate()
definiert, dass 10 Mal pro Sekunde OnUpdate()
und anschließend OnRender()
aufgerufen werden (SetUpdateRate
), initialisiert den Zufallsgenerator, und lädt Spielegrafiken sowie -sounds. Abschließend ruft es das Unterprogramm StartwerteFuerSpielSetzen()
auf, welches wir zwischen den Zeilen 54 und 59 definieren. Dieses setzt die Startwerte eines Spiels (Punkte=0). Das Auslagern in ein eigenes Unterprogramm hat den Vorteil, dass wir auch zu einem späteren Zeitpunkt im Programm ein neues Spiel starten können, indem StartwerteFuerSpielSetzen()
aufgerufen wird.
Die in Intervallen automatisch gestartete Methode OnUpdate()
erstreckt sich anschließend von Zeile 62 bis 94: Die Logik ist hierbei im Groben dieselbe wie bei der Umsetzung für das App Game Kit aus dem letzten Heft – abhängig vom Spielstatus wird entweder auf das Drücken der Schaltfläche „Neues Spiel starten“ getestet (Zeile 64-71), oder es wird während eines laufenden Spiels reagiert (Zeile 73-92): Wenn die Zeit abgelaufen ist, dann beende das Spiel (Zeile 74-77). Läuft das Spiel hingegen noch und der Spieler hat einen Apfel abgeschossen, dann belohne ihn mit 50 Punkten (Zeile 78-85). Hat er danebengetippt? Dann sind 50 Strafpunkte abzuziehen (Zeile 86-87). Besonders beachtenswert sind bei dieser Methode die Zeilen 65 und 81: Anders als beim App Game Kit lässt sich nicht vereinfacht abfragen, ob ein bestimmte Sprite berührt wurde – stattdessen ist es in Monkey vonnöten, etwas umständlicher zu testen, ob eine Bildschirmberührung innerhalb des Quadrates lag, an der sich die entsprechende Grafik befindet. Allerdings liesse sich theoretisch auch für Monkey ein eigenes Unterprogramm schreiben, welches dieses Vorgehen vereinfacht.
App Game Kit oder Monkey?
Beide Produkte erlauben, mit ein und demselben Code ein Spiel für unterschiedliche Plattformen (wie z.B. Android und iOS) zu entwickeln. Ferner gestaltet sich bei beiden der Entwicklungsprozess oft kürzer, als dies etwa in Java oder Objective-C der Fall wäre. Für Anfänger scheint das App Game Kit die bessere Wahl zu sein. Es ist einfach zu installieren, gut und anschaulich dokumentiert, und kann nach einer einfachen, auch für Fachfremde verständlichen Struktur programmiert werden. Die Foren des Herstellers bieten ebenfalls Menschen mit wenigen Vorkenntnissen unkomplizierte Hilfe an. Anders sieht dies bei Monkey aus: Dieses bietet unter der Haube viel Potential, bringt aber wenig eingebaute Funktionen mit. Dies wird zwar durch die von Dritten programmierten Module mehr als kompensiert, doch dürfte es nicht jedem Anfänger liegen, bei der Installation zuerst einmal alle benötigten Erweiterungen im Internet zusammenzusuchen.
Der Aufbau von Monkey-Apps wirkt auf Fortgeschrittene sauberer und professioneller, auch lässt sich die Programmiersprache intern besser erweitern. In den Monkey-Foren wird tendenziell auf einem höheren technischen Niveau diskutiert – für Profis interessant, für den Durchschnittsmenschen, der einfach nur schnell und unkompliziert sein erstes eigenes Spiel fertigstellen möchte, hingegen eher hinderlich. Es sollte jedoch berücksichtigt werden, dass es beim App Game Kit neben der anfängerfreundlichen, einfachen Basic-Sprache optional auch eine sogenannte Tier 2 gibt: Dort werden Spiele in C++ entwickelt und die App-Game-Kit-Befehle als externes Framework zur Verfügung gestellt. Überhaupt versuchen die beiden Produkte auf Grund ihrer gegenseitigen Konkurrenzsituation, mit jeder neuen Version die eigenen Schwächen auszubügeln: So wird Monkey zunehmend übersichtlicher, und das App Game Kit lässt mehr Komplexität zu. Zum jetzigen Zeitpunkt lautet die Empfehlung jedoch noch: Einsteiger sollten eher zum App Game Kit greifen, Fortgeschrittene eher zu Monkey. Vor einem Kauf ist es unabhängig davon ratsam, zuerst einmal von beiden die jeweiligen Demoversionen ausprobiert zu haben. Nur so können Sie feststellen, was Ihrem persönlichen Geschmack entspricht.
Infos
- Diddy-Modul: https://code.google.com/p/diddy/downloads/list