Lucas Jensen (lujen14) and Thanusaan Rasiah (trasi14)

 

Introduction

2048 is an existing computer game in which the goal is to reach as high a score as possible. There are a multitude of free and probably paid alternative implementation of the concept, yet they mostly share the same concept.

In 2048 tiles are navigated up, down, left, or right typically by using the arrow keys on a keyboard or swiping on a smartphone. When navigating all tiles will be thrown as far in that direction as possible, ie. to the edge or next to existing tiles if they do not match. Matching tiles will join and double in value when they clash. The new value accumulated will be added to the score. After each move (navigation) a new tile with the lowest value of 2, spawns in a random unused grid field. The idea is to accumulate as high a score as possible before tiles eventually fill up the entire grid and navigation is no longer possible – exhausting possibilities for more clashes and ending the game.

Typically the difference between various implementations of this concept vary only in the graphic used for the tiles, ie. the numbers can be represented by pictures for a joyous experience, or in how high the tile values go. Originally the maximum value of a tile was 2048, but many games take it farther. Of course most of the games limited by a maximum value are games which used pictures for tiles as they require a bit more labour than just adding numbers.

An existing free 2048 game found at https://gabrielecirulli.github.io/2048/

The value of 2048 Tilt’it

2048 is first and foremost entertainment. It is a simple time killer game that is forever repeatable. However, it is also a logic puzzle of a certain simplicity. Logic puzzles are generally accepted as being helpful in stimulating and evolving the human brain and improving learning.

2048 Tilt’it adds a different level of interaction by replacing navigation with arrow keys or swipe with navigation by tilting a smartphone utilizing a gyroscope.

Depiction of a common gyroscope, not exactly what is found inside a smartphone though

 

Problem statement

All modern smartphones have built in gyroscopes. Many are unfamiliar with the benefits of gyroscopes in smartphones as most just use them to look at 3D kittens on Facebook. Gyroscopes can be used in a multitude of games to bring out a new level of interaction and thereby improve or temporarily alter the level of entertainment interaction that a game creates, better engaging the user. The aim of 2048 Tilt’it is to build a 2048 game on iOS wherein navigation is performed via tilting the smartphone by accessing the built in gyroscope capabilities.

 

Requirements

  • U1 – A highscore table must be available in a game menu
  • U2 – A way to start a new game must be available in a game menu
  • U3 – A way to continue a game should be available in a game menu
  • U4 – Tiles must be able to be navigated as far up, down, left, or right until colliding with an edge or another tile by tilting the smartphone
  • U5 – Tiles of equal value must join and accumulate their values on collision
  • U6 – Colliding tiles accumulates the score with the tiles accumulated value
  • U7 – The app should have sound to create awareness on actions and engage the user
  • T1 – Tilting must use the built in gyroscope capabilities
  • T2 – Highscores must be saved to a local database
  • T3 – The app should automatically size to fit the screen size of the smartphone

 

Methods

A quick brainstorm led to a conceptual design in the form of sketched prototypes on paper. A couple of friends were informally interviewed on their perception of the idea and sketches. The group typically considers building navigational prototypes in prototyping software or frameworks a bit of a waste of time as these are so easily done in the actual target platforms anyway. The first navigational prototype was built in Xcode for a quick initial impression of the app on an iPhone 5S. Properties and methods are found using a top-down approach. It is a simple game wherein most aspects are already specified in existing implementations of the base concept of 2048. First the data necessary for the views to be operational are identified and then the models are built from this data. At last when there is actually a grid and tiles to move around the controllers are adjusted to update the models based on input data from the gyroscope sensor.

 

Results

Brainstorm

The idea really came about from the nostalgic memories of maze ball games such as this one.

A maze ball game with wooden steering wheels, knobs

In this classic game, the goal was to get the metal ball from start to finish steering away from the many holes, which effectively resets the game state and ends the progress. Only by navigating successfully with the steering wheels on each side of the box a success would be had. Such a mechanism lies in the past with most people today owning a smartphone with a gyroscope. Utilizing the smartphone seems like a smarter alternative to carrying around a big wooden box just to play a single simple game.

There should be sound or haptic feedback on actions and events such as colliding tiles as these are often less distractful, quicker to pick up, and engage the user more than textual feedback.

 

Sketching

Some early “hand drawn” sketches for a prototype were developed. These give a simplistic view of each of the app’s menus.

Sketch of the main menu for the game
Sketch of the high score menu
Sketch of the actual 2048 game screen

 

Interviews

Here is what a couple of friends had to say about the concept in an informal interview.

“It is a new take on the game, that perhaps encourages you to play it again. But i would not play it in public on the bus or on the train, due to the added movement” – Chris

“This is the perfect addition the game always needed” – Ploug

 

Implementation

Diagram showing the MVC’s in the application. MainMenu, Gameview and Highscore ViewControllers are all controlled by an UINavigationController

Diagram of MVC(s)

Motion detection

Tilting of the phone for tile movement is detected using CoreMotion and CMMotionManager. When the game view has appeared, the motion tracking is started by invoking viewDidAppear(). The updateInterval for the closure callback from device motion is set to 0.2 seconds, which prevents a lot of unnecessary processing, yet keeps the navigation responsive. The closure defines how the game acts on the update data from each callback. The attitude pitch determines the axis offset upwards or downwards. Certain boundaries are used to determine if the player tilted the device upwards or downwards. Similarly the attitude roll can be used to determine device tilt to the left or right. The latest motion is stored in a variable to prevent executing an action multiple times on the same tilt. The device has to be reset to normal tilt state before tilting in the same direction again.

var motionManager = CMMotionManager()

override func viewDidAppear(_ animated: Bool) {
        motionManager.deviceMotionUpdateInterval = 0.2
        
        var lastMotion = ""
        motionManager.startDeviceMotionUpdates(to: OperationQueue.current!) { (data, error) in
            if myData.attitude.pitch <= 0.4 {
                    if lastMotion != "up" {
                        self.game.moveUp()
                    }
                    lastMotion = "up"
                }
                else if myData.attitude.pitch > 1.4 {
                    if lastMotion != "down" {
                        self.game.moveDown()
                    }
                    lastMotion = "down"
                }
                else if myData.attitude.roll <= -1 {
                    if lastMotion != "left" {
                        self.game.moveLeft()
                    }
                    lastMotion = "left"
                }
                else if myData.attitude.roll > 1 {
                    if lastMotion != "right" {
                        self.game.moveRight()
                    }
                    lastMotion = "right"
                }
                 else {
                    lastMotion = ""
                }
...
}

 

Game Graphics

Custom UIViews are used to draw the graphics of the game. A GameView class makes up the board of the game that generates TileViews. TileViews represent the tiles in each grid cell of the board.

 

override func draw(_ rect: CGRect) {
        let roundedRect = UIBezierPath(roundedRect: bounds, cornerRadius: 16.0)
        UIColor.init(red: 51/255, green: 51/255, blue: 0, alpha: 1).setFill()
        roundedRect.fill()
    }

 

The GameView draws a background with rounded corners and adds the tile subviews and manages their positions and size, drawing them with appropriate size and position no matter the screen size.

 

private func configureTile(tile: TileView, tilesPerRow: Int) {
        let sizePerTileTotal = bounds.maxX / CGFloat(tilesPerRow)
        let padding = sizePerTileTotal / 10
        let sizePerTile = sizePerTileTotal - padding * 2
        
        let labelRect = CGRect(x: 0, y: 0, width: sizePerTile, height: sizePerTile)
        tile.frame = labelRect
        tile.label.frame = labelRect
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        let sizePerTileTotal = bounds.maxX / CGFloat(tiles.count)
        let padding = sizePerTileTotal / 10
        let sizePerTile = sizePerTileTotal - padding * 2
        
        for y in 0..<tiles.count {
            for x in 0..<tiles.count {
                configureTile(tile: tiles[y][x], tilesPerRow: tiles.count)
                tiles[y][x].frame.origin = bounds.origin.offsetBy(dx: padding+CGFloat(x)*sizePerTile+padding*CGFloat(x)*2, dy: padding+CGFloat(y)*sizePerTile+padding*CGFloat(y)*2)
            }
        }
    }

The tiles needs to be redrawn everytime the value inside them changes, therefore setNeedsDisplay() and setNeedsLayout() are called when the value is changed using didSet

 

var value: Int = 0 {
        didSet {
            if value == 0 {
                label.text = ""
            } else {
                label.text = String(value)
            }
            setNeedsDisplay()
            setNeedsLayout()
        }
    }

Source code

https://bitbucket.org/iosprogrammingsdu/2048tiltit/src/master/

Video

 

Discussion

Results

U2, U4, U5, U6, and T1 have been successfully implemented. These are the basic pillars for the games functionality. Those are the most important requirements from a prototype to beta release perspective.

U1 and T2 are fulfilled by keeping the score in a local database, and the list of the scores can be seen on highscore page.

U3 has been implemented on a session basis, so that it is possible to leave the game page and for example go to the highscore page, and then go back to the main menu and choose to continue an existing game. However it is not saved when exiting the app.

T3 has been implemented, so the game looks good on all types of screen sizes and aspect ratios.

U7 has not been implemented.

Evaluation

The app certainly lives up to our friends expectations. They understand that the game is more like a functional prototype or an app in beta release. The game is in a playable and enjoyable state, which can be polished into an actual public release.

 

Pros/Cons – comparison to rivals

To the knowledge of the project group, no rivals have come up with a similar or challenging design that can hurt the success of the concepts employed within this specific implementation of the 2048 game.

That is, the pro is that the game is more interactive and more entertaining to play than rival implementations. The con is that it can require a bit more space to navigate and that such a game might often be played while on the move, eg. by bus or train where space can be a bit limited or public perception can have a negative impact on the user’s entertainment.

 

Conclusion

The goal of improving upon an existing game by adding a twist to the controls of the game has been fulfilled. From the user feedback on the developed prototype it is clear that controlling by tilting creates a fun interaction with the game, and is enjoyable and fun to play.

 

Future improvement?

Create breathtaking animations and fun sounds.

Unlock animations and sound packages by playing or paying. Microtransactions $$$

Global leaderboard

Challenge friends

 

Leave a Reply