2020-05-24 21:56:11 -06:00
|
|
|
//
|
|
|
|
// GameViewController.swift
|
|
|
|
// Privyet
|
|
|
|
//
|
|
|
|
// Created by Amy Bowersox on 5/23/20.
|
|
|
|
// Copyright © 2020 Erbosoft Metaverse Design Solutions. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
import UIKit
|
|
|
|
import SpriteKit
|
|
|
|
import GameplayKit
|
|
|
|
|
|
|
|
class GameViewController: UIViewController, PrivyetDelegate, UIGestureRecognizerDelegate {
|
|
|
|
var scene: GameScene!
|
|
|
|
var privyet: Privyet!
|
2020-05-28 13:04:24 -06:00
|
|
|
var bucketRect: CGRect!
|
2020-05-24 21:56:11 -06:00
|
|
|
var panPointReference: CGPoint?
|
|
|
|
|
|
|
|
@IBOutlet weak var scoreLabel: UILabel!
|
|
|
|
@IBOutlet weak var levelLabel: UILabel!
|
|
|
|
|
|
|
|
override func viewDidLoad() {
|
|
|
|
super.viewDidLoad()
|
|
|
|
|
|
|
|
// Configure the view
|
|
|
|
let skView = view as! SKView
|
|
|
|
skView.isMultipleTouchEnabled = false
|
|
|
|
|
|
|
|
// Create and configure the scene
|
|
|
|
scene = GameScene(size: skView.bounds.size)
|
|
|
|
scene.scaleMode = .aspectFill
|
|
|
|
|
2020-05-28 13:04:24 -06:00
|
|
|
bucketRect = scene.rectForBucket()
|
|
|
|
print("Computed bucket rectangle = \(bucketRect!)")
|
|
|
|
|
2020-05-24 21:56:11 -06:00
|
|
|
scene.tick = didTick
|
|
|
|
|
|
|
|
privyet = Privyet()
|
|
|
|
privyet.delegate = self
|
|
|
|
privyet.beginGame()
|
|
|
|
|
|
|
|
// Present the scene
|
|
|
|
skView.presentScene(scene)
|
|
|
|
}
|
|
|
|
|
|
|
|
override var prefersStatusBarHidden: Bool {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:10:50 -06:00
|
|
|
// Called when the user taps the screen
|
2020-05-24 21:56:11 -06:00
|
|
|
@IBAction func didTap(_ sender: UITapGestureRecognizer) {
|
2020-05-28 13:04:24 -06:00
|
|
|
let tapLoc = sender.location(in: view)
|
|
|
|
if bucketRect.contains(tapLoc) {
|
|
|
|
privyet.rotateShape()
|
|
|
|
}
|
2020-05-24 21:56:11 -06:00
|
|
|
}
|
|
|
|
|
2020-05-27 11:10:50 -06:00
|
|
|
// Called when the user slides their finger across the screen
|
2020-05-24 21:56:11 -06:00
|
|
|
@IBAction func didPan(_ sender: UIPanGestureRecognizer) {
|
|
|
|
let currentPoint = sender.translation(in: self.view)
|
|
|
|
if let originalPoint = panPointReference {
|
|
|
|
if abs(currentPoint.x - originalPoint.x) > (BlockSize * 0.9) {
|
|
|
|
if sender.velocity(in: self.view).x > CGFloat(0) {
|
|
|
|
privyet.moveShapeRight()
|
|
|
|
panPointReference = currentPoint
|
|
|
|
} else {
|
|
|
|
privyet.moveShapeLeft()
|
|
|
|
panPointReference = currentPoint
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if sender.state == .began {
|
|
|
|
panPointReference = currentPoint
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:10:50 -06:00
|
|
|
// Called when the user swipes the screen in a downward direction
|
2020-05-24 21:56:11 -06:00
|
|
|
@IBAction func didSwipe(_ sender: UISwipeGestureRecognizer) {
|
|
|
|
privyet.dropShape()
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:10:50 -06:00
|
|
|
// Used to allow multiple gesture recognizers to be used simultaneously
|
2020-05-24 21:56:11 -06:00
|
|
|
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:10:50 -06:00
|
|
|
// Used to prioritize one gesture recognizer over another
|
2020-05-24 21:56:11 -06:00
|
|
|
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
|
|
|
if gestureRecognizer is UISwipeGestureRecognizer {
|
|
|
|
if otherGestureRecognizer is UIPanGestureRecognizer {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
} else if gestureRecognizer is UIPanGestureRecognizer {
|
|
|
|
if otherGestureRecognizer is UITapGestureRecognizer {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:10:50 -06:00
|
|
|
// Called once per game tick (interval over which blocks drop)
|
2020-05-24 21:56:11 -06:00
|
|
|
func didTick() {
|
|
|
|
privyet.letShapeFall()
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:10:50 -06:00
|
|
|
// Advances the "next' and "falling" shapes and places them on the screen
|
2020-05-24 21:56:11 -06:00
|
|
|
func nextShape() {
|
|
|
|
let newShapes = privyet.newShape()
|
|
|
|
guard let fallingShape = newShapes.fallingShape else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
self.scene.addPreviewShapeToScene(shape: newShapes.nextShape!) { }
|
|
|
|
self.scene.movePreviewShape(shape: fallingShape) {
|
|
|
|
self.view.isUserInteractionEnabled = true
|
|
|
|
self.scene.startTicking()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:10:50 -06:00
|
|
|
// Called when the game starts
|
2020-05-24 21:56:11 -06:00
|
|
|
func gameDidBegin(privyet: Privyet) {
|
|
|
|
levelLabel.text = "\(privyet.level)"
|
|
|
|
scoreLabel.text = "\(privyet.score)"
|
|
|
|
scene.tickLengthMillis = TickLengthLevelOne
|
|
|
|
|
|
|
|
// The following is false when restarting a new game
|
|
|
|
if privyet.nextShape != nil && privyet.nextShape!.blocks[0].sprite == nil {
|
|
|
|
scene.addPreviewShapeToScene(shape: privyet.nextShape!) {
|
|
|
|
self.nextShape()
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
nextShape()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:10:50 -06:00
|
|
|
// Called when the game ends
|
2020-05-24 21:56:11 -06:00
|
|
|
func gameDidEnd(privyet: Privyet) {
|
|
|
|
view.isUserInteractionEnabled = false
|
|
|
|
scene.stopTicking()
|
|
|
|
scene.playSound(sound: "Sounds/gameover.mp3")
|
|
|
|
scene.animateCollapsingLines(linesToRemove: privyet.removeAllBlocks(), fallenBlocks: privyet.removeAllBlocks()) {
|
|
|
|
privyet.beginGame()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:10:50 -06:00
|
|
|
// Called when the game advances in level (gets faster)
|
2020-05-24 21:56:11 -06:00
|
|
|
func gameDidLevelUp(privyet: Privyet) {
|
|
|
|
levelLabel.text = "\(privyet.level)"
|
|
|
|
if scene.tickLengthMillis >= 100 {
|
|
|
|
scene.tickLengthMillis -= 100
|
|
|
|
} else if scene.tickLengthMillis >= 50 {
|
|
|
|
scene.tickLengthMillis -= 50
|
|
|
|
}
|
|
|
|
scene.playSound(sound: "Sounds/levelup.mp3")
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:10:50 -06:00
|
|
|
// Called when a shape is "dropped"
|
2020-05-24 21:56:11 -06:00
|
|
|
func gameShapeDidDrop(privyet: Privyet) {
|
|
|
|
scene.stopTicking()
|
|
|
|
scene.redrawShape(shape: privyet.fallingShape!) {
|
|
|
|
privyet.letShapeFall()
|
|
|
|
}
|
|
|
|
scene.playSound(sound: "Sounds/drop.mp3")
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:10:50 -06:00
|
|
|
// Called when a shape "lands" on top of existing blocks or at the bottom of the bucket
|
2020-05-24 21:56:11 -06:00
|
|
|
func gameShapeDidLand(privyet: Privyet) {
|
|
|
|
scene.stopTicking()
|
|
|
|
self.view.isUserInteractionEnabled = false
|
|
|
|
let removedLines = privyet.removeCompletedLines()
|
|
|
|
if removedLines.linesRemoved.count > 0 {
|
|
|
|
self.scoreLabel.text = "\(privyet.score)"
|
|
|
|
scene.animateCollapsingLines(linesToRemove: removedLines.linesRemoved, fallenBlocks: removedLines.fallenBlocks) {
|
|
|
|
self.gameShapeDidLand(privyet: privyet)
|
|
|
|
}
|
|
|
|
self.scene.playSound(sound: "Sounds/bomb.mp3")
|
|
|
|
} else {
|
|
|
|
nextShape()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-27 11:10:50 -06:00
|
|
|
// Called when a shape moves on the screen
|
2020-05-24 21:56:11 -06:00
|
|
|
func gameShapeDidMove(privyet: Privyet) {
|
|
|
|
scene.redrawShape(shape: privyet.fallingShape!) { }
|
|
|
|
}
|
|
|
|
}
|