     }
   }
   
-  // TODO: Add code for player movement here
+  // TODO: Uncomment code for player movement here
+  func movePlayerInDirection(direction: MoveDirection) {
+    
+    switch gameState {
+    case GameState.WaitingForFirstTap:
+      
+      // Start playing
+      switchToPlaying()
+      movePlayerInDirection(direction)
+      break
+      
+    case GameState.Playing:
+      
+      // Determine if the new position is a valid position
+      var newPlayerGridCol = playerGridCol
+      var newPlayerGridRow = playerGridRow
+      
+      switch direction {
+      case .Forward:
+        newPlayerGridRow += 1
+        break;
+      case .Backward:
+        newPlayerGridRow -= 1
+        break
+      case .Left:
+        newPlayerGridCol -= 1
+        break
+      case .Right:
+        newPlayerGridCol += 1
+      }
+      
+      // Determine the type of tile at new position
+      let type = levelData.gameLevelDataTypeForGridPosition(column: newPlayerGridCol, row: newPlayerGridRow)
+      
+      if type == GameLevelDataType.Invalid || type == GameLevelDataType.Obstacle {
+        // Invalid - do not move
+        // println("Invalid move")
+        
+      } else {
+        // Valid - move
+        // println("Valid move to \(newPlayerGridCol), \(newPlayerGridRow)")
+        
+        playerGridCol = newPlayerGridCol
+        playerGridRow = newPlayerGridRow
+        
+        // Move the player to new position
+        var newPlayerPosition = levelData.coordinatesForGridPosition(column: playerGridCol, row: playerGridRow)
+        newPlayerPosition = SCNVector3(x: newPlayerPosition.x, y: 0.1, z: newPlayerPosition.z)
+        
+        // Move the player using an action
+        let moveAction = SCNAction.moveTo(newPlayerPosition, duration: 0.2)
+        let jumpUpAction = SCNAction.moveBy(SCNVector3(x: 0.0, y: 0.2, z: 0.0), duration: 0.1)
+        jumpUpAction.timingMode = SCNActionTimingMode.EaseInEaseOut
+        let jumpDownAction = SCNAction.moveBy(SCNVector3(x: 0.0, y: -0.2, z: 0.0), duration: 0.1)
+        jumpDownAction.timingMode = SCNActionTimingMode.EaseInEaseOut
+        let jumpAction = SCNAction.sequence([jumpUpAction, jumpDownAction])
+        
+        // Play the action
+        player.runAction(moveAction)
+        playerModelNode.runAction(jumpAction)
+        
+        // Play jump sound
+        if let overlay = view.overlaySKScene {
+          overlay.runAction(soundJump)
+        }
+      }
+      
+      break
+      
+    case GameState.GameOver:
+      
+      // Switch to tutorial
+      switchToRestartLevel()
+      break
+      
+    case GameState.RestartLevel:
+      
+      // Switch to new level
+      // switchToWaitingForFirstTap()
+      break
+      
+    default:
+      break
+    }
+    
+  }
   
 }
  }
  
  
  func createLevelAtPosition(#position: SCNVector3) -> SCNNode {
    
    let levelNode = SCNNode()
    
    // Create light grass material
    let lightGrassMaterial = SCNMaterial()
    lightGrassMaterial.diffuse.contents = UIColor(red: 190.0/255.0, green: 244.0/255.0, blue: 104.0/255.0, alpha: 1.0)
    lightGrassMaterial.locksAmbientWithDiffuse = false
    
    // Create dark grass material
    let darkGrassMaterial = SCNMaterial()
    darkGrassMaterial.diffuse.contents = UIColor(red: 183.0/255.0, green: 236.0/255.0, blue: 96.0/255.0, alpha: 1.0)
    darkGrassMaterial.locksAmbientWithDiffuse = false
    
    // Create tree top material
    let treeTopMaterial = SCNMaterial()
    treeTopMaterial.diffuse.contents = UIColor(red: 118.0/255.0, green: 141.0/255.0, blue: 25.0/255.0, alpha: 1.0)
    treeTopMaterial.locksAmbientWithDiffuse = false
    
    // Create tree trunk material
    let treeTrunkMaterial = SCNMaterial()
    treeTrunkMaterial.diffuse.contents = UIColor(red: 185.0/255.0, green: 122.0/255.0, blue: 87.0/255.0, alpha: 1.0)
    treeTrunkMaterial.locksAmbientWithDiffuse = false
    
    // Create road material
    let roadMaterial = SCNMaterial()
    roadMaterial.diffuse.contents = UIColor.darkGrayColor()
    roadMaterial.diffuse.wrapT = SCNWrapMode.Repeat
    roadMaterial.locksAmbientWithDiffuse = false
    
    // First, create geometry for grass and roads
    for row in 0..<levelData.data.rowCount() {
      
      // HACK: Check column 5 as column 0 to 4 will always be obstacles
      let type = levelData.gameLevelDataTypeForGridPosition(column: 5, row: row)
      switch type {
      case GameLevelDataType.Road:
        
        // Create a road row
        let roadGeometry = SCNPlane(width: CGFloat(levelData.gameLevelWidth()), height: CGFloat(levelData.segmentSize))
        roadGeometry.widthSegmentCount = 1
        roadGeometry.heightSegmentCount = 1
        roadGeometry.firstMaterial = roadMaterial
        
        let roadNode = SCNNode(geometry: roadGeometry)
        roadNode.position = levelData.coordinatesForGridPosition(column: Int(levelData.data.columnCount() / 2), row: row)
        roadNode.rotation = SCNVector4(x: 1.0, y: 0.0, z: 0.0, w: -3.1415 / 2.0)
        levelNode.addChildNode(roadNode)
        
        break
        
      default:
        
        // Create a grass row
        let grassGeometry = SCNPlane(width: CGFloat(levelData.gameLevelWidth()), height: CGFloat(levelData.segmentSize))
        grassGeometry.widthSegmentCount = 1
        grassGeometry.heightSegmentCount = 1
        grassGeometry.firstMaterial = row % 2 == 0 ? lightGrassMaterial : darkGrassMaterial
        
        let grassNode = SCNNode(geometry: grassGeometry)
        grassNode.position = levelData.coordinatesForGridPosition(column: Int(levelData.data.columnCount() / 2), row: row)
        grassNode.rotation = SCNVector4(x: 1.0, y: 0.0, z: 0.0, w: -3.1415 / 2.0)
        levelNode.addChildNode(grassNode)
        
        // Create obstacles
        for col in 0..<levelData.data.columnCount() {
          let subType = levelData.gameLevelDataTypeForGridPosition(column: col, row: row)
          if subType == GameLevelDataType.Obstacle {
            // Height of tree top is random
            let treeHeight = CGFloat((arc4random_uniform(5) + 2)) / 10.0
            let treeTopPosition = Float(treeHeight / 2.0 + 0.1)
            
            // Create a tree
            let treeTopGeomtery = SCNBox(width: 0.1, height: treeHeight, length: 0.1, chamferRadius: 0.0)
            treeTopGeomtery.firstMaterial = treeTopMaterial
            let treeTopNode = SCNNode(geometry: treeTopGeomtery)
            let gridPosition = levelData.coordinatesForGridPosition(column: col, row: row)
            treeTopNode.position = SCNVector3(x: gridPosition.x, y: treeTopPosition, z: gridPosition.z)
            levelNode.addChildNode(treeTopNode)
            
            let treeTrunkGeometry = SCNBox(width: 0.05, height: 0.1, length: 0.05, chamferRadius: 0.0)
            treeTrunkGeometry.firstMaterial = treeTrunkMaterial
            let treeTrunkNode = SCNNode(geometry: treeTrunkGeometry)
            treeTrunkNode.position = SCNVector3(x: gridPosition.x, y: 0.05, z: gridPosition.z)
            levelNode.addChildNode(treeTrunkNode)
          }
        }
        
        break
      }
    }
    
    // Combine all the geometry into one - this will reduce the number of draw calls and improve performance
    let flatLevelNode = levelNode.flattenedClone()
    flatLevelNode.name = "Level"
    
    return flatLevelNode
  }
  
  
  // TODO: Add code to create player here
  
  
  
  // MARK: Game Play
  
  func didPlayerReachEndOfLevel() -> Bool {
    //return playerGridRow == levelData.data.rowCount() - 7
    return false
  }
  
  

  func handleTap(gesture: UIGestureRecognizer) {
    if let tapGesture = gesture as? UITapGestureRecognizer {
      // TODO: Add code to do movement here
      movePlayerInDirection(MoveDirection.Forward)
    }
  }
  
