SpriteKit 自定义 UIScrollView 带加速

Posted

技术标签:

【中文标题】SpriteKit 自定义 UIScrollView 带加速【英文标题】:SpriteKit custom UIScrollView with acceleration 【发布时间】:2014-12-15 16:17:21 【问题描述】:

基本上我需要在我的 SpriteKit 项目中创建一个 UIScrollView,但是我在添加 SKButtons(用于按钮管理的自定义 SKNode 类)时遇到了很多问题。所以我开始创建一个带有触摸手势的可滚动 SKNode,但显然,这个栏不会有原生 UIScrollView 加速:我一直在寻找的功能。

所以试图通过添加一个原生 UIScrollView 来解决这个问题,并捕捉每一个位置变化,像这样:

使用此代码:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView

    [blueNode setPosition:CGPointMake(blueNode.position.x, scrollerUI.contentOffset)];

这很好用,但我愚蠢地忘记了如果我添加按钮,触摸手势将无法识别按钮的触摸事件! (UIScrollView 优先)。

也许这只是一个愚蠢的问题,但我真的不知道如何弄清楚。也许编写我自己的加速方法?

【问题讨论】:

您是否将uikit 元素(uiscrollview)直接添加到您的场景中?可能不是最好的方法。只是滑动一个 sknode 会容易得多。是的,您必须对某种缓动和加速进行编程。 你确实应该创造一些东西,比如加速度、速度等。 我觉得这是一个有趣的问题。投了赞成票,期待有人给出一个很好的答案。 【参考方案1】:

我想我想出了一个处理触摸的解决方案。由于UIScrollView 吃掉了所有的触摸以使其滚动,您需要将它们传递给SKScene。你可以通过继承UIScrollView来做到这一点:

class SpriteScrollView: UIScrollView 

    var scene: SKScene?


    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) 
        scene?.touchesBegan(touches, withEvent: event)
    

    override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) 
        scene?.touchesMoved(touches, withEvent: event)
    

    override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) 
        scene?.touchesCancelled(touches, withEvent: event)
    

    override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) 
        scene?.touchesEnded(touches, withEvent: event)
    

然后您的场景需要查看触摸是否触及任何节点并将触摸适当地发送到这些节点。所以在你的SKScene 添加这个:

var nodesTouched: [AnyObject] = []

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) 
    super.touchesBegan(touches, withEvent: event)

    let location = (touches.first as! UITouch).locationInNode(self)
    nodesTouched = nodesAtPoint(location)

    for node in nodesTouched as! [SKNode] 
        node.touchesBegan(touches, withEvent: event)
    


override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) 
    super.touchesMoved(touches, withEvent: event)

    for node in nodesTouched as! [SKNode] 
        node.touchesMoved(touches, withEvent: event)
    


override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) 
    super.touchesCancelled(touches, withEvent: event)
    for node in nodesTouched as! [SKNode] 
        node.touchesCancelled(touches, withEvent: event)
    


override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) 
    super.touchesEnded(touches, withEvent: event)
    for node in nodesTouched as! [SKNode] 
        node.touchesEnded(touches, withEvent: event)
    

请注意,这是针对单次触摸的,不能很好地处理错误,如果您想正确执行此操作,则需要在 if 语句中包含一些强制向下转换

我希望这对某人有帮助,即使这个问题已经存在几个月了。

【讨论】:

【参考方案2】:

一种可能的解决方案是在场景中添加点击手势:

override func didMoveToView(view: SKView) 
    let tap : UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: Selector("tapped:"))
    view.addGestureRecognizer(tap)


func tapped(tap : UITapGestureRecognizer) 
    let viewLocation = tap.locationInView(tap.view)
    let location = convertPointFromView(viewLocation)
    let node = nodeAtPoint(location)

    if node.name == "lvlButton" 
        var button = node as! SKButton
        button.touchBegan(location)
    

【讨论】:

感谢一百万!这对我来说效果很好!节省了我几个小时的代码!!!

以上是关于SpriteKit 自定义 UIScrollView 带加速的主要内容,如果未能解决你的问题,请参考以下文章

SpriteKit:如何在没有 SKShapeNode 的情况下绘制自定义形状?

使用 SpriteKit 的自定义框架 - 未加载资产文件

使用 Swift 在 SpriteKit 中将自定义“数字”图像作为分数添加到 SKLabelNode

如何在启动 OSX spritekit 应用程序时设置自定义光标?

touchesBegan Swift 2 自定义 SpriteKit 节点

使用 SpriteKit 和 Swift 的自定义着色器有一些不同