Das Buch befindet sich noch in Arbeit. Hier ist ein kleiner Auszug der ersten Kapitel. Wem es gefällt, kann es bald in iTunes herunterladen!

Vorwort

Schon einmal daran gedacht, wie es wohl wäre, eine eigene App zu programmieren, erfolgreich zu sein und dafür gefeiert zu werden? Ein Traum all derer, die an dessen Umsetzung scheitern oder nicht wagen es zu versuchen. Dabei gehört nicht viel dazu! Hauptsächlich ist es Durchhaltevermögen (und vielleicht ein bisschen Glück). Programmieren hat, entgegen aller Vorurteile, nichts mit höherer Mathematik oder Talent zu tun! Wichtiger ist das logische Denkvermögen und die Motivation an der Lösung, über einen längeren Zeitraum hinweg, zu arbeiten. Es ist ein guter Vorsatz, den man sich zur Gewohnheit macht.

Meine Passion für das Programmieren, entdeckte ich vor einigen Jahren, mit dem Kauf eines iPad. Damals war das noch etwas Besonderes, heute besitzt jedes Kind ein Smart Device. Und das ist auch der Grund dafür, warum der App Store nun zur attraktivsten Geldeinnahmequelle für Entwickler geworden ist. Die Nachfrage nach Apps ist riesig und das Geschäft mit den Apps floriert!

Mit dem iPad brachte Apple ein unglaublich aufregendes Gerät auf den Markt! Es ist ganz anders als ein herkömmlicher Computer oder ein Telefon. Ich war sofort begeistert und wollte gleich coole Spiele und Apps dafür entwickeln, hatte aber keinen Dunst wie. Also kaufte ich ein dutzend Fachbücher, um Apple’s kryptische Programmiersprache, Objective-C, zu erlernen. Und scheiterte! Verständlicherweise, denn Apple hat mit der Zeit eine schier unendliche Dokumentation an Funktionen, Klassen und Bibliotheken angehäuft. Es würde Jahre dauern alles durchzulesen und zu verstehen. Und selbst Swift, Apples neue Programmiersprache, vermag nichts daran zu ändern. Das ist mir viel zu trocken. Ich möchte basteln, Spaß haben und schnell Erfolge sehen!

Ich gab nicht auf, las unzählige Tutorials im Internet und begann einen tieferen Einblick in die Materie zu gewinnen. Zwei Sachen wurden deutlich: Die meisten (guten) Bücher zum Thema Spielentwicklung sind auf Englisch und »viele Wege führen nach Rom«. Aus diesem Grund schreibe ich diese Anleitung.

Das richtige Werkzeug

Die Qual der Wahl

Analog zu verschieden Kulturen auf dieser Welt, gibt es auch in der Welt der Programmierung, sehr viele Sprachen und in jeder Entwicklungsumgebung, die man benötigt, um Apps zu schreiben, wird eine eigene Sprache gesprochen. Einige Sprachen sind leicht, andere schwieriger zu meistern, bieten aber auch deutlich mehr Ausdruck und Vielfalt. Hätte man die Aufgabe, die perfekte Sprache, und damit eine Community, auszusuchen, wäre man sicherlich in einer Zwickmühle! Es geht eben um Präferenzen und Kompromisse.

Nach meinen Recherchen zu diesem Thema, kann ich zwei Optionen, besonders für Anfänger, wärmstens empfehlen: Löve2D und Codea. Beide sind sogenannte Game-Engines (oder Frameworks) und beide machen Gebrauch von der Programmiersprache Lua.

Lua

Lua ist eine plattformunabhängige Programmiersprache. Einmal gelernt kann man sie immer und überall gebrauchen! Die Syntax liest sich traumhaft leicht und die API ist winzig, simpel und genial zugleich, was rasches Erlernen der Sprache zu einem Kinderspiel macht. Lua ist ein wahres Kraftbündel!

Mit Lua, habe ich die perfekte Sprache für mich gefunden! Sie ist sowohl simpel als auch mächtig. Meiner Meinung nach, die flexibelste aller Programmiersprachen. Und Codea spricht in Lua. Dieses Duo pusht Programmierung auf ein ganz neues Level!

Codea

Im Gegensatz zu Löve2D, ist Codea eine vollständige IDE (Integrierte Entwicklungsumgebung), die speziell für das iPad entwickelt wurde. Der größte Vorteil liegt darin, dass man seine App direkt auf dem Gerät, programmiert und testet. Codea kommt mit einem hübschen und aufgeräumten Interface daher und lädt sofort zum Verweilen und Ausprobieren ein. Und genau dazu ist es da! Es ist ein Game-Framework das eines sehr gut kann: Sachen schnell und unkompliziert zum Laufen bringen und dazu passt keine andere Sprache besser als Lua! Aber Prototyping ist nur eine der vielen Stärken von Codea. Genau genommen kann man damit auch komplette Spiele, Simulationen und andere Arten von Apps, sowohl in 2D als auch 3D, programmieren und ohne Aufwand im App Store veröffentlichen. Doch nirgendwo geht das einfacher und schneller als in Codea!

Codea wird derzeit für 9,99EUR im iTunes App Store angeboten und ich kann es nicht oft genug loben und empfehlen.

Crashcourse

Bevor wir uns aufregenderen Experimenten hingeben, gehen wird kurz auf die Basics von Lua ein. Alles Weitere ergibt sich aus dem Kontext und wird bei Bedarf an Ort und Stelle genauer erläutert.

Variablen

Es gibt in jeder Sprache Variablen. So auch in Lua. Und da man beim Programmieren ständig etwas, für einen späteren Zugriff, aufheben muss, sind Variablen unerlässliche Instrumente der Programmierung. Variablen sind, abstrakt gesagt, Türchen zu Informationen. Als Programmierer verstauen wir unsere Informationen hinter eben solchen Türchen. Und damit wir ein bestimmtes Türchen wieder finden, benennen wir dieses.

Superstar = "Jonny Depp"
Türchen   = Information

Es gibt verschiedene Typen von Informationen, die wir möglicherweise speichern wollen. In vielen Programmiersprachen ist es üblich der Variable vorher zu sagen, welchen Typ Information sie repräsentieren wird. Bei einem Text, beispielsweise, wäre die Variable ein Typ string. Glücklicherweise sind wir in Lua davon verschont! Lua erkennt an Hand der Zuweisung (Definition) automatisch um welchen Wert-Typ es sich handelt. Somit entfällt die Deklaration gänzlich.

Eigentlich hat Lua keine Wert-Typen. Alles ist ein Objekt. Aber der Programmierer ist nunmal gewohnt alles zu klassifizieren, daher gibt es dann doch sechs Wert-Typen.

Name   = "Jonny"        -- string
Alter  = 50             -- number
ledig  = false          -- boolean
iD     = nil            -- nil
zeigen = function() end -- function
Perso  = {}             -- table

OK, theoretisch gibt es acht (nämlich noch thread und userdata), aber das sind meiner Meinung nach die wichtigsten, auf die man zu jeder Zeit angewiesen ist.

  • Strings sind Zeichenketten, also Texte.
  • Numbers sind Zahlen. Positiv, negativ und dezimal.
  • Booleans sind Wahr- & Falschaussagen (true und false).
  • Nil ist Nichts! Also ein Türchen, dass noch überhaupt keine Informationen enthält. Eine undefinierte oder noch nicht zugewiesene (deklarierte) Variable ist grundsätzlich nil. Sollte einleuchten.
  • Functions sind Funktionen, eine Reihe von Anweisungen, die nacheinander ausgeführt werden, ergo ein Algorithmus. Funktionen sind sehr nützlich für wiederkehrende Aufgaben.
  • Tables, zu deutsch Listen, sind Lua’s wichtigstes Konzept und das mächtigste Werkzeug überhaupt!

Hat man eine Variable erst einmal definiert, erhält man fortan Zugriff auf die darin gespeicherte Information und kann sie, zur Laufzeit, nach belieben aufrufen oder ändern. Wir können ein Türchen also jederzeit aufmachen und nachschauen was dahinter steckt, oder stattdessen etwas ganz anderes dahinter verstauen.

Name = "Jonny" -- Variable definieren
print(Name)    -- Variable aufrufen
> Jonny        -- Ausgabe

Name = "Jonny" -- Definition
print(Name)    -- Aufruf
> Jonny        -- Ausgabe
Name = "Mike"  -- Neuzuweisung: Variable in "Mike" ändern.
print(Name)    -- Aufruf
> Mike         -- Ausgabe

print(Name)    -- Variable existiert noch nicht, daher ist sie 'nil'.
> nil
Name = "Jonny" -- Variable definieren
print(Name)
> Jonny
Name = nil     -- 'nil' ist Nichts: Variable löschen!
print(Name)
> nil

print() ist eine Funktion, die ihr vielleicht noch nicht kennt! Mit Hilfe von print() können wir Informationen in der Konsole (CLI) ausgeben. Das ist oft sehr nützlich um einen Fehler im Programm aufzuspüren oder einfach einen Status auszugeben und ist als Debugging bekannt.

Variablen haben einen Wirkungsbereich (Scope), der sich auf einen Chunk beschränkt! Jedes Stück Code, das Lua ausführt, ist eine Sequenz. Eine Sequenz kann eine einzige Zeile Code oder gar eine ganze Datei umfassen. Ein Chunk ist im Grunde eine Reihe von Sequenzen. Standardmäßig sind Variablen öffentlich (global), was bedeutet, dass sie jedem Chunk zugänglich sind. Stellt man das Schlüsselwort 'local' voran, werden sie privat (local) und gelten nur für den nachfolgenden Chunk.

Name = "Jonny" -- global (Öffentlich)
local Name = "Jonny" -- local (Privat)

Zusammenfassung

Variablen sind Türchen, die verschiedene Typen von Informationen beherbergen. Variablen werden wie folgt definiert:

Türchen = Information

Ein Variablenname darf:
- keine Umlaute beinhalten.
- nicht nur aus Zahlen bestehen.
- keine Leerzeichen enthalten.
- kein reserviertes Wort von Lua sein. Andernfalls wird der bisherige Wert überschrieben.

Variablen haben einen Wirkungsbereich: global oder local.

Wenn eine Variable bereits existiert, kann sie abgefragt oder neu zugewiesen werden. Existiert sie noch nicht, ist ihr Wert 'nil', also nicht vorhanden.

Um eine existierende Variable zu löschen, weißt man ihr nil zu! Eine Variable beansprucht eine gewisse Menge an Speicherplatz im RAM des Computers. Wie viel ist abhängig davon, wie groß die Information ist, die wir in dieser Variable speichern. Durch die Zuweisung von nil kann eine Variable, bewusst, wieder gelöscht werden. Das schafft erneut Platz.

score = 22  -- definiert
score = nil -- gelöscht

Möchte man auf die gespeicherte Information in einer Variable zugreifen, ruft man sie direkt beim Namen.

name = "Sheldon"
realPerson = false
print(name, realPerson)
> Sheldon false

Dabei spielt Groß- und Kleinschreibung eine wichtige Rolle, denn Lua ist case sensitive. Name ist also nicht gleich name!

Ein Programm führt den Code immer von oben nach unten aus. Zeile für Zeile.

print() schreibt Text in die Konsole.

Der eigene Code darf gern kommentiert werden. Kommentare werden vom Programm nicht ausgeführt.

-- einzeilige Kommentare

--[[
	mehrzeilige
	Kommentare
]]--

Funktionen

Ein Algorithmus ist ein Gruppe von Anweisungen, die eine bestimmte Aufgabe lösen. In einem Programm kommt es oft vor, dass man ähnliche oder gar gleiche Aufgaben mehrmals zu bearbeiten hat. Um den Code nicht zu wiederholen, lagert man solche Algorithmen in Funktionen aus! Das hat vielerlei Vorteile. Einerseits sparrt man wertvolle Dateigröße ein, andererseits erhöht das die Lesbarkeit bei umfangreichen Projekten. Doch weitaus wichtiger ist die Wartung! Denn mit einer Funktion hat man den Code für eine bestimmte Aufgabe, an einem Ort. Ändert man etwas daran, passt sich das ganze Programm an, ohne dass man es komplett umschreiben muss.

Funktionen haben drei Merkmale: das Wort 'function', runde Klammern und ein 'end'-Tag. Wie wir bereits gesehen haben, ist eine function ein Wert-Typ, und einen Wert weist man gewöhnlich Variablen zu.

hello = function()
	print("Hello my friend.")
end

Tatsächlich haben functions zwei Schreibweisen, die völlig identisch funktionieren.

f1 = function() end -- Sieht aus wie eine Variablendefinition
function f2() end   -- Kurzschreibweise

In beiden Fällen wird die Funktion einer Variable mit dem definierten Namen zugewiesen. Das bedeutet wir können die Variable aufrufen, ändern und weitergeben.

Eine Funktion ist ein Lua Chunk und eine in sich geschlossene Einheit. Es kann auf globale Variablen oder auf locale, die innerhalb der Funktion definiert werden zugreifen. Aber auch auf locale Variablen die vor dem Chunk def. worden sind. Diese nennt man upvalues. PARAMETER

Zusammenfassung

Funktionen erfüllen Routineaufgaben.

Es gibt zwei Arten eine Funktion zu definieren.

speak = function() print("Hello World") end
function speak()   print("Hello World") end

Der Aufruf ist ganz einfach!

speak()
> Hello World

Eine Funktion kann Parameter übergeben bekommen...

Listen

Um Informationen zu gruppieren, wird ein sogenanntes table verwendet! Ein table ist das, was in anderen Programmiersprachen als Array oder Node (Knoten) bezeichnet wird. Einfach ausgedrückt, ist es eine Auflistung von Informationen. Tables sind Lua’s einzige Datenstruktur und das mächtigstes Werkzeug!

Beim Definieren eines table, trennt man die einzelnen Datensätze durch ein Komma von einander ab und fasst den ganzen Block in geschweifte Klammern. Nicht viel anders als eine einfache Variablendefinition.

Perso   = {
	Name  = "Jonny",
	Alter = 50,
	ledig = false
}

Dieser abstrakte Personalausweis besteht aus einigen Daten zur Person und ist einer Variable Perso zugewiesen. So fasst man Information zu logischen Gruppen zusammen! Der Sinn des Ganzen wird noch viel deutlicher, wenn es um Klassen und Objekt-Orientierte-Programmierung geht. Außerdem können tables unendlich tief verschachtelt werden!

Zutaten = {
	Zucker = 10,
	Milch  = 200,
	Kekse  = 100,
	Butter = {
		Marke = "Kerrygold",
			Menge = 50
		}
}

Jedes der Datensätze in einem table, hat einen eigenen Schlüssel über den es angesprochen werden kann. Das ist analog zu einer Variable, bei der der Name der Schlüssel zu ihrem Wert ist! Der Zugriff auf ein Datensatz erfolgt über seinen Schlüssel, mit Zuhilfenahme vom sogenannten Selektor. Wie bei einer Variable ruft man die Werte direkt beim Namen auf. Und jedes mal, wenn man eine Ebene tiefer geht, benutzt man den Selektor. Dies ist vergleichbar mit einem Pfad, dessen Ordner mit Slashes abtrennt werden, nur das hier ein Punkt benutzt wird.

print(Perso.Name)
> Jonny
print(Zutaten.Zucker)
> 10
print(Zutaten.Butter.Marke)
> Kerrygold

Um genau zu sein, haben wir bisher eine Kurzform (speziell für tables) benutzt! Denn die Datensatz-Schlüssel sehen in ausgeschriebener Form ein wenig anders aus. Die folgenden zwei Beispiele verdeutlichen das. Sie sind in ihrer Funktion identisch.

bank = {
	money    = 1000,
	currency = "EUR"
}

bank = {
	["money"]    = 1000,
	["currency"] = "EUR"
}

Da die Schlüssel zwei Schreibweisen besitzen, gibt es auch zwei Möglichkeiten des Aufrufs. Beide sind, wie schon erwähnt, in ihrer Funktion, identisch.

print(bank.money)
print(bank["money"])

Im Umkehrschluss kann man die Werte wie folgt manipulieren.

bank.money       = 1700
bank["currency"] = "€"

Es ist auch möglich Datensätze ohne Schlüssel aufzulisten!

shoppinglist = {
	"milk",
	"meat",
	"salt",
}

In solch einem Fall nummeriert Lua die Datensätze automatisch von Eins aufwärts. Noch ein Unterschied! In den meisten Programmiersprachen zählt man von Null. Lua beginnt mit Eins! Man kann Lua zwingen mit der Null zu beginnen, aber das braucht man höchstens in Ausnahmefällen. Folglich sieht die shoppinglist ausgeschrieben wie folgt aus.

shoppinglist = {
	[1] = "milk",
	[2] = "meat",
	[3] = "salt"
}

Aber Vorsicht! Ein Aufruf in Kurzform, wie eben beschrieben, funktioniert hier nicht und führt zu einem Fehler!

print(shoppinglist.1)
> ')' expected near '.1'

Der Grund dafür ist recht einfach. Vergleicht man den Datensatz [1] mit einer normalen Variable, würde es bedeuten, dass er "1" heißt und sein Wert "milk" entspricht.

1 = "milk"

Variablennamen dürfen aber nicht nur aus Zahlen bestehen, denn Zahlen sind Wert-Typen! Woher wüsste Lua denn sonst, was davon nun der Name, und was der Wert ist? Deshalb die eckigen Klammern! Damit sagt man dem Interpreter, dass man den Schlüssel eines table meint. Der korrekte Aufruf wäre demnach:

print(shoppinglist[1])
> milk

In solch einem Fall entfällt auch der Selektor.

Nun gibt es manchmal Situationen, wenn ein Datensatz, statt sofort, zur Laufzeit angelegt werden muss. In solchen Fällen kann man sich eine leere Liste anlegen und die Werte bei Bedarf darin ablegen. Dazu gibt es folgende Möglichkeiten.

list = {} -- Ein leeres table
list.cars = {"Audi", "VW", "BMW", "Ford"} -- Der Datensatz 'cars' existiert noch nicht, sein Wert war bisher 'nil'. Hiermit wird der Wert in ein 'table' mit vier Werten geändert.
list.cars[2] = "Porsche" -- "VW" wird zu "Porsche"
list["bikes"] = {"BMX", "Mountainbike"} -- Ein neuer Datensatz.

Wie man sieht lassen sich tables ebenso einfach wie Variablen manipulieren. Aber tables haben mehr drauf! Sie haben Methoden, die es ihnen erlauben noch einfacher mit Daten zu arbeiten. Nummerierte Datensätze kann man zB auch wie folgt anlegen und löschen.

table.insert(list, birds = {"Owl", "Dove"})
table.remove(list.birds, 2) -- "Dove" wurde gelöscht.
list.birds = nil -- kompletten Datensatz 'birds' gelöscht.

Ich bin mir fast sicher, dass euer Kopf bereits abgeschaltet hat, aber das ist schon OK! Tables sind am Anfang wirklich hart, doch hat man sie erst begriffen, wird alles Andere sonnenklar, und fügt sich wie ein Puzzle!

Nemmt euch an dieser Stelle die Zeit und repetiert alles noch einmal. Experimentiert mit Listen und seht was passiert. Macht auch mal bewusst Fehler und arbeitet mit den Fehlerausgaben im Terminal, damit ihr sie zu verstehen lernt! Hier ist ein letztes Beispiel, wo wir die eckigen Klammern dringend brauchen.

institutions = {
	"Sparkasse",
	"Deutsche Bank"
}
bankbalance = {
	[institutions[1]] = 365,
	[institutions[2]] = -499
}
print(bankbalance.Sparkasse)
> 365 EUR
print(bankbalance[institutions[1]])
> 365 EUR
print(bankbalance["Deutsche Bank"])
> 499 EUR
print(bankbalance[institutions[2]])
> 499 EUR

Zusammenfassung

Tables sind, vereinfacht gesagt, Gruppen, und können verschachtelt werden. Man erkennt sie an den geschweiften Klammern!

tabelle = {}

Jeder Datensatz eines table hat einen eigenen Schlüssel (Key), wie eine Variable ihren Namen.

Der Zugriff auf einen Datensatz erfolg mit Hilfe des Wert-Schlüssels, in eckigen Klammern geschrieben, oder stattdessen durch den Selektor abgetrennt.

tabelle["schluessel"] = "wert"
print(tabelle.schluessel)
> wert

Schleifen

[...]