swift – 如何在spritekit中创建垂直滚动菜单?

我想用我的游戏(In SpriteKit)创建一个带有按钮和图像的商店,但是我需要这些项目可以滚动,这样玩家就可以在商店中上下滚动(就像一个UITableView,但每个都有多个SKSpriteNodes和SKLabelNodes)细胞).知道如何在SpriteKit中做到这一点吗?
承诺的第二个答案,我只是想出了问题.

我建议总是从我的gitHub项目中获取此代码的最新版本,因为我做了更改,因为这个答案,链接在底部.

第1步:创建一个新的swift文件并粘贴此代码

import SpriteKit

/// Scroll direction
enum ScrollDirection {
    case vertical // cases start with small letters as I am following Swift 3 guildlines.
    case horizontal
}

class CustomScrollView: UIScrollView {

// MARK: - Static Properties

/// Touches allowed
static var disabledTouches = false

/// Scroll view
private static var scrollView: UIScrollView!

// MARK: - Properties

/// Current scene
private let currentScene: SKScene

/// Moveable node
private let moveableNode: SKNode

/// Scroll direction
private let scrollDirection: ScrollDirection

/// Touched nodes
private var nodesTouched = [AnyObject]()

// MARK: - Init
init(frame: CGRect,scene: SKScene,moveableNode: SKNode) {
    self.currentScene = scene
    self.moveableNode = moveableNode
    self.scrollDirection = scrollDirection
    super.init(frame: frame)

    CustomScrollView.scrollView = self
    self.frame = frame
    delegate = self
    indicatorStyle = .White
    scrollEnabled = true
    userInteractionEnabled = true
    //canCancelContentTouches = false
    //self.minimumZoomScale = 1
    //self.maximumZoomScale = 3

    if scrollDirection == .horizontal {
        let flip = CGAffineTransformMakeScale(-1,-1)
        transform = flip
    }
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
   }
}

// MARK: - Touches
extension CustomScrollView {

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

    for touch in touches {
        let location = touch.locationInNode(currentScene)

        guard !CustomScrollView.disabledTouches else { return }

        /// Call touches began in current scene
        currentScene.touchesBegan(touches,withEvent: event)

        /// Call touches began in all touched nodes in the current scene
        nodesTouched = currentScene.nodesAtPoint(location)
        for node in nodesTouched {
            node.touchesBegan(touches,withEvent: event)
        }
    }
}

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

    for touch in touches {
        let location = touch.locationInNode(currentScene)

        guard !CustomScrollView.disabledTouches else { return }

        /// Call touches moved in current scene
        currentScene.touchesMoved(touches,withEvent: event)

        /// Call touches moved in all touched nodes in the current scene
        nodesTouched = currentScene.nodesAtPoint(location)
        for node in nodesTouched {
            node.touchesMoved(touches,withEvent: event)
        }
    }
}

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

    for touch in touches {
        let location = touch.locationInNode(currentScene)

        guard !CustomScrollView.disabledTouches else { return }

        /// Call touches ended in current scene
        currentScene.touchesEnded(touches,withEvent: event)

        /// Call touches ended in all touched nodes in the current scene
        nodesTouched = currentScene.nodesAtPoint(location)
        for node in nodesTouched {
            node.touchesEnded(touches,withEvent: event)
        }
    }
}

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

    for touch in touches! {
        let location = touch.locationInNode(currentScene)

        guard !CustomScrollView.disabledTouches else { return }

        /// Call touches cancelled in current scene
        currentScene.touchesCancelled(touches,withEvent: event)

        /// Call touches cancelled in all touched nodes in the current scene
        nodesTouched = currentScene.nodesAtPoint(location)
        for node in nodesTouched {
            node.touchesCancelled(touches,withEvent: event)
        }
     }
   }
}

// MARK: - Touch Controls
extension CustomScrollView {

     /// Disable
    class func disable() {
        CustomScrollView.scrollView?.userInteractionEnabled = false
        CustomScrollView.disabledTouches = true
    }

    /// Enable
    class func enable() {
        CustomScrollView.scrollView?.userInteractionEnabled = true
        CustomScrollView.disabledTouches = false
    }
}

// MARK: - Delegates
extension CustomScrollView: UIScrollViewDelegate {

    func scrollViewDidScroll(scrollView: UIScrollView) {

        if scrollDirection == .horizontal {
            moveableNode.position.x = scrollView.contentOffset.x
        } else {
            moveableNode.position.y = scrollView.contentOffset.y
        }
    }
}

这将构成UIScrollView的子类并设置它的基本属性.它有自己的触摸方法,它被传递到相关的场景.

第2步:在您想要使用它的相关场景中,您可以创建滚动视图和可移动节点属性

weak var scrollView: CustomScrollView!
let moveableNode = SKNode()

并将它们添加到didMoveToView中的场景中

scrollView = CustomScrollView(frame: CGRect(x: 0,y: 0,width: self.frame.size.width,height: self.frame.size.height),scene: self,moveableNode: moveableNode,scrollDirection: .vertical)
scrollView.contentSize = CGSizeMake(self.frame.size.width,self.frame.size.height * 2)
view?.addSubview(scrollView) 


addChild(moveableNode)

您在第1行中执行的操作是使用场景维度初始化滚动视图助手.您还传递场景以供参考,以及您在步骤2中创建的moveableNode.
第2行是设置scrollView的内容大小的地方,在这种情况下,它是屏幕高度的两倍.

第3步: – 添加标签或节点等,并定位它们.

label1.position.y = CGRectGetMidY(self.frame) - self.frame.size.height
moveableNode.addChild(label1)

在此示例中,标签将位于scrollView的第2页上.这是您必须使用标签和定位的地方.

我建议如果滚动视图中有很多页面,并且有很多标签要执行以下操作.在滚动视图中为每个页面创建一个SKSpriteNode,并使每个页面都与屏幕大小相同.将它们称为page1Node,page2Node等.您可以将第二页上所需的所有标签添加到page2Node.这里的好处是你基本上可以像往常一样在page2Node中定位你所有的东西,而不仅仅是在scrollView中定位page2Node.

你也很幸运,因为垂直使用scrollView(你说你想要的)你不需要做任何翻转和反向定位.

我制作了一些类func,所以如果你需要禁用你的scrollView,你可以在scrollView上覆盖另一个菜单.

CustomScrollView.enable()
CustomScrollView.disable()

最后不要忘记在转换到新场景之前从场景中删除滚动视图.在spritekit中处理UIKit时的痛苦之一.

scrollView?.removeFromSuperView()

对于水平滚动,只需将init方法上的滚动方向更改为.horizo​​ntal(步骤2).

而现在最大的痛苦是在定位东西时一切都在逆转.所以滚动视图从右到左.因此,您需要使用scrollView“contentOffset”方法重新定位它,并且基本上从右到左以相反的顺序放置所有标签.一旦了解了发生的事情,再次使用SkNodes可以更轻松.

希望这对大量帖子有帮助和抱歉,但正如我所说,spritekit有点痛苦.让我知道它是怎么回事,如果我错过了什么.

项目在gitHub上

https://github.com/crashoverride777/SwiftySKScrollView

相关文章

软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘...
现实生活中,我们听到的声音都是时间连续的,我们称为这种信...
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿...
【Android App】实战项目之仿抖音的短视频分享App(附源码和...
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至...
因为我既对接过session、cookie,也对接过JWT,今年因为工作...