POSTS
Tappy Plane Postmortem
Over the weekend I tried my hand at making a clone of Flappy Bird on iOS using Swift and SpriteKit. The game uses the excellent graphics from Kenney, which are public domain although well worth leaving a tip for.
The first thing I noticed was how slow the iOS simulator was when it came to graphics rendering. The development experience became a lot smoother once I started running the game as a Mac app. I’ve not noticed any difference in behaviour so far, other than having to receive input as a mouse click rather than a touch.
Initially, I enjoyed being able to get a lot done using just the sprite kit tools in Xcode. Using the tools, one can create the entire scene and even add animation without writing any code. Physics bodies can be previewed as well, and very accurate collision are supported by SpriteKit via alpha masks.
Once I started adding gameplay logic, I quickly ran into the more interesting/rough edges of SpriteKit. In SpriteKit, instead of having to manipulate each game object frame by frame, we can use SpriteKit actions to describe how we want that object to change over time. For my game I wanted to create an infinite scrolling background by having two instances of an image (lets call them A and B) moving from right to left and looping them back again once they had moved off the visible screen. However, when image A was moved back to the original position again, it didn’t seem to fit with B seamlessly and I could see micro gaps in the background. It turns out that the precise sprite position is somewhat unpredictable when using an action to move a sprite, so I had to take the position of B into account when moving A back.
Reference nodes also become necessary once a game gets slightly more complicated, because they allow you to create multiple instances of the same object and hence avoid duplication. However, they ended up being quite tricky to use as well because each nested node has its own coordinate system. I wanted to examine the location of a node that was contained within a reference node with respect to the overall scene, but the SKNode.convertPoint method doesn’t seem to work well on child nodes with more than 1 level of nesting. I had to work around this problem by only moving the reference node itself, which felt somewhat limiting.
The physics body of a sprite also gets quite wonky whenever it gets scaled, and I ran into issues such as bodies not being aligned with the actual image. I’m not sure if this was because I was making use of precise alpha masks for collision or not. In any case, I also worked around this by recreating the physics body every time I resized the sprite, which meant that I could no longer tweak the physics using the scene builder tools.
The last problem manifested only on iOS, in which SpriteKit would unpause all actions whenever an app was exited (via the home button) and re-entered again, regardless of their state beforehand. When the game is first started, I have a “ready” screen that starts the game only when pressed (just like the real Flappy Bird!) so I needed some actions to remain paused when in this state. After exiting and resuming the app, these actions would unpause by themselves and break the game. I gave up on finding a fix for this in the end.
If you would like to try out the Mac version of Tappy Plane, I’ve put up the binary here.
-
gamedev