Category Archives: Software Engineering

Free the Robots! Mein erstes Produkt für die Facebook Messenger Platform.

Free the Robots! Mein erstes Produkt für die Facebook Messenger Platform.

This is a repost of a note I originally published on my Facebook account on August 12th, 2016, in German language.

Vielen Dank, dass du meinen Artikel geöffnet hast. Es würde mir viel bedeuten, wenn du ihn zu Ende lesen würdest und mir Rückmeldung gibst. Es geht um Chatbots, Conversational Commerce, die Facebook Messenger Platform und ein Produkt, das ich entwickelt habe.

Wer mich ein bisschen besser kennt weiß, dass ich in meiner Freizeit immer an irgendeinem Projekt arbeite. Die meisten davon landen recht schnell in der Schublade. Weil es mir reicht zu wissen, wie etwas grundsätzlich funktionieren könnte; weil die Ideen in den ersten Gesprächen mit Freunden zerrissen werden; weil mir etwas untergekommen ist, das ich noch interessanter finde. Selten wird mal was so fertig, dass es vorzeigbar wäre und noch seltener wage ich mich dann auch tatsächlich, es zu zeigen. Heute ist es mal wieder so weit.

“The hardest part about making stuff: you eventually have to show it to real people.”

Warum? Zum einen glaube ich, dass die Technologie dahinter reif ist. Das ist der interessante Part für diejenigen unter euch, die sich für Produktentwicklung und Unternehmertum interessieren. Zum anderen glaube ich, dass es trotz der Einfachheit einen echten Nutzen mitbringt. Ein kleines Utility, das jedem einmal nützlich sein kann und das wirklich jeder, egal ob technisch versiert oder nicht, benutzen kann. Nichts revolutionäres, nichts noch nie dagewesenes, aber nützlich.

Worum geht’s?

Preibo, der unermüdliche Preisroboter

Darf ich vorstellen? Das ist Preibo, dein Preisroboter im Facebook Messenger. Du kannst mit ihm genau so chatten, wie du das mit deinen übrigen Facebook Freunden machst, auch wenn seine Fähigkeiten zur Konversation reichlich beschränkt sind. Stattdessen kann er eine Sache richtig gut: Preibo “versteht” Amazon-Produktlinks und kann dich über Preissenkungen deiner Wunschprodukte auf dem Laufenden halten.

Für den Fall, dass sich der unmittelbare Nutzen nicht erschließt, liefere ich noch ein paar interessante Informationen über Amazon, auf die ich während meiner Recherche gestoßen bin: ein Unternehmen hat z. B. festgestellt, dass Amazon in einem Testzeitraum von 72 Stunden über eine Millionen Preisänderungen durchgeführt hat. Einzelne Artikel schwankten dabei um bis zu 240% [1]. Bei einfachen Stichproben konnte ich selbst Preissenkungen um bis zu 42% feststellen. Während ich diesen Artikel schreibe hat Preibo nur 30 Artikel im Bereich von 7,99 EUR bis 1499 EUR in der Datenbank, aber die Gesamtdifferenz zwischen durch Preibo registrierten Minimal- und Maximalpreisen beträgt bereits über 1000 EUR.

Damit wäre der Nutzen dann geklärt: wer etwas nicht sofort braucht, schreibt Preibo einfach einen Link zum Wunschartikel und Preibo meldet sich, sobald der Preis fällt. Und das funktioniert genau so einfach, wie du mit jedem anderen deiner Facebook Kontakte chattest.

Du musst keine fremde Website besuchen, du musst dich nirgendwo registrieren, deine Email-Adresse preisgeben, das nächste Passwort merken und dich dann mit Newslettern zuspammen lassen. Du erhälst ausschließlich erfreuliche Nachrichten und kannst auch noch richtig Geld dabei sparen.

Preibo kann außerdem auf Amazon suchen (gib z. B. “suche tribute von panem” bzw. “search …”, falls Preibo mit dir Englisch spricht, ein) und dir auch an eine Email-Adresse Benachrichtigungen schicken, wenn du deine Email-Adresse in den Chat eingibst. Natürlich mit Double Opt-In. Durch Eingabe von “watchlist” erhälst du einen Link zu deiner persönlichen Übersichtsseite über alle beobachteten Produkte samt Initialpreis und zuletzt abgefragtem Preis. Hier kannst du Produkte auch wieder aus der Liste werfen.

Falls du es nicht nötig hast, Geld zu sparen, (herzlichen Glückwunsch!) oder wenn du bisher weder Amazon noch den Facebook Messenger verwendet hast und auch nicht planst, das in naher Zukunft zu tun, dann ist Preibo natürlich vollkommen uninteressant für dich und du kannst einfach im nächsten Kapitel weiterlesen – vielleicht stimmt es dich zumindest bzgl. Facebook Messenger noch um. Für alle anderen gibt es hier schon einmal die wichtigsten Links zum direkt ausprobieren – ich würde mich freuen!

Alternativ kannst du mit der Messenger App auch diesen Messenger Code scannen, um Preibo zu kontaktieren:

Preibo Messenger code

Natürlich würde auch ich gerne langfristig von diesem Projekt profitieren. Daher sind alle Links, die Preibo z. B. im Rahmen einer Preissenkungsbenachrichtigung versendet, mit einem Affiliate-Code ausgestattet. Für dich als Nutzer ändert sich nichts – du zahlst den angegebenen Preis laut Amazon Produktseite. Aber Amazon zahlt mir vom Gesamtwarenkorbwert deiner Bestellung einen kleinen Anteil Provision. Also ein echter Win-Win!

Skeptiker mögen fragen, warum man dazu nun ausgerechnet einen Facebook Messenger Bot verwenden muss, Preisvergleichseiten gibt es ja schon einige. Um eine Antwort zu erhalten, muss man vielleicht eine andere Frage stellen:

Warum sind Chatbots auf einmal cool?

Eigentlich sind Chatbots nichts Neues. Schon in den 1950ern haben sich schlaue Menschen Gedanken darüber gemacht, wie man feststellen könnte, ob man Nachrichten mit einem Computer oder einem Mensch austauscht. Und das, obwohl es noch bis 1966 dauern sollte, bis mit ELIZA zum ersten Mal ein Programm entwickelt wurde, das die Illusion eines realen Gegenübers gut genug vermitteln konnte um es in die öffentliche Wahrnehmung zu schaffen.

Ohne Zweifel sind wir heute ein ganzes Stück weiter. Apples Siri oder Amazons Alexa sind nur zwei Beispiele, wie der Austausch mit einer Maschine in natürlicher Sprache langsam in unseren Alltag Einzug hält. Aber der Ursprung des aktuellen Chatbot-Hypes liegt nicht in einem weiteren Durchbruch in der Mensch-Computer-Interaktion begründet, sondern viel mehr an der erreichbaren Masse an Nutzern, einer in diesem Jahrtausend ganz neu entstandenen Art der Kommunikation und in einem weiteren genialen Schachzug von Facebook, um Endkunden und Unternehmen weiter an sich zu binden.

Eine Milliarde Menschen nutzen Facebook Messenger bereits. Es ist die zweitpopulärste App der Welt auf Apple Geräten – gleich hinter Facebook. Per Messenger und WhatsApp (das übrigens auch Facebook gehört) werden heute 60 Milliarden Nachrichten am Tag verschickt. Der wesentliche Anteil dieser Nachrichten dürfte zwar aktuell privater Natur sein, aber auch mit Facebook-Seiten (Pages), also der Präsenz von Unternehmen auf Facebook, lassen sich Nachrichten austauschen.

Wer mit einer solchen Facebook-Seite schreibt, will in der Regel keinen Smalltalk betreiben oder Sticker austauschen. Vielmehr handelt es sich häufig um Support-Anfragen im weitesten Sinne. Ein Ecommerce Unternehmen wird z. B. mit Fragen konfrontiert wie: wo bleibt meine Bestellung, versendet ihr auch nach Deutschland, wie sind die Versandkosten, gibt es den Artikel auch in anderer Ausführung; eine Band mit: wann tourt ihr wieder durch Europa, kann ich eine Autogrammkarte bekommen; eine Bank mit: wo ist der nächste Geldautomat, wie hoch ist mein Verfügungsrahmen, wie teuer ist die Auslandsverwendung; usw.

Bisher musste jede Nachricht von einem Seitenbetreiber manuell beantwortet werden.

Auf der letzten F8, der Facebook Entwicklerkonferenz, hat Mark Zuckerberg nun die Facebook Messenger Platform [2] vorgestellt. Mit dieser neuen Programmierschnittstelle lässt sich der Nachrichtenaustausch automatisieren, eine Seite kann also vollautomatisch auf die Nachrichten eines menschlichen Besuchers antworten. Außerdem bietet Facebook kostenlosen Entwicklerzugang zum bereits Anfang 2015 eingekauften wit.ai an, einer Plattform zur Auswertung von natürlichem Text [3].

Mark Zuckerberg formulierte seine Intention wie folgt:

“We think you should be able to message a business in the same way you’d message a friend.”

Denjenigen Seitenbetreibern, die bisher wenig Interaktion mit ihren Fans zu verzeichnen hatten, ist somit ein Werkzeug an die Hand gegeben, sie zu mehr Interaktion zu bewegen: Ein Imbiss könnte z. B. vollautomatisch Vorbestellungen entgegennehmen und sich direkt zurückmelden, wenn die Speisen abholbereit sind. Ein Restaurant könnte die Tischreservierung direkt im Messenger anbieten, ohne dass der Kunde Facebook verlässt und ohne dass ein Mitarbeiter am Telefon hängen und Restaurantbesucher vernachlässigen muss.

Diejenigen Seitenbetreiber mit zu vielen Anfragen können häufig wiederkehrende Gespräche automatisieren. Kein Kunde muss mehr Facebook verlassen, um die FAQs auf der Unternehmensseite zu studieren oder sich durch Warteschleifen in der Support-Hotline quälen.

Dort, wo Sonderwünsche geäußert werden oder der Bot sonstwie nicht mehr weiterkommt, kann jederzeit doch noch ein Seitenbetreiber höchstpersönlich einspringen und antworten. Und falls wit.ai verwendet wird, landet jeder nicht ausreichend eindeutig verarbeitete Satz auch noch im wit.ai Dashboard und kann vom Entwickler dazu verwendet werden, das System weiter zu trainieren.

Facebook hat also ein Mittel geschaffen, mit dem Seitenbetreiber neuen Mehrwert für den Endkunden anbieten können. Außerdem lassen sich Mehrwertdienste anbieten, bei denen Bots nicht ein Zusatzmodul einer bestehenden Seite sind, sondern das eigentliche Hauptmerkmal darstellen. Facebooks Vorzeigeprojekt, der Wetterbot Poncho [9], der mir Wettervorhersagen für meinen aktuellen Standort liefert und mir allmorgendlich die Frage beantwortet, ob ich heute einen Regenschirm einpacken muss, ist das beste Beispiel dafür. Und der Endkunde hat so oder so einen Grund weniger, Facebook zu verlassen.

Und während auf der Entwicklungsseite viel mehr Grips aufgewendet werden muss, um Eingaben des Nutzers richtig zu interpretieren, ist das Benutzerinterface für den Endnutzer auf das Wesentliche reduziert: ein Texteingabefeld und im besten Fall natürliche Sprache zur Interaktion.

Es scheint, als könnte sich der App Hype mit Bots wiederholen. Das Spielfeld ist jedenfalls weitestgehend unbesetzt, die aktuellen Spieler stecken noch in den Kinderschuhen und wir werden zweifellos noch einige Überraschungen erleben, welche Services demnächst als Bots auftauchen.

In der Telegram API Dokumentation heißt es sinngemäß,

“Bots können alles, außer Geschirr spülen. Bots sind wirklich schlecht im Geschirr spülen.”

Darum also sind Chatbots plötzlich cool: Einfach zugänglich über eine Art und Weise, mit der wir spätestens seit SMS bestens vertraut sind, und nutzbar auch ohne viel Bandbreite. Kein Lernen von immer neuen Benutzerschnittstellen, keine Registrierungsprozesse, kein Download, kein vergessenes AppStore-Passwort, schnelle Aktivierung, reduziert auf das Wesentliche. Echter Mehrwert für Unternehmen und Endkunden. Milliarden an Nutzern.

Der Vollständigkeit halber sei gesagt, dass Facebook nicht die erste und auch nicht die einzige Plattform ist, die den Einsatz von Bots erlaubt. Aber unter den Mitbewerbern, zu denen bspw. Skype, Slack oder Telegram gehören, ist nur einer, was die Integration angeht, ein ganzes Stück weiter: das chinesische Weixin (WeChat) unterstützt Bots bereits seit 2014 und auch hat auch die Bindung von Endkunden und Unternehmen innerhalb der Plattform perfektioniert, was sich u.a. daran bemerkbar macht, dass Unternehmen in China laut Wikipedia zuerst ein Weixin-Profil anlegen, bevor sie eine Website einrichten [4]. (Die New York Times hat zum Phänomen WeChat ein sehenswertes Video veröffentlicht. [5])

Die unübertroffene Reichweite der beiden Facebook Apps – Messenger wirbt mit 1 Mrd. User und WhatsApp hat ebenfalls bereits im Februar 1 Mrd. Nutzer berichtet [6] – und mein persönlicher Bezug sind die Gründe dafür, dass ich ich mich hier fast ausschließlich auf Facebook beziehe und auch Preibo zuerst für den Facebook Messenger entwickelt habe.

Erwähnenswerte Beispiele

Elftausend Bots gab es Anfang Juli bereits auf der Messenger Plattform. Wenn man sich umsieht und recherchiert, welche Use Cases abgebildet werden und welche größeren Unternehmen vertreten sind, gewinnt man einen guten Eindruck darüber, wie viel Zukunft Unternehmen und sogar Regierungen in dem Medium sehen.

  • Fluglinien wie KLM liefern aktuelle Fluginformationen bis hin zum Boarding Pass in den Messenger. Facebook sieht hier wohl ebenfalls einen wichtigen Use Case, da einige der ersten verfügbaren Nachrichtentypen bereits explizit für diesen Anwendungsfall eingerichtet wurden.
  • Allgemeine Reiseplanung scheint ebenfalls ein ganz heißes Thema im Messenger zu sein. Reisen, Ausflüge oder Unterkünfte kann man direkt aus den Bots von Expedia, Kayak, Skyscanner oder Hipmunk buchen.
  • Nachrichtenagenturen liefern mit ihren Bots die Schlagzeilen direkt in einen Chat und steuern die Leser über Links zu den vollen Artikeln auf ihre Homepages.
  • Das weiße Haus hat jüngst einen Bot veröffentlicht, mit dem amerikanische Staatsbürger ihre Nachrichten an den Präsident der Vereinigten Staaten senden können. Angeblich liest er zehn davon jeden Abend vorm Schlafengehen.
  • American Express hat einen Bot entwickelt, der in Echtzeit Informationen über Einkäufe mit der Kreditkarte in den Chat schickt und den Kunden über Vorteilsprogramme informieren soll. Bots wie Cloe oder Trim analyisieren Bewegungen auf Bankkonto oder Kreditkarte, liefern Statistiken und helfen beim Sparen.
  • Burger King experimentiert mit Burger-Vorbestellung.
  • Ecommerce allgemein und “Curated Shopping” im Besonderen verlagert sich Richtung Messenger.
  • Ein Uber lässt sich direkt aus dem Messenger bestellen und auch die Genossenschaft Taxi Deutschland ist diesmal schnell auf den Zug aufgesprungen.
  • Mit dem HealthTap Bot kann man Fragen anonym an Ärzte stellen und erhält eine qualifizierte und individuelle Antwort.
  • Microsoft hat Entwicklern ein komplettes Bot Framework zur Verfügung gestellt, mit dem nicht nur für das hauseigene Skype entwickelt werden kann, sondern für alle gängigen Plattformen inklusive Messenger.
  • Nicht unbedingt ein Bot, aber dennoch ein erwähnenswertes Beispiel für eine gelungene und wichtige Integration: Facebook bietet Mitgliedern bei Hinweisen auf Selbstmordabsicht oder anderweitig selbstgefährdendes Verhalten die Möglichkeit, sich per Messenger mit einem Seelsorger in Verbindung zu setzen.

Wohin geht die Reise?

Aus den vielen Meinungsäußerungen zum Thema Bots möchte ich zwei von Leuten herausgreifen, von denen man wohl behaupten kann, sie haben was Internet-Trends angeht einen ganz guten Riecher.

Chris Messina hat 2007 bei Twitter die Hashtags erfunden. Er war auch bei Google, heute ist er in leitender Rolle bei Uber tätig. Er hat selbst einen Messenger Bot entwickelt und das relativ spektakuläre Ergebnis dokumentiert [8]. Und er hat in einem umfangreichen Artikel über Bots [10] das Jahr 2016 als das Jahr des “Conversational Commerce” bezeichnet und dafür den Hashtag #ConvComm etabliert.

“2016 will be the year of conversational commerce”

Dharmesh Shah hat das Marketingunternehmen HubSpot mitgegründet (Marktwert heute ca. 1,75 Mrd. US$) und als schwerbeschäftigter CTO dennoch Zeit gefunden, einen (richtig tollen) Bot zu entwickeln. Gefragt nach seinen Motiven antwortete er [11], dass er in seiner IT-Karriere drei große Paradigmenwechsel gesehen habe: Internetsurfen mit Web-Browsern, Einführung von Smartphones und Apps und nun eben Chatbots. Er sagt,

“[It] feels like a Very Big Deal”

Ich glaube, dass die Herrschaften Recht haben. Ein ähnlich großes disruptives Potenzial habe ich zuletzt in #FinTech mit der Blockchain erlebt. Und die ist im Vergleich zum Messenger ein technologisches Schwergewicht, für Otto Normalverbraucher ohne viel Erklärung kaum verständlich und ohne ein gewisses technisches Grundwissen kaum erlebbar. Chatbots sind das totale Gegenteil und deshalb um so faszinierender: jeder kann sie nutzen, sie sind über einfachste Mittel bedienbar und die Anbieter- und Nutzerbasis ist schon längst da. Sie sind der nächste logische Schritt, das nächste Bindeglied zwischen Unternehmen und Konsumenten, zwischen Anbietern und Abnehmern. Unter der Haube verbirgt sich eine beliebig hohe technische Komplexität, aber bedient werden können sie von jedem, der in der Lage ist, Text in ein Eingabefeld zu tippen.

Ich bin davon überzeugt, dass schon Ende dieses Jahres alle größeren Marken Bots für ihre Facebook Seiten einsetzen werden. Ich glaube, dass Bots einen neuen Geschäftszweig in der IT etablieren werden und neue Geschäftsmodelle entstehen. Von “Bot as a Service” Plattformen bis zu auf Bots spezialisierten Softwareentwicklungs-Boutiquen ist eine neue Anbieterlandschaft im Entstehen. Bots werden ein ähnliches Wachstum erleben, wie das bei Smartphone-Apps und den AppStores der Fall war. Zum Vergleich: denen wird ein Umsatz von über 100 Mrd. US$ bis 2020 prognostiziert [7]. Aktuell gibt es für Bots noch keine Möglichkeit, Zahlungen im Messenger abzuwickeln, aber mit Ex-PayPal Chef David Marcus als Verantwortlichem für die Messenger Plattform ist das nur noch eine Frage der Zeit. Und eins wissen wir von Facebook: sie iterieren wahnsinnig schnell.

Dass ausgerechnet Text das nächste große User Interface Paradigma werden würde, konnte man zugegebenermaßen nicht erwarten, nachdem wir uns im Web doch lange und mühsam in Richtung responsive “Mobile First” UIs mit schicken retina-optimierten Grafiken bewegt haben. Aber wer Kunden erreichen will muss sie dort ansprechen wo sie sich aufhalten: in sozialen Medien, in Messengern.

Deshalb wette ich, dass in zwei Jahren Bots bereits zum Alltag bei der Interaktion mit Unternehmen gehören.

Auch, wenn der Nutzen gelegentlich recht fragwürdig ist:

Microsoft's Project Murphy erlaubt das Verschmelzen von zwei Bildern über "Was wäre wenn..." Fragen und liefert das Ergebnis direkt als Bild in den Messenger.

Microsoft’s Project Murphy erlaubt das Verschmelzen von zwei Bildern über “Was wäre wenn…” Fragen und liefert das Ergebnis direkt als Bild in den Messenger.

Du hast es bis hierher geschafft?

Hammer. Danke für’s Lesen. Würdest du mir dann vielleicht noch helfen?

  • Wenn du die Idee von Preibo cool findest und ohnehin ein paar Artikel auf deiner Amazon Wunschliste hast, probiere Preibo bitte aus! Im schlechtesten Fall hörst du nie wieder was, im besten Fall kannst du ein paar Euro sparen.
  • Wenn du Entwickler bist und einfach mal sehen willst, wie ein Facebook Messenger Bot funktioniert (oder wie schnell er auch nicht mehr funktioniert), probiere Preibo auch aus. Ich freue mich über jeden gefundenen Fehler.
  • Wenn du diesen Artikel lesenswert fandest, like und/oder teile ihn bitte. Gerne kannst du ihn auch auf anderen Medien verlinken, er ist öffentlich sichtbar.
  • Und natürlich freue ich mich über ein Like für meinen ersten Bot Preibo: https://www.facebook.com/PreiboBot

So… und jetzt klicke ich auf “Publish”, denn das ist ein “Lean Article”, genau wie Preibo ein “Lean Product” ist: lieber Fehler nachträglich korrigieren als ewig verbessern und nie an die Öffentlichkeit gehen. Tschaka!

Quellen und Verweise

Die Zitate stammen, in der Reihenfolge der Nennung, von/aus

[1] http://www.prmaximus.de/121404
[2] https://messengerplatform.fb.com/
[3] https://wit.ai/
[4] https://de.wikipedia.org/wiki/WeChat
[5] http://www.nytimes.com/video/technology/100000004574648/china-internet-wechat.html
[6] https://blog.whatsapp.com/616/One-billion
[7] http://www.statista.com/statistics/269025/worldwide-mobile-app-revenue-forecast/
[8] http://venturebeat.com/2016/07/05/messinabot-what-worked-and-what-didnt/
[9] http://poncho.is/
[10] https://medium.com/chris-messina/2016-will-be-the-year-of-conversational-commerce-1586e85e3991#.ecddkaxu1
[11] http://www.inc.com/jeff-haden/confessions-of-a-business-bot-builder-the-founder-of-a-175-billion-company-who-.html

How to build a game like Flappy Bird with Xcode and SpriteKit

How to build a game like Flappy Bird with Xcode and SpriteKit

When I heard about Flappy Bird for the first time, the hype was already in its final phase: developer Dong Nguyen had decided to pull the app from the stores in “22 hours from now“. Apart from overreacting users and an allegedly daily advertising revenue of up to 50,000 US$, the simple game mechanics were something that caught my attention. The concept of clicking/tapping to keep the player on track wasn’t really an innovation in itself, but given the hype it caused, it was certainly worth a closer look. As a Sunday evening challenge, I tried to reproduce the game mechanics and ended up with less than 200 lines of code.

Update Feb. 20th: I added the score counting part and included suggestions by readers Sascha and Nico. Updated code is pushed to GitHub.

Update Feb. 27th: Fixed a small glitch in the tutorial that DylanYasen pointed out, thanks! (No code change.)

Update Apr. 9th: Sorry, I currently don’t have time to update the tutorial. In the meantime, take a look what reader Daniel Bocksteger built with the learnings from this tutorial: Coin Catcher.

Graphic assets

Since the app was already removed from the stores when I started working on the clone, I had to rely on screenshots and videos of the original game to reproduce the individual sprites. I used The Gimp to produce the bird (two simple frames for animation), the pipes (upper and lower version), the distant background and the ground.

Art creation with The Gimp

Note that the created files are a little too small for an iPhone display. Therefore, in the course of this tutorial, you’ll see that I simply doubled the size by scaling every sprite by a factor of 2. In order to maintain the 8 bit retro look I changed the filtering mode of the textures from SKTextureFilteringLinear (standard) to SKTextureFilteringNearest.

You can download the created files with the final project.

Xcode project setup

iOS 7 comes with a great new framework called Sprite Kit. It hides lots of the iOS UI development details game programmers are not necessarily familiar with (outlets anyone?) and builds upon a basic game infrastructure they are are more used to (e.g. rendering loop and scene graph). For all iOS developers, focussing on the game mechanics becomes a breeze.

When Xcode starts, simply select “Create a new Xcode project” from the splash screen.

XCode start

From the available project templates, select “SpriteKit Game”.

Select SpriteKit Game

Now enter some project details. You can change them later if you need to.

Enter Project Options

Select a place to store the project files. I usually create a new subfolder in my Documents folder.

Finally, the project is created and we’re ready for development.

04-project-created

The bird

The template project comes with some sample code and assets that need to be removed. Delete the Spaceship.png graphic from the project and add the Bird1.png and Bird2.png files instead. Also remove the existing code in the initWithSize and touchesBegan methods of MyScene.m.

In initWithSize, create the bird sprite and add it to the scene. To access the bird easily from other class methods, we declare it as an ivar.

#import "MyScene.h"

@interface MyScene () {
    SKSpriteNode* _bird;
}
@end

@implementation MyScene

-(id)initWithSize:(CGSize)size {    
    if (self = [super initWithSize:size]) {
        /* Setup your scene here */
        
        SKTexture* birdTexture1 = [SKTexture textureWithImageNamed:@"Bird1"];
        birdTexture1.filteringMode = SKTextureFilteringNearest;
        
        _bird = [SKSpriteNode spriteNodeWithTexture:birdTexture1];
        [_bird setScale:2.0];
        _bird.position = CGPointMake(self.frame.size.width / 4, CGRectGetMidY(self.frame));
        
        [self addChild:_bird];
    }
    return self;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */
}

-(void)update:(CFTimeInterval)currentTime {
    /* Called before each frame is rendered */
}

@end

One important thing to remember is that the SpriteKit’s scene coordinate system has it’s origin at the bottom left point and the positive y- and x-axes extend to the top and right of the screen. A sprite’s default anchor point is always the center. Using the code above, the bird is placed on the vertical center and end of the horizontal first quarter of the screen.

Bird added to the scene

Hooray, we’re nearly there! It won’t get much harder than that, believe me.

Animating the bird

Animating is pretty easy thanks to SpriteKit Actions. We simply create a sequence of texture-changes and loop them endlessly with a little delay in order to produce the illusion of flapping wings. I believe that the original game used some more frames, but we’ll go with two for the sake of simplicity.

We’ll have to load the second bird sprite, too, produce an SKAction to animate them, and attach this animation to the bird.

SKTexture* birdTexture1 = [SKTexture textureWithImageNamed:@"Bird1"];
birdTexture1.filteringMode = SKTextureFilteringNearest;
SKTexture* birdTexture2 = [SKTexture textureWithImageNamed:@"Bird2"];
birdTexture2.filteringMode = SKTextureFilteringNearest;
        
SKAction* flap = [SKAction repeatActionForever:[SKAction animateWithTextures:@[birdTexture1, birdTexture2] timePerFrame:0.2]];
        
_bird = [SKSpriteNode spriteNodeWithTexture:birdTexture1];
[_bird setScale:2.0];
_bird.position = CGPointMake(self.frame.size.width / 4, CGRectGetMidY(self.frame));
[_bird runAction:flap];

This results in a simple animation like this:

Bird flapping its wings

Adding ground and background

Most of the screen background is a bright blue sky. Let’s fill the screen accordingly. We store the sky color in an ivar for later…

@interface MyScene () {
    SKSpriteNode* _bird;
    SKColor* _skyColor;
}
@end

@implementation MyScene

-(id)initWithSize:(CGSize)size {    
    if (self = [super initWithSize:size]) {
        /* Setup your scene here */
        
        _skyColor = [SKColor colorWithRed:113.0/255.0 green:197.0/255.0 blue:207.0/255.0 alpha:1.0];
        [self setBackgroundColor:_skyColor];

The background and ground sprites are repeating patterns. After adding Skyline.png and Ground.png to the project, we setup the textures first and then fill the full screen width with the sprites.

// Create ground
        
SKTexture* groundTexture = [SKTexture textureWithImageNamed:@"Ground"];
groundTexture.filteringMode = SKTextureFilteringNearest;

for( int i = 0; i < 2 + self.frame.size.width / ( groundTexture.size.width * 2 ); ++i ) {
    SKSpriteNode* sprite = [SKSpriteNode spriteNodeWithTexture:groundTexture];
    [sprite setScale:2.0];
    sprite.position = CGPointMake(i * sprite.size.width, sprite.size.height / 2);
    [self addChild:sprite];
}
        
// Create skyline
        
SKTexture* skylineTexture = [SKTexture textureWithImageNamed:@"Skyline"];
skylineTexture.filteringMode = SKTextureFilteringNearest;
        
for( int i = 0; i < 2 + self.frame.size.width / ( skylineTexture.size.width * 2 ); ++i ) {
    SKSpriteNode* sprite = [SKSpriteNode spriteNodeWithTexture:skylineTexture];
    [sprite setScale:2.0];
    sprite.zPosition = -20;
    sprite.position = CGPointMake(i * sprite.size.width, sprite.size.height / 2 + groundTexture.size.height * 2);
    [self addChild:sprite];
}

This leads to the following static scene.

Background, skyline and ground updated

You may have noticed that I created one more tile than necessary. This is required for the animation: We can create the illusion of movement by simply moving each sprite to the left for a full width and then resetting it to the original position. When the tiles wander to the left, a gap opens at the right edge of the screen. We use the extra tile to fill that gap.

// Create ground
        
SKTexture* groundTexture = [SKTexture textureWithImageNamed:@"Ground"];
groundTexture.filteringMode = SKTextureFilteringNearest;
        
SKAction* moveGroundSprite = [SKAction moveByX:-groundTexture.size.width*2 y:0 duration:0.02 * groundTexture.size.width*2];
SKAction* resetGroundSprite = [SKAction moveByX:groundTexture.size.width*2 y:0 duration:0];
SKAction* moveGroundSpritesForever = [SKAction repeatActionForever:[SKAction sequence:@[moveGroundSprite, resetGroundSprite]]];

for( int i = 0; i < 2 + self.frame.size.width / ( groundTexture.size.width * 2 ); ++i ) {
    // Create the sprite
    SKSpriteNode* sprite = [SKSpriteNode spriteNodeWithTexture:groundTexture];
    [sprite setScale:2.0];
    sprite.position = CGPointMake(i * sprite.size.width, sprite.size.height / 2);
    [sprite runAction:moveGroundSpritesForever];
    [self addChild:sprite];
}
        
// Create skyline
        
SKTexture* skylineTexture = [SKTexture textureWithImageNamed:@"Skyline"];
skylineTexture.filteringMode = SKTextureFilteringNearest;
        
SKAction* moveSkylineSprite = [SKAction moveByX:-skylineTexture.size.width*2 y:0 duration:0.1 * skylineTexture.size.width*2];
SKAction* resetSkylineSprite = [SKAction moveByX:skylineTexture.size.width*2 y:0 duration:0];
SKAction* moveSkylineSpritesForever = [SKAction repeatActionForever:[SKAction sequence:@[moveSkylineSprite, resetSkylineSprite]]];
        
for( int i = 0; i < 2 + self.frame.size.width / ( skylineTexture.size.width * 2 ); ++i ) {
    SKSpriteNode* sprite = [SKSpriteNode spriteNodeWithTexture:skylineTexture];
    [sprite setScale:2.0];
    sprite.zPosition = -20;
    sprite.position = CGPointMake(i * sprite.size.width, sprite.size.height / 2 + groundTexture.size.height * 2);
    [sprite runAction:moveSkylineSpritesForever];
    [self addChild:sprite];
}

Two layers of the scene are scrolling with different pace (speed scale factors 0.1 and 0.02 above), leading to an illusion of depth. This effect has been used in 2D video games for ages and is called parallax scrolling.

Parallax scrolling

Let’s add some physics

Until now, everything in the scene is just fake. The bird doesn’t even move. But we can easily enable the SpriteKit physics engine in order to add some realistic movement to the scene.

SpriteKit allows to attach a physics body to every scene node. The physics body has certain properties like mass, density, friction,… and it can interact with other physics-enabled entities in the scene. Once a physics body is created, the owner node is controlled by physics.

Let’s start with the bird. We will represent it’s physical shape by a circle.

_bird = [SKSpriteNode spriteNodeWithTexture:birdTexture1];
[_bird setScale:2.0];
_bird.position = CGPointMake(self.frame.size.width / 4, CGRectGetMidY(self.frame));
[_bird runAction:flap];

_bird.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:_bird.size.height / 2];
_bird.physicsBody.dynamic = YES;
_bird.physicsBody.allowsRotation = NO;

[self addChild:_bird];

When we start our clone now, we’ll see the bird falling straight down – and out of the screen. In order to avoid that, we will have to create a physics body for the ground as well. We could attach it to each of the ground tiles, but remember that they’re continuously moving left and then resetting their position. This could lead to some strange effects once the bird collides with such a ground tile. So instead, we can simply create an empty node with a rectangular physics body which spans the full ground.

Add this below the creation of the ground sprites:

// Create ground physics container

SKNode* dummy = [SKNode node];
dummy.position = CGPointMake(0, groundTexture.size.height);
dummy.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(self.frame.size.width, groundTexture.size.height * 2)];
dummy.physicsBody.dynamic = NO;
[self addChild:dummy];

Note that the bird has property dynamic set to YES, while the ground (and all other “static” entities) have dynamic set to NO. This is because that only the bird is affected by interactions with the physic world. The remaining entities are under our control and won’t change their position or rotation e.g. due to a collision.

With these changes in place, you’ll see our little bird falling to the ground.

Physics enabled

The bird is falling a little too fast for my taste. We have multiple options to control this behavior, let’s try the easiest and most obvious one first: we’ll change the world’s gravity!

At the beginning of the scene setup, simply add:

self.physicsWorld.gravity = CGVectorMake( 0.0, -5.0 );

This will reduce the gravity from an authentic -9.8m/s^2 to only -5m/s^2, making the bird falling slower.

In order to let the bird raise on a click/touch, we will apply a small directed impulse to the bird’s physics body. You wouldn’t believe how easy this is with SpriteKit. Just add one line to the touchesBegan method:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */
    [_bird.physicsBody applyImpulse:CGVectorMake(0, 8)];
}

The result should look like that:

Touches producing an upward directed impulse

Blog reader Sascha suggests to reset the bird’s velocity before the new impulse is applied. This avoids that the impulses accumulate per touch/click. Blog reader Nico suggests to reduce the impulse a little in that case, so the touchesBegan method now looks like that:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */
    _bird.physicsBody.velocity = CGVectorMake(0, 0);
    [_bird.physicsBody applyImpulse:CGVectorMake(0, 4)];
}

I strongly encourage you to experiment with these values.

While we’re at it, we can also change the bird’s rotation depending on it’s velocity. If it’s flying upward the beak should point to the top right; if downward, to the bottom right. This can easily happen on a per-frame basis in the update:currentTime method, which was unused up to now.

CGFloat clamp(CGFloat min, CGFloat max, CGFloat value) {
    if( value > max ) {
        return max;
    } else if( value < min ) {
        return min;
    } else {
        return value;
    }
}

-(void)update:(CFTimeInterval)currentTime {
    /* Called before each frame is rendered */
    _bird.zRotation = clamp( -1, 0.5, _bird.physicsBody.velocity.dy * ( _bird.physicsBody.velocity.dy < 0 ? 0.003 : 0.001 ) );
}

As you can see, I use the bird’s physics body velocity property which is maintained by the physics simulation. I added a little helper function clamp which avoids too large values in either direction. Note that the minimum and maximum values (-1, 0.5) are radians.

Pipes

The last game entity are the pipes which are moving in to the scene from the right and need to be avoided. As before, the pipes are textured SKSpriteNodes, they will be animated using SKActions and they’ll get a physics body attached for collision.

Add the two pipe graphics Pipe1.png and Pipe2.png to the project. From a graphical perspective, the pipes are a special entity. While the ground and skyline are always attached to the bottom edge of the screen and the bird always has the same dimensions, the top pipe has to extend from the top edge and the bottom pipe has to extend from the bottom edge. While this could be solved programmatically with the benefit of saving some texture space, I decided to use very high textures instead and not worry about display size anymore.

Just make the pipes long enough

While pipes consist of two SKSpriteNodes, I wrap both nodes into one empty SKNode as a parent. This has the advantage that it is sufficient to position the parent node in the world, while the two childs are positioned relatively to their parent node, so I only need to worry about their vertical position.

The distance between the upper and lower pipe is arbitrary, I chose 100 points.

@implementation MyScene

static NSInteger const kVerticalPipeGap = 100;

-(id)initWithSize:(CGSize)size {

A pair of pipes is created outside of the right screen edge. The lower pipe’s position is chosen randomly somewhere in the lower third of the screen. The upper pipe is added accordingly, considering the defined gap size. The zPosition for the pipes is chosen so that they always are rendered behind the ground.

// Create pipes

SKTexture* _pipeTexture1 = [SKTexture textureWithImageNamed:@"Pipe1"];
_pipeTexture1.filteringMode = SKTextureFilteringNearest;
SKTexture* _pipeTexture2 = [SKTexture textureWithImageNamed:@"Pipe2"];
_pipeTexture2.filteringMode = SKTextureFilteringNearest;

SKNode* pipePair = [SKNode node];
pipePair.position = CGPointMake( self.frame.size.width + _pipeTexture1.size.width * 2, 0 );
pipePair.zPosition = -10;

CGFloat y = arc4random() % (NSInteger)( self.frame.size.height / 3 );

SKSpriteNode* pipe1 = [SKSpriteNode spriteNodeWithTexture:_pipeTexture1];
[pipe1 setScale:2];
pipe1.position = CGPointMake( 0, y );
pipe1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:pipe1.size];
pipe1.physicsBody.dynamic = NO;
[pipePair addChild:pipe1];

SKSpriteNode* pipe2 = [SKSpriteNode spriteNodeWithTexture:_pipeTexture2];
[pipe2 setScale:2];
pipe2.position = CGPointMake( 0, y + pipe1.size.height + kVerticalPipeGap );
pipe2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:pipe2.size];
pipe2.physicsBody.dynamic = NO;
[pipePair addChild:pipe2];

SKAction* movePipes = [SKAction repeatActionForever:[SKAction moveByX:-1 y:0 duration:0.02]];
[pipePair runAction:movePipes];

[self addChild:pipePair];

The bird collides with the moving pipe and is pushed out of the screen.

Collision detection

We want these pipes to appear regularly. We will use SKActions again, but this time, in a little different way. Instead of moving the pipes and resetting their position, we will spawn new pipes regularly. We will move the spawn logic into a separate method. For that purpose, we need to store textures and the SKAction to move the pipes in new ivars:

@interface MyScene () {
    SKSpriteNode* _bird;
    SKColor* _skyColor;
    SKTexture* _pipeTexture1;
    SKTexture* _pipeTexture2;
    SKAction* _moveAndRemovePipes;
}
@end

The _moveAndRemovePipes action is created right after the pipe texture loading like so:

CGFloat distanceToMove = self.frame.size.width + 2 * _pipeTexture1.size.width;
SKAction* movePipes = [SKAction moveByX:-distanceToMove y:0 duration:0.01 * distanceToMove];
SKAction* removePipes = [SKAction removeFromParent];
_movePipesAndRemove = [SKAction sequence:@[movePipes, removePipes]];

This will move the pipes by a full screen width plus two times their texture width to make sure that the pipes are out of sight. Then, they are removed from the scene.

The spawn method is responsible for creating new pipes:

-(void)spawnPipes {
    SKNode* pipePair = [SKNode node];
    pipePair.position = CGPointMake( self.frame.size.width + _pipeTexture1.size.width, 0 );
    pipePair.zPosition = -10;
    
    CGFloat y = arc4random() % (NSInteger)( self.frame.size.height / 3 );
    
    SKSpriteNode* pipe1 = [SKSpriteNode spriteNodeWithTexture:_pipeTexture1];
    [pipe1 setScale:2];
    pipe1.position = CGPointMake( 0, y );
    pipe1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:pipe1.size];
    pipe1.physicsBody.dynamic = NO;
    [pipePair addChild:pipe1];
    
    SKSpriteNode* pipe2 = [SKSpriteNode spriteNodeWithTexture:_pipeTexture2];
    [pipe2 setScale:2];
    pipe2.position = CGPointMake( 0, y + pipe1.size.height + kVerticalPipeGap );
    pipe2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:pipe2.size];
    pipe2.physicsBody.dynamic = NO;
    [pipePair addChild:pipe2];
    
    [pipePair runAction:_movePipesAndRemove];
    
    [self addChild:pipePair];
}

Finally, we need to ensure that the spawnPipes method is called regularly to produce new pipes and attach the animation to it. This happens with an SKAction which is directly attached to the SKScene.

SKAction* spawn = [SKAction performSelector:@selector(spawnPipes) onTarget:self];
SKAction* delay = [SKAction waitForDuration:2.0];
SKAction* spawnThenDelay = [SKAction sequence:@[spawn, delay]];
SKAction* spawnThenDelayForever = [SKAction repeatActionForever:spawnThenDelay];
[self runAction:spawnThenDelayForever];

This action calls the spawnPipes method, then pauses for two seconds, then repeats.

Now we’ve got beautiful repeating pipes.

Repeating pipes

Collision detection and response

The game is over when the bird hits a pipe, so detecting a hit is our next challenge. SpriteKit provides a dedicated delegate for collision detection, SKPhysicsContactDelegate, which allows to respond whenever two physics entities are in contact. We will implement the delegate in our scene and set the physics world delegate to the scene.

Moreover, we need to setup some categories for the different types of entities in the scene. Right now, all entities collide with each other and we would receive notifications for all these contacts because of the default setup: all relevant properties – discussed below – have value 0. We will use the categories to configure the contact testing in more detail.

@interface MyScene () <SKPhysicsContactDelegate> {
    SKSpriteNode* _bird;
    SKColor* _skyColor;
    SKTexture* _pipeTexture1;
    SKTexture* _pipeTexture2;
    SKAction* _movePipesAndRemove;
}
@end

@implementation MyScene

static const uint32_t birdCategory = 1 << 0;
static const uint32_t worldCategory = 1 << 1;
static const uint32_t pipeCategory = 1 << 2;

static NSInteger const kVerticalPipeGap = 100;

-(id)initWithSize:(CGSize)size {    
    if (self = [super initWithSize:size]) {
        /* Setup your scene here */
        
        self.physicsWorld.gravity = CGVectorMake( 0.0, -5.0 );
        self.physicsWorld.contactDelegate = self;

We can use the categories to configure which entities can collide with each other and for which types of collisions we want to get notified. This is useful for two reasons: 1. the physics engine doesn’t need to test for collisions between e.g. the pipes and the ground (which saves some performance) and 2. we don’t require notifications for all possible types of collisions.

SpriteKit provides three physics body properties for that purpose: categoryBitMask says to which categories an entity belongs, collisionBitMask says which categories can collide with the entity and contactTestBitMask says which contacts lead to a notification. Note the separation of collision (actual interaction with the physics world) and contact (sole collision testing without any reaction in the physics world)! The latter two fields allow to produce three different scenarios: 1. contacts between entities are ignored, 2. contacts are notified but nothing happens in the physics simulation, 3. contacts are notified and applied to the physics world.

We will setup the bird as follows:

_bird.physicsBody.categoryBitMask = birdCategory;
_bird.physicsBody.collisionBitMask = worldCategory | pipeCategory;
_bird.physicsBody.contactTestBitMask = worldCategory | pipeCategory;

This means that the bird can collide with entities of the worldCategory and pipeCategory and that we would get notified for both of them. (You may wonder why we separate the categories for world and pipes – we could use one category for both of them. I’ll clarify later in this tutorial.)

The definition for the ground entity is a little easier. We only need to assign the category but do not request any collision notification/reaction.

dummy.physicsBody.categoryBitMask = worldCategory;
pipe1.physicsBody.categoryBitMask = pipeCategory;
pipe1.physicsBody.contactTestBitMask = birdCategory;
pipe2.physicsBody.categoryBitMask = pipeCategory;
pipe2.physicsBody.contactTestBitMask = birdCategory;

For the player nothing has changed: the bird still collides with the world. But the internals are now configured in a more sensible way.

Now we need to implement the contact notification method as required by the delegate. In order to visualize the collision, we will flash the background a little. That’s why we stored the sky color at the beginning of the tutorial!

- (void)didBeginContact:(SKPhysicsContact *)contact {
    // Flash background if contact is detected
    [self removeActionForKey:@"flash"];
    [self runAction:[SKAction sequence:@[[SKAction repeatAction:[SKAction sequence:@[[SKAction runBlock:^{
        self.backgroundColor = [SKColor redColor];
    }], [SKAction waitForDuration:0.05], [SKAction runBlock:^{
        self.backgroundColor = _skyColor;
    }], [SKAction waitForDuration:0.05]]] count:4]]] withKey:@"flash"];
}

We’re using a symbolic identifier for the SKAction here for the first time. That way, we can remove any previously created SKAction with the same name.

When you start the game now, you’ll see the background flashing red in case of a collision.

Animation stop

In order to stop the world movement and disable player control of the bird in case of a collision, we can make use of the speed property of the SKNodes. Setting the speed to 0 means that all running SKActions are paused. In order to avoid setting the speed property on every individual moving entity in the scene, we create a dummy parent node called _moving which holds all moving entities: the pipes, the background, the ground.

Once again we use an ivar to make it accessible from all methods.

@interface MyScene () <SKPhysicsContactDelegate> {
    SKSpriteNode* _bird;
    SKColor* _skyColor;
    SKTexture* _pipeTexture1;
    SKTexture* _pipeTexture2;
    SKAction* _movePipesAndRemove;
    SKNode* _moving;
}
@end

The entity is created at the beginning and added to the scene. All moving entities are added to this parent node.

        _skyColor = [SKColor colorWithRed:113.0/255.0 green:197.0/255.0 blue:207.0/255.0 alpha:1.0];
        [self setBackgroundColor:_skyColor];
        
        _moving = [SKNode node];
        [self addChild:_moving];
        
        SKTexture* birdTexture1 = [SKTexture textureWithImageNamed:@"Bird1"];
        birdTexture1.filteringMode = SKTextureFilteringNearest;

        ...
        
        // Create ground
        
        ...

        for( int i = 0; i < 2 + self.frame.size.width / ( groundTexture.size.width * 2 ); ++i ) {
            ...
            [_moving addChild:sprite];
        }
        
        // Create skyline
        
        ...

        for( int i = 0; i < 2 + self.frame.size.width / ( skylineTexture.size.width * 2 ); ++i ) {
            ...
            [_moving addChild:sprite];
        }

This affects also the pipe creation:

-(void)spawnPipes {
    ...    
    [pipePair runAction:_movePipesAndRemove];
    
    [_moving addChild:pipePair];
}

Now that we have all moving parts except the bird under one parent node. In order to stop animations, we can set the speed of _moving to 0 in case of contact. The parent’s speed is applied to all child nodes. We also want to happen this exactly once. We’re not interested in any further contacts once the animation has halted, so we wrap the whole method in a corresponding if.

- (void)didBeginContact:(SKPhysicsContact *)contact {
    if( _moving.speed > 0 ) {
        _moving.speed = 0;
    
        // Flash background if contact is detected
        ...
    }

You might have noticed that we did not add the bird to the _moving node. This is because we still want it to move and animate. We just need to retain player control from the bird by allowing touches only with _moving.speed > 0.

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */
    if( _moving.speed > 0 ) {
        _bird.physicsBody.velocity = CGVectorMake(0, 0);
        [_bird.physicsBody applyImpulse:CGVectorMake(0, 4)];
    }
}

Animations are haltet on collision

Restart

Before we can restart the game, we need some way to reset the entire scene: the bird has to be moved to its initial position, its physics properties have to be reset, existing pipes have to be removed and the animation has to be restarted. Most importantly, this shouldn’t start immediately after a collision but after a little delay and an explicit user click/touch.

Let’s keep track when the user is allowed to restart the game in a new ivar _canRestart.

@interface MyScene () <SKPhysicsContactDelegate> {
    SKSpriteNode* _bird;
    SKColor* _skyColor;
    SKTexture* _pipeTexture1;
    SKTexture* _pipeTexture2;
    SKAction* _movePipesAndRemove;
    SKNode* _moving;
    BOOL _canRestart;
}
@end

We will initialize this flag to NO because it’s not relevant during a running game.

-(id)initWithSize:(CGSize)size {
    if (self = [super initWithSize:size]) {
        /* Setup your scene here */
        
        _canRestart = NO;
        
        self.physicsWorld.gravity = CGVectorMake( 0.0, -5.0 );

But we’ll change the flag to YES after a collision and after the background-flash-animation has finished (that should be enough game-over-drama for the sake of this tutorial). For that purpose, we can use another kind of SKAction, one that supports block execution. We simply append it to the flash-animation.

- (void)didBeginContact:(SKPhysicsContact *)contact {
    _moving.speed = 0;
    
    // Flash background if contact is detected
    [self removeActionForKey:@"flash"];
    [self runAction:[SKAction sequence:@[[SKAction repeatAction:[SKAction sequence:@[[SKAction runBlock:^{
        self.backgroundColor = [SKColor redColor];
    }], [SKAction waitForDuration:0.05], [SKAction runBlock:^{
        self.backgroundColor = _skyColor;
    }], [SKAction waitForDuration:0.05]]] count:4], [SKAction runBlock:^{
        _canRestart = YES;
    }]]] withKey:@"flash"];
}

Now, if the game finished due to a collision and the user is allowed to restart, we can simply make use of the flag in the touchesBegan method and reset the scene after click/touch.

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */
    if( _moving.speed > 0 ) {
        _bird.physicsBody.velocity = CGVectorMake(0, 0);
        [_bird.physicsBody applyImpulse:CGVectorMake(0, 4)];
    } else if( _canRestart ) {
        [self resetScene];
    }
}

But wait, where’s that resetScene method coming from? Right, we still need to implement it.

How would we do that? We can easily reset the bird, restart the animation and reset the _canRestart flag, but how can we reset the pipes? Right now the existing pipes are direct children of the _moving container and we have no way to easily distinguish them from other nodes like the ground or skyline.

In order to easily access the pipes and remove them from the scene, we will restructure the scene hierarchy one more time: We will introduce another artificial parent node for all pipes, add this node to the existing _moving node and add all pipes to this new parent node.

The change is pretty straightforward. Once again a new ivar…

@interface MyScene () <SKPhysicsContactDelegate> {
    SKSpriteNode* _bird;
    SKColor* _skyColor;
    SKTexture* _pipeTexture1;
    SKTexture* _pipeTexture2;
    SKAction* _movePipesAndRemove;
    SKNode* _moving;
    SKNode* _pipes;
    BOOL _canRestart;
}
@end

…and a new SKNode as the parent for the pipes…

_moving = [SKNode node];
[self addChild:_moving];

_pipes = [SKNode node];
[_moving addChild:_pipes];
        
SKTexture* birdTexture1 = [SKTexture textureWithImageNamed:@"Bird1"];
birdTexture1.filteringMode = SKTextureFilteringNearest;

…and all created pipes added to this node instead of the _moving node.

    [pipePair runAction:_movePipesAndRemove];
    
    [_pipes addChild:pipePair];
}

Now we have everything we need to implement the resetScene method:

-(void)resetScene {
    // Move bird to original position and reset velocity
    _bird.position = CGPointMake(self.frame.size.width / 4, CGRectGetMidY(self.frame));
    _bird.physicsBody.velocity = CGVectorMake( 0, 0 );
    
    // Remove all existing pipes
    [_pipes removeAllChildren];
    
    // Reset _canRestart
    _canRestart = NO;
    
    // Restart animation
    _moving.speed = 1;
}

A little more drama

Right now, a crashed bird would simply fall as far as the physics world permits. If it crashes right in a pipe gap, it would possibly land directly on the lower pipe. I thought a little more drama was due! I wanted to ensure that the bird falls down to the ground and I wanted it to look a little more spectacular. So I changed the bird’s collision bitmask after collision so that it only would collide with the ground, and I added a little rotation animation:

- (void)didBeginContact:(SKPhysicsContact *)contact {
    _moving.speed = 0;
    
    _bird.physicsBody.collisionBitMask = worldCategory;
    
    [_bird runAction:[SKAction rotateByAngle:M_PI * _bird.position.y * 0.01 duration:_bird.position.y * 0.003] completion:^{
        _bird.speed = 0;
    }];

The angle and duration calculations are attempts to adjust the amount of rotation to the bird’s altitude. If the bird collides at a very low position, it will hit the ground sooner than if it collides at a high position, so the angle and durations are smaller if the bird flew lower. Right after the animation we change the bird’s speed to 0, too, to halt the wing flap animation. To avoid overriding the animation, we need to restrict the velocity-dependent rotation to when the game is still running:

-(void)update:(CFTimeInterval)currentTime {
    /* Called before each frame is rendered */
    if( _moving.speed > 0 ) {
        _bird.zRotation = clamp( -1, 0.5, _bird.physicsBody.velocity.dy * ( _bird.physicsBody.velocity.dy < 0 ? 0.003 : 0.001 ) );
    }
}

Now we need to reset the collisionBitMask, speed and zRotation properties in the resetScene method as well:

-(void)resetScene {
    // Reset bird properties
    _bird.position = CGPointMake(self.frame.size.width / 4, CGRectGetMidY(self.frame));
    _bird.physicsBody.velocity = CGVectorMake( 0, 0 );
    _bird.physicsBody.collisionBitMask = worldCategory | pipeCategory;
    _bird.speed = 1.0;
    _bird.zRotation = 0.0;

An idea to make the crash even more spectacular would be to add a little feather particle system. But maybe that’s something for another tutorial.

Score counting

The first thing to do for score counting is to actually display the score. SpriteKit provides SKLabelNodes, which are meant to display text in the scene. iOS 7 comes with plenty of fonts to choose from, I decided to go for “MarkerFelt-Wide”. Eventually we should switch to a more fitting bitmap font, but this should do for now.

To keep track of the score and the label, we’ll first add two new ivars.

@interface MyScene () <SKPhysicsContactDelegate> {
    SKSpriteNode* _bird;
    SKColor* _skyColor;
    SKTexture* _pipeTexture1;
    SKTexture* _pipeTexture2;
    SKAction* _movePipesAndRemove;
    SKNode* _moving;
    SKNode* _pipes;
    BOOL _canRestart;
    SKLabelNode* _scoreLabelNode;
    NSInteger _score;
}
@end

Now we’ll initialize the ivars and add the label to the scene. Add this at the end of the /* Setup your scene here */ block.

// Initialize label and create a label which holds the score
_score = 0;
_scoreLabelNode = [SKLabelNode labelNodeWithFontNamed:@"MarkerFelt-Wide"];
_scoreLabelNode.position = CGPointMake( CGRectGetMidX( self.frame ), 3 * self.frame.size.height / 4 );
_scoreLabelNode.zPosition = 100;
_scoreLabelNode.text = [NSString stringWithFormat:@"%d", _score];
[self addChild:_scoreLabelNode];

The score should increment whenever the bird has passed a pair of pipes. The easy way, as suggested in the comments, would be to simply increment the score when the pipes have left the screen and are removed from the scene graph. However, this would also mean a little delay until the score is counted. Instead, we will create an SKNode right “after” (meaning: to the right of) the pipes with a physics body with contact detection enabled.

Add this to -(void)spawnPipes:

[pipePair addChild:pipe2];
    
SKNode* contactNode = [SKNode node];
contactNode.position = CGPointMake( pipe1.size.width + _bird.size.width / 2, CGRectGetMidY( self.frame ) );
contactNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake( pipe2.size.width, self.frame.size.height )];
contactNode.physicsBody.dynamic = NO;
[pipePair addChild:contactNode];

[pipePair runAction:_movePipesAndRemove];

If you run the game now, you’ll see that the bird crashes shortly after passing a pair of pipes. This happens because the contact of the bird’s physics body with the contactNode’s physics body is detected and - (void)didBeginContact:(SKPhysicsContact*) is called, but we currently do not distinguish whether the bird is in contact with the world or something else. We can make use of the collision categories again and add a dedicated one for the score area.

@implementation MyScene

static const uint32_t birdCategory = 1 << 0;
static const uint32_t worldCategory = 1 << 1;
static const uint32_t pipeCategory = 1 << 2;
static const uint32_t scoreCategory = 1 << 3;

static NSInteger const kVerticalPipeGap = 100;

We assign this category to the score node that we created right before.

SKNode* contactNode = [SKNode node];
contactNode.position = CGPointMake( pipe1.size.width + _bird.size.width / 2, CGRectGetMidY( self.frame ) );
contactNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(pipe2.size.width, self.frame.size.height)];
contactNode.physicsBody.dynamic = NO;
contactNode.physicsBody.categoryBitMask = scoreCategory;
contactNode.physicsBody.contactTestBitMask = birdCategory;
[pipePair addChild:contactNode];

Now we can handle the different types of contacts properly by investigating the SKPhysicsContact object passed to the didBeginContact method. It has two properties representing the two physics bodies in contact, bodyA and bodyB. If either of these two physics bodies is of category scoreCategory, we can increase the score. In all other cases, the bird collides with the world.

- (void)didBeginContact:(SKPhysicsContact *)contact {
    if( _moving.speed > 0 ) {
        if( ( contact.bodyA.categoryBitMask & scoreCategory ) == scoreCategory || ( contact.bodyB.categoryBitMask & scoreCategory ) == scoreCategory ) {
            // Bird has contact with score entity
            
            _score++;
            _scoreLabelNode.text = [NSString stringWithFormat:@"%d", _score];
        } else {
            // Bird has collided with world

            ...
        }
    }
}

The only thing left is to reset the score to 0 in the reset method.

-(void)resetScene {
    ...
    
    // Reset score
    _score = 0;
    _scoreLabelNode.text = [NSString stringWithFormat:@"%d", _score];
}

The result should look like that:

Score Counting

The score update is a little boring. You can easily add some visual feedback by using some SKActions to scale the score for a short moment.

- (void)didBeginContact:(SKPhysicsContact *)contact {
    if( _moving.speed > 0 ) {
        if( ( contact.bodyA.categoryBitMask & scoreCategory ) == scoreCategory || ( contact.bodyB.categoryBitMask & scoreCategory ) == scoreCategory ) {
            // Bird has contact with score entity
            
            _score++;
            _scoreLabelNode.text = [NSString stringWithFormat:@"%d", _score];

            // Add a little visual feedback for the score increment
            [_scoreLabelNode runAction:[SKAction sequence:@[[SKAction scaleTo:1.5 duration:0.1], [SKAction scaleTo:1.0 duration:0.1]]]];
        } else {
            ...

The action scales the score text up to 150% of its size of 1/10th of a second and then back to the original 100% in another 1/10th second.

Many roads lead to Rome

I need to emphasize that there are dozens of other possible ways to implement the game mechanics.

For example, the world movement and score counting could easily be done in the update method. The movement could be implemented depending on the passed time since last frame and the counting could be implemented depending on the pipe’s horizontal position. Even collision detection is so trivial that you don’t need the physics engine for that. On the other hand, look how easy it was to implement the bird’s behavior!

You would also normally not load all sprites into separate files but use texture atlasses instead (i.e. as many sprites as possible on one texture) because texture switches are an expensive operation on the graphics card.

From a software engineering perspective there is also plenty of improvement potential, like moving the score update functionality into a dedicated method, or even a subclass of SKLabelNode with dedicated increment/reset methods.

Conclusion

During the course of this tutorial, you’ve learned how to…

  • create a SpriteKit project with Xcode
  • load textures into SKTexture
  • create sprites with SKSpriteNode
  • create text with SKLabelNode
  • use different animation speeds to create the illusion of depth
  • use the SKSpriteNode‘s zPosition property to control rendering order
  • attach and configure physics bodies to nodes
  • configure the physics world
  • use SKAction to animate sprites, move the game world and control game states
  • control game flow using the SKNode.speed property
  • handle touches
  • detect and distinguish contacts between entities
  • structure the scene graph in a way that makes sense for the game world

If you think that something needs to be covered in more detail, feel free to leave a comment or contact me on Twitter (@digitalbreed). I will try to update the tutorial or respond to you directly.

If you liked this tutorial and you have some Bitcoins to spare, I would appreciate a tip at 1QByEN4aeEN1KKqikBFUGdgeg1ZCX6c1nr.

Download

I have pushed the tutorial code to GitHub.

Tomcat 7 and Nginx on Ubuntu 10.12

Tomcat 7 and Nginx on Ubuntu 10.12

Earlier last week, I installed Nginx with a Tomcat on a newly installed Ubuntu VPS. Unfortunately, although it comes with a lower memory footprint, it was noticably slower than my earlier Apache installation. It seemed like the simple proxying that I had in place was too slow. I decided to give the “APR based Apache Tomcat Native library” a try. Here’s what I did.

No signature of method addTo* is applicable

No signature of method addTo* is applicable

Last night, I started getting an exception in one of my pet projects, created with Grails:

No signature of method: package.Parent.addToChildren() is applicable for argument types: (package.Child) values: [package.Child : null]
Possible solutions: getChildren(). Stacktrace follows:
groovy.lang.MissingMethodException: No signature of method: package.Parent.addToChildren() is applicable for argument types: (package.Child) values: [package.Child : null]

I searched for the problem, read dozens of different hints regarding proper general ORM one-to-many setups, GORM-specific hasMany/belongsTo relationships, cascading, saving before adding, etc. All were different problems leading to the same exception.

My problem, however, was far more trivial. Here’s the code that made me want to tear my hair out.

class Parent {
	static hasMany = {
		children: Child
	}
}

Do you spot the mistake?

I used curly braces for the hasMany relationship. Groovy doesn’t complain at all, as it’s valid syntax. But to make GORM work the expected way, it should be square brackets:

class Parent {
	static hasMany = [
		children: Child
	]
}

I’ve lost two hours of my life to this one.

Enabling Tomcat NIO Connector with Grails 2.0

Enabling Tomcat NIO Connector with Grails 2.0

At dozens of different sources, even in Graeme Rocher’s corresponding Jira ticket, it says that you need to put grails.tomcat.nio=true into your Config.groovy file. I believed that, too, and it drove me nuts to see that the org.apache.coyote.http11.Http11NioProtocol class wasn’t even instantiated.

I had to review the commit logs to figure out that the property should actually be in the BuildConfig.groovy file.

Now I finally got the log messages that I expected to see…

| Loading Grails 2.0.0
| Configuring classpath.
| Environment set to development.....
| Packaging Grails application.....
| Running Grails application
| Enabling Tomcat NIO connector
http11.Http11NioProtocol Initializing ProtocolHandler ["http-nio-8080"]
| Server running. Browse to http://localhost:8080/...

MongoDB: can only have 1 index plugin / bad index key pattern

MongoDB: can only have 1 index plugin / bad index key pattern

While working with MongoDB and the MongoDB Java driver I got the following exception when attempting to iterate over a result set.

com.mongodb.MongoException: can only have 1 index plugin / bad index key pattern
at com.mongodb.MongoException.parse(MongoException.java:82)
at com.mongodb.DBApiLayer$MyCollection.__find(DBApiLayer.java:312)
at com.mongodb.DBCursor._check(DBCursor.java:369)
at com.mongodb.DBCursor._hasNext(DBCursor.java:498)
at com.mongodb.DBCursor.hasNext(DBCursor.java:523)

This exception drove me nuts. I checked the index definition in Java, which looked fine, compared it to the index result in Mongo shell (db.collectionName.getIndexes()), which looked fine too, made several desperate attempts to drop and recreate the index, re-index the collection, etc.

Then I cut down the DB query and recognized that removing my sort() call made a difference. Eventually it turned out that the sort order was specified as a String instead of an Integer, see below:

BasicDBObject query = ...
// WRONG:
// BasicDBObject sort = new BasicDBObject("column1", "1").append("column2", "-1");
// RIGHT:
BasicDBObject sort = new BasicDBObject("column1", 1).append("column2", -1);
mongoDB.getCollection("collectionName").find(query).sort(sort);
Using Grails without a database

Using Grails without a database

If you’re using Grails for a frontend without direct database access, there are four things you need to do.

  1. Remove Grails’ Hibernate plugin.
    grails uninstall-plugin hibernate
  2. Delete the datasource configuration file conf/DataSource.groovy
  3. Explicitly declare services as non-transactional. The default is true and your class methods would be proxied, but without the Hibernate plugin there is no transaction manager and the deployment will fail.
    class SomeService {
    	static transactional = false
    	// ...
    }
  4. Use command objects instead of domain objects, particularly if you need validation.
Deprecation of ConfigurationHolder in Grails 2

Deprecation of ConfigurationHolder in Grails 2

While porting my Grails applications to 2.0 RC1, I recognized that ConfigurationHolder is now deprecated. The new way to access the configuration is through dependency injection of the grailsApplication bean.

Before 2.0:

import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH
...
def value = CH.config.my.configEntry

With 2.0:

class MyService/MyController {
	def grailsApplication
	def method {
		def value = grailsApplication.config.my.configEntry
	}
}
Learning Grails the hard way: Facebook Authentication

Learning Grails the hard way: Facebook Authentication

Every now and then I try to explore a new programming language. Last year, I tried Scala, this year, I’m fiddling around with Grails. My first attempt was to try something I already implemented in other languages, like verifying Facebook’s signed_request. It’s fun to see what I tried to get it running and how a short version by a more experienced Groovy coder looks like.

Compare both versions after the break if you like.