Christopher Christensen – chrch17@student.sdu.dk

Peter Obling – peobl17@student.sdu.dk

Introduction

This report aims to show the creating of an iOS application for the course iOS Programming at University of Southern Denmark. The aim was to create an application using Swift and XCode which uses at least 1 sensor. 

FlyingPiglet is a sidescrolled application that reminds of the successful game called “Flappy Bird”.  The idea is to have a Piglet of our main character flying over the landscape avoiding autogenerated obstacles. FlyingPiglet is going to be flying towards the left side of the screen, instead of the traditional right side to make it a bit more challenging and interesting to play. The piglet will have a constant speed while flying. We will make use of the microphone sensor of the phone to register voice volume, that will make the piglet flying, instead of the traditional way of tapping the screen. There is going to be a score measured in total time flying, and this will be stored locally and stored in a highscore tableview.

Methodes and materials

We used different methods and materials for the creation of the application:

Brainstorming, we used time to discuss all different kind of games we wanted to make, pointed some of the most feasible of this scale to make and which sensor would make sense to use for the application. One by one, we excluded more and more ideas until we had FlyingPiglet as the project.

We made use of paper prototypes in the beginning for the initial design and we made some wireframes to further present the concept for testing the idea.

Use-case diagrams were used to show core abilities in the application.

We used a couple of frameworks such as:

  • SpriteKit, this SpriteKit framework makes it easy to create high-performance, battery-efficient 2D games. It contains integration with SceneKit, advanced physics, effects and animations.
  • UIKit, provides the required infrastructure for our iOS app. This contains window and view architecture for implementing our interface, event handling and managing interactions.
  • GamePlayKit, provides foundational tools and technologies for building games and gives us features as character movement.
  • AVFoundation, to impliment the microphone and convert the input to a value which could be measured in the application

Evaluation

The idea of making prototypes and testing these for families and friends, to give a better experience.

Results

The brainstorm sessions resulted in ideas of making a game like “Flappy Bird” controlled by the microphone sensor. The objective of this gameplay is to keep flying as long as possible to the left side and to get a higher time score, without colliding into the obstacles and the ground.

Prototypes

In relation to the brainstorm sessions we had, we made a couple of low-fi prototypes that are kind of similar to one another. Prototype 1 consists of a paper prototype that shows the basic screens like, main screen, high-score scene, gamescene and settings scene.

Prototype 2 is more of a high-fi prototype with more refined looks and the look that we were going for appearance-wise:

These 2 prototypes were not playable, these were merely rough sketches of how the game would look like. Meanwhile we later made a implementation of the game, with the basic navigation working.

This is the use-case diagram of core player interaction in our application “FlyingPiglet”. You are the actor/user and the only features you can click are “Play”, “Settings”, “Help” and “Highscore”. When pressed “Play” the game will start and when you die, you will be redirected to the main menu. “Settings” is a simple page, where you are mainly able to set difficulty of the game.

Requirements

Functional requirements

  • The player should be able to control the game using the microphone
  • The player should be able to go back to main menu after dying
  • The player should be able to set the difficulty to either easy, normal or hard
  • The player should be able to get a score
  • and get new highscores

Non-functional requirements:

  • Highscore should be stored locally
  • The game should become more and more difficult over time, with more obstacles

Architecture

The architecture has been worked on several times. We tried to separate all the different classes in different Swift files to keep them separate and for the MVC part.
It led to this SKS diagram:

Implementation

Results

//
//  MSButtonNode.swift
//  Make School
//
//  Copyright (c) 2017 Make School. All rights reserved.
//
//https://github.com/MakeSchool-Tutorials/Hoppy-Bunny-SpriteKit-Swift-Solution/blob/master/HoppyBunny/MSButtonNode.swift
//

import SpriteKit

enum MSButtonNodeState {
    case MSButtonNodeStateActive, MSButtonNodeStateSelected, MSButtonNodeStateHidden
}

class MSButtonNode: SKSpriteNode {
    
    /* Setup a dummy action closure, for debugging if its not working */
    var selectedHandler: () -> Void = { print("No button action set") }
    
    /* Button state management */
    var state: MSButtonNodeState = .MSButtonNodeStateActive {
        didSet {
            switch state {
            case .MSButtonNodeStateActive:
                /* Enable touch */
                self.isUserInteractionEnabled = true
                
                /* Visible */
                self.alpha = 1
                break
            case .MSButtonNodeStateSelected:
                /* Semi transparent */
                self.alpha = 0.7
                break
            case .MSButtonNodeStateHidden:
                /* Disable touch */
                self.isUserInteractionEnabled = false
                
                /* Hide */
                self.alpha = 0
                break
            }
        }
    }
    
    /* Support for NSKeyedArchiver (loading objects from SK Scene Editor */
    required init?(coder aDecoder: NSCoder) {
        
        /* Call parent initializer e.g. SKSpriteNode */
        super.init(coder: aDecoder)
        
        /* Enable touch on button node */
        self.isUserInteractionEnabled = true
    }
    
    // MARK: - Touch handling on Began
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        state = .MSButtonNodeStateSelected
    }
    
    //touch handling on Ended
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        selectedHandler()
        state = .MSButtonNodeStateActive

These lines of code makes it possible to make our PNG files to have properties as buttons. We do this by taking a PNG-file in the SKScene and give it a Custom Class Name “MSButtonNode”. By doing this, you can manipulate the chosen PNG in the corresponding Swift file and assign a function to for example load a specific scene. This has been the general use for the navigation in the app.

override func update(_ currentTime: TimeInterval) {
            // Called before each frame is rendered
            if isGameStarted == true{
                if isDied == false{
                    enumerateChildNodes(withName: "background", using: ({
                        (node, error) in
                        let bg = node as! SKSpriteNode
                        bg.position = CGPoint(x: bg.position.x - 2, y: bg.position.y)
                        if bg.position.x <= -bg.size.width {
                            bg.position = CGPoint(x:bg.position.x + bg.size.width / 2,
                                                  y:bg.position.y)
                        }
                    }))
                    
                    // * Herunder bruger vi .updateMeters() og .everagePower(forChannel: 0) til at udtrække en værdi der er tilsvarende til hvor højt der bliver råbt ind i microfonen.
                    audioRecorder.updateMeters()
                    let power = audioRecorder.averagePower(forChannel: 0)
                    print(power)
                    
              //* Hvis der bliver råbt højt nok vil grisen bevæge sig oppad.
                   if power > -15 {
                       pig.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
                       pig.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 35))
                    
                   }
                    
                }
              
            }
        }

The Code above shows the update function while the game is running. The first part of the code handles the background moving from right to left on screen. The second part of the code we use audiRecorder.updateMeters() to update the value our recorder gets us. We then use audioRecorder.averagePower(forChannel: 0) that returns the average power in decibels that are being recorded. We then use a simple if statement to trigger the movement of the flying piglet.

Discussion

We ended up with an application as we earlier described. A game similar to Flappy Bird, but working with the microphone sensor as the primary gameplay-sensor. The play pattern is not super smooth with the microphone input, but works pretty decently. Sometimes for some reason the game crashes after dying, we believe that is it somekind of memory overload but not sure how to fix it. If this happens, make sure to relaunch the game.

The game is also going to the left side as intended. We succeeded in most of our goals, but did not get the highscore list sorted in the best times/scores gotten. Instead we used the UserDefaults class to store highscore integer, using UserDefaults we stor locally on a single device. We did not succeed in getting the level to get harder the longer you fly through the landscape. We did not have time for getting the Setting scene to working either, so you can not choose other difficulties than the one already existing.

But most importantly, the essential gameplay is working, which was the main goal for this project. We think when we have worked the missing parts, we will have an application that can be competitive in the market. If not, it would make a cool drinking game, as some of our test persons pointed out as the main sales reason.

Things still to be implemented in future work:

  • Highscore list sorting on best times/scores
  • Level getting harder the longer you fly

Working settings scene where you are able to change the difficulty

Conclusion

The team managed to make a game where the player use the microphone to jump and pass through obstacles. There are still are couple of features to be improved on, but overall the apps most important functionalities is implemented and working.

References

Making PNG-files to “buttons”:

https://github.com/MakeSchool-Tutorials/Hoppy-Bunny-SpriteKit-Swift-Solution/blob/master/HoppyBunny/MSButtonNode.swift

How to make a Flappy Bird game:

How to make a programmed tableview:

https://stackoverflow.com/questions/41626348/using-a-uitableview-in-spritekit

Inspiration for saving and retrieving score:
https://www.youtube.com/watch?v=CLmOoHzIekw

Leave a Reply