Adventures in Swift: Making a blasting shoot’em up

For further fun and learning with Swift and game design, I decided to make a space shoot’em up in classic style for iOS. The code for the game can be fetched from this repository in GitHub: https://github.com/LarsBergqvist/BlasterMaster.git

BlasterMaster1

Game idea

The player commands a ship at the lower part of the screen and can move to the left and right to aim at enemies and upwards to trigger a thrust at the aliens spawning ground. The background moves slowly downwards which creates an illusion of constant upward movement. Evil invading aliens ships appear from the top of the screen and moves downwards, sometimes shooting red deadly laser beams. The player’s task is to laser-blast the aliens to infinity and beyond without being hit by the aliens ships or lasers.

Graphics

I found an excellent set of public domain space ships by Kenney here: http://opengameart.org/content/space-shooter-redux. This sprite set is huge which inspires me for a complete game with lots of different bad-ass aliens and different upgrades to the player’s ship. This blog/code example covers only a one level game, though.

Player interaction

I started out with an elaborate idea of game controls that should be placed at the bottom of the screen. While working on this, my oldest son walked by and I explained what I was doing. -“But why don’t you steer the ship by tilting the device? And tap anywhere to fire?”, he asked. Well…Ehrrm…Suddenly it was obvious that I am part of the old joystick generation and was desperately trying to emulate this with iOS. But the truth is, my idea and implementation sucked big time, especially on a small iPhone screen. So I switched to the youngster’s approach: no visible on-screen buttons, tilt to move the spaceship and tap anywhere to fire. This turned out to be a pretty good game interaction as it allowed for three-finger tapping for rapid firing (which is absolutely essential when the number of invading aliens are abundant).

Code design

The main classes in this game are:

  • StartScene, GameScene and GameOverScene – the three SKScenes for this simple one-level game
  • EnemySpawner – creates new alien ships at top of the screen with some randomness built-in. The rate of ships created is increased over time.
  • SpaceShip – this is the players ship which has actions for movement and emitting blue lasers.
  • Enemy – this represents an alien ship with a random start position and a random speed downwards the screen. Some enemy objects have the canFire property set which triggers a timer for recurring laser firing.
  • BackgroundMusic – a wrapper for playing the background music so that it can be re-used in the StartScene and in the GameScene.
  • LaserShot/EnemyShot – handles the laser shots from the player and the enemies
  • CollisionDetector – implements the didBeginContactDelegate, figures out what-hit-what and what should happen after a collision.
  • BackgroundGfx – this class handles the drawing and movement of background tiles so that there is an illusion of movement through space in the game.

Sound playback on an iOS device

One new area that I wanted to try out was sounds on iOS. I created a short looping background track with Arturia instruments in Logic Pro X and generated a few sound effects with Arturia’s Jupiter 8. Audio playback can be implemented in this way on an iOS device:

  • import AVFoundation to get access to the Audio-Visual framework
  • Access the AVAudioSession singleton for your app
  • Set a category on the session that defines how the audio from your app should interact with other audio on the device (which audio should be muted/ducked etc). Can be set early in the app startup code.
  • Set the session to active. Should be set in applicationDidBecomeActive so that it is reset after an application is put back as active app (the audio session could have been set inactive by other apps during this app’s inactivity).
  • Create an AVAudioPlayer with an argument to an URL for your audio (can be a resource path to an audio file dropped into your Xcode project)
  • Set options on the AVAudioPlayer object
  • Call prepareToPlay()
  • Call play()
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil);

var url = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("ArturiaMood1", ofType: "mp3")!)

var avPlayer = AVAudioPlayer(contentsOfURL: url, error: nil)
avPlayer.numberOfLoops = -1 // the sound will loop forever
avPlayer.volume = 0.1
avPlayer.prepareToPlay()
avPlayer.play()

In one of my apps, an action from the user changes the texture of a sprite and starts a sound. I wanted to change the texture back to normal after the sound was finished playing. This can be solved by letting a class implement the AVAudioPlayerDelegate protocol. An object of this class can then be set as the delegate property of the AVAudioPlayer object, and you will get a call to audioPlayerDidFinishPlaying when the audio playing is complete.

class GameScene: SKScene, AVAudioPlayerDelegate {

   var avPlayer = AVAudioPlayer()

   func playMySound(){
      let s = sounds[Int(nextSound)]
      var url = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(s, ofType: "wav")!)

      avPlayer = AVAudioPlayer(contentsOfURL: url, error: nil)
      avPlayer.prepareToPlay()
      avPlayer.play()
      avPlayer.delegate = self
 }

 func audioPlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool) {
    // action when sound is finished

 }

}

Further improvements

There are lots of ways to improve and build upon this game. My own list includes these features:

  • Implement a high-score list that can be stored on the device
  • Add more levels with increasing difficulty
  • Add goodies like enhanced ships and guns that the player can upgrade to after blasting certain items in the game
  • Implement a more AI-like behaviour of the EnemySpawner so that the aliens attack in an intelligent way

Feel free to clone and fork the code and build your own version of this shoot’em up app!

Game on!

5 Thoughts

    1. Hi, the ship gets directions and speed by readings from the accelerometer in processUserMotionForUpdate. The actual ship sprite movement takes place in the UpdateActions method in the SpaceShip class.
      The ship should move when the device is tilted left/right/up/down. I have only tested this on iPhone 5s and Ipad2. What device are you using?

      Like

      1. My test devise is iPhone 6, but I’m not run your app on it. Just on simulator. Thanks for your answer. It’s interesting to check it. I’ll check it on iPhone 6 and write the result. But I guess if you said that movement uses accelerometer it will be running ok.

        Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s