After a few months learning Swift and UIKit, as well as playing with some of the iOS libraries it was finally time to get acquainted with SpriteKit, Apple’s framework for creating 2D games.
I worked on an iteration of the classic Pong, as the core game loop is very basic. You can follow the exact step by step by seeing all the commits and pull requests against my own repository.
This is my personal workflow, so it may be helpful or not in your case: I found out that opening a GIT repository with the initial commit and then self-report bugs and enhancements works pretty well for me. I just add a
#warning into Xcode with a link to the issue so is easier to catch when building the app:
Then is just a matter of opening a new branch, work on the changes, and submit a pull request as I would do with a collaborative project:
Alright, let’s jump into the development process.
Initial game core loop:
All code is inside the GameScene.swift file, overriding the following SpriteKit methods:
- didMove(): Implements any custom behaviour for your scene when it is about to be presented by a view.
- touchesBegan(): Determines where is the screen touched. Deals with paddle movement.
- touchesMoved(): Determines where is the screen touched and dragged. Same as before, deals with paddle movement.
- update(): Called every frame. We keep the code a minimum here for performance.
As custom methods we have:
- startGame(): Sets the game initial stuff, like positioning and score.
- addScore(): Deals with scoring, resetting ball position after scoring, etc, …
We use SKSpriteNode() and SKLabelNode() to create the paddles, the ball, and the scoring labels. Add a SKPhysicsBody() to the elements who should respond to physics, and with that we have the [ initial commit ]:
So it doesn’t look so empty I’m adding some sort of parallax backgrounds, adding this to didMove() as we want them loading when setting up the scene. [ PR ] and [ PR ] .The background consists of 3 different layers: A base, and then 2 moving layers that move at different speeds:
- createParallaxBackGround(): Static base background.
- createParallaxBaseLayer(): A SKTexture that moves in one direction at certain speed.
- createParallaxDetailLayer(): Another, more detailed SKTexture that moves in the same direction at higher speed.
Scoring labels are a bit annoying in the middle of the screen, let’s do them to appear only when we score, and add some animation to it [ PR ] . This is done in the following method:
- animateLabels(): This runs a SKAction.sequence with all the animations the labels will go through when score is increased: unhide the label, scale it up, scale it down, wait a bit, hide it again.
Let’s make an easy change that will improve the game playability a bit, right now when the game is reset ( when any player scores ) the ball will always re-spawn in the same place, will go in the same direction, and with the same angle and speed, which not only is 100% predictable but also introduces a bug where the enemy can get stuck on an infinite positional loop. We’l fix this by adding some randomization via a helper function [ PR ]
- randomize() : We pass this function ( rather than constants ) to the ball position and impulse methods and will return a random number within a given range.
Refactor, clean up, and comments
And that’s it! Now is just time to refactor some method names and variables to make everything clearer, add some comments where needed, clean up overall and push the changes [ Commit ] . There’s always iterations that can be done: Adding Unit Tests, more playability, scorecard, different screens, settings, different graphics, etc, … but as a base game to experiment with SpriteKit it accomplishes its objective.
Got any question? Feel free to drop a comment below.