How to create a vertical scrolling menu in spritekit?

后端 未结 4 1310
悲&欢浪女
悲&欢浪女 2020-12-02 13:56

I\'m looking to create a shop in my game (In SpriteKit) with buttons and images, but I need the items to be scrollable so the player can scroll up and down the shop (Like a

4条回答
  •  攒了一身酷
    2020-12-02 14:39

    Here's the code we used to simulate UIScrollView behavior for SpriteKit menus.

    Basically, you need to use a dummy UIView that matches the height of the SKScene then feed UIScrollView scroll and tap events to the SKScene for processing.

    It's frustrating Apple doesn't provide this natively, but hopefully no one else has to waste time rebuilding this functionality!

    class ScrollViewController: UIViewController, UIScrollViewDelegate {
        // IB Outlets
        @IBOutlet weak var scrollView: UIScrollView!
    
        // General Vars
        var scene = ScrollScene()
    
        // =======================================================================================================
        // MARK: Public Functions
        // =======================================================================================================
        override func viewDidLoad() {
            // Call super
            super.viewDidLoad()
    
            // Create scene
            scene = ScrollScene()
    
            // Allow other overlays to get presented
            definesPresentationContext = true
    
            // Create content view for scrolling since SKViews vanish with height > ~2048
            let contentHeight = scene.getScrollHeight()
            let contentFrame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: contentHeight)
            let contentView = UIView(frame: contentFrame)
            contentView.backgroundColor = UIColor.clear
    
            // Create SKView with same frame as , must manually compute because  frame not ready at this point
            let scrollViewPosY = CGFloat(0)
            let scrollViewHeight = UIScreen.main.bounds.size.height - scrollViewPosY
            let scrollViewFrame = CGRect(x: 0, y: scrollViewPosY, width: UIScreen.main.bounds.size.width, height: scrollViewHeight)
            let skView = SKView(frame: scrollViewFrame)
            view.insertSubview(skView, at: 0)
    
            // Configure 
            scrollView.addSubview(contentView)
            scrollView.delegate = self
            scrollView.contentSize = contentFrame.size
    
            // Present scene
            skView.presentScene(scene)
    
            // Handle taps on 
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(scrollViewDidTap))
            scrollView.addGestureRecognizer(tapGesture)
        }
    
        // =======================================================================================================
        // MARK: UIScrollViewDelegate Functions
        // =======================================================================================================
        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            scene.scrollBy(contentOffset: scrollView.contentOffset.y)
        }
    
    
        // =======================================================================================================
        // MARK: Gesture Functions
        // =======================================================================================================
        @objc func scrollViewDidTap(_ sender: UITapGestureRecognizer) {
            let scrollViewPoint = sender.location(in: sender.view!)
            scene.viewDidTapPoint(viewPoint: scrollViewPoint, contentOffset: scrollView.contentOffset.y)
        }
    }
    
    
    
    class ScrollScene : SKScene {
        // Layer Vars
        let scrollLayer = SKNode()
    
        // General Vars
        var originalPosY = CGFloat(0)
    
    
        // ================================================================================================
        // MARK: Initializers
        // ================================================================================================
        override init() {
            super.init()
        }
    
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
    
        // ================================================================================================
        // MARK: Public Functions
        // ================================================================================================
        func scrollBy(contentOffset: CGFloat) {
            scrollLayer.position.y = originalPosY + contentOffset
        }
    
    
        func viewDidTapPoint(viewPoint: CGPoint, contentOffset: CGFloat) {
            let nodes = getNodesTouchedFromView(point: viewPoint, contentOffset: contentOffset)
        }
    
    
        func getScrollHeight() -> CGFloat {
            return scrollLayer.calculateAccumulatedFrame().height
        }
    
    
        fileprivate func getNodesTouchedFromView(point: CGPoint, contentOffset: CGFloat) -> [SKNode] {
            var scenePoint = convertPoint(fromView: point)
            scenePoint.y += contentOffset
            return scrollLayer.nodes(at: scenePoint)
        }
    }
    

提交回复
热议问题