Search code examples
iosswiftscrollviewscene

SpriteKit, Swift 2.0 - ScrollView Missing from Scene Startup via Button


I recently implemented a scrollView into my GameViewController and it works really well, but the tutorial I looked at had only one scene which was the start up scene (GameScene) rather than a seperate scene which I'm going to be calling "Menu" so I managed to get it to launch the Menu scene rather than the regular "GameScene" but when I go from GameScene to the Menu scene with a button that I implemented in GameScene, the scrollview does not work, but it does show the pictures, but I just can't scroll through them.

My question is how do I get scrollView to work when I use the button (that is in GameScene) to go to the Menu scene?

This is the button (which is In GameScene)

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

    let touch: UITouch = touches.first!
    let location: CGPoint = touch.locationInNode(self)
    let node: SKNode = self.nodeAtPoint(location)


    if (node == menubutton) {

        let MenuScene = Menu(size: self.size, viewController: viewController)
        let transition = SKTransition.flipVerticalWithDuration(0.5)
        MenuScene.scaleMode = SKSceneScaleMode.AspectFill
        self.scene!.view?.presentScene(MenuScene, transition: transition) 

}

Here is my Menu scene:

import Foundation
import SpriteKit


let kMargin: CGFloat = 40

var backButton = SKSpriteNode()
var selectButton = SKSpriteNode()


class Menu: SKScene {

    let world2 = SKSpriteNode()

private var imageSize = CGSize.zero

private weak var viewController: GameViewController?


init(size: CGSize, viewController: GameViewController?) {
    self.viewController = viewController
    super.init(size: size)
}

required init?(coder aDecoder: NSCoder) {
    assert(false, "Use init(size:viewController:)")

    super.init(coder: aDecoder)
}


override func didMoveToView(view: SKView) {
    physicsWorld.gravity = CGVector.zero

    imageSize = SKSpriteNode(imageNamed: "card_level01").size

    let initialMargin = size.width/2
    let marginPerImage = kMargin + imageSize.width

    world2.size = CGSize(width: initialMargin*2 + (marginPerImage * 7), height: size.height)
    addChild(world2)

    for i in 1...8 {
        let sprite = SKSpriteNode(imageNamed: String(format: "card_level%02d", i))
        sprite.position = CGPoint(x: initialMargin + (marginPerImage * (CGFloat(i) - 1)), y: size.height / 2)
        world2.addChild(sprite)

    }
}

override func update(currentTime: NSTimeInterval) {
    viewController?.applyScrollViewToSpriteKitMapping()
}

Here is my GameViewController

import UIKit
import SpriteKit

class GameViewController: UIViewController {

var scrollView: UIScrollView!
var contentView: UIView!

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    let skView = view as! SKView

    if (skView.scene === Menu.self) {

        skView.showsFPS = true
        skView.showsNodeCount = true

        skView.ignoresSiblingOrder = true

        let scene = Menu(size: skView.bounds.size, viewController: self)
        scene.scaleMode = .AspectFill

        skView.presentScene(scene)

        scrollView = UIScrollView(frame: self.view.bounds)
        scrollView.delegate = self
        scrollView.contentSize = scene.world2.frame.size
        view.addSubview(scrollView)

        contentView = UIView(frame: CGRect(origin: CGPoint.zero, size: scene.world2.size))
        contentView.backgroundColor = UIColor.greenColor().colorWithAlphaComponent(0.2)
        scrollView.addSubview(contentView)

        applyScrollViewToSpriteKitMapping()

    }
}

func applyScrollViewToSpriteKitMapping() {

    let origin = contentView.frame.origin

    let skPosition = CGPoint(x: -scrollView.contentOffset.x + origin.x, y: -scrollView.contentSize.height + CGRectGetHeight(view.bounds) + scrollView.contentOffset.y - origin.y)


    let skView = view as! SKView
    if let scene = skView.scene as? Menu {
        scene.world2.position = skPosition

    }

}

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
        return UIInterfaceOrientationMask.Portrait
    } else {
        return UIInterfaceOrientationMask.All
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Release any cached data, images, etc that aren't in use.
}

override func shouldAutorotate() -> Bool {
    return true
}

override func prefersStatusBarHidden() -> Bool {
    return true
 }

}

extension GameViewController: UIScrollViewDelegate {


}

Solution

  • I recently helped another member with a similar question, check it out it might be helpful to you

    How to create a vertical scrolling menu in spritekit?

    In my way I am subclassing scroll view and therefore can add it to SKScenes directly rather than the view controllers.

    If you want the scrollView on more than 1 SKScene without duplicate code than need to subclass your SKScnenes

     class BaseScene: SKScene ...
     // Add scroll view 
    
     class Menu: BaseScene...
     class GameScene: BaseScene ...
    

    As a side note, you shouldn't really reference your viewController in your SKScenes, they shouldn't have to know about each other.