【问题标题】:touchesBegan Vs UITapGestureRecognizertouchesBegan VS UITapGestureRecognizer
【发布时间】:2015-12-17 16:54:05
【问题描述】:

所以我正在使用 swift 制作一个 spritekit 游戏。我想知道哪个最适合使用手势?

目前我有一个 override func touchesBegan 处理所有点击和一个 UILongPressGestureRecognizer 处理长点击/按住。

所以你知道,一个水龙头按下按钮并跳跃英雄。长时间的持有让英雄回避。

由于某种原因,我的 longPress 函数并不总是被调用(有时您可以按住 10 次然后它停止被调用(无法识别),其他时候它是 5 次,它会有所不同),这导致了昨天一整天都在尝试新事物和调查,这让我想到了这个问题。

是使用touchesBegan 还是将我所有的触摸调用转移到由UITapGestureRecognizer 处理的新函数更好?

我确实将所有内容从 touchesBegan 移至 UITapGestureRecognizer,但它似乎非常缓慢。但我可能执行错了?

recognisers 是这样设置的:

func setupRecognizers() {
    let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    view!.addGestureRecognizer(tapRecognizer)

    let longTapRecognizer = UILongPressGestureRecognizer(target: self, action: Selector("handleLongPress:"))
    longTapRecognizer.minimumPressDuration = 0.2
    view!.addGestureRecognizer(longTapRecognizer)

}

这些是处理手势的函数:

func handleTap(recognizer: UIGestureRecognizer) {
    //currently all handled in touchesBegan
}

func handleLongPress(recognizer: UIGestureRecognizer) {
    print("1 --------> longPress Called.... ", recognizer.state.rawValue, gameState)
    if gameState == .Play {
       //do stuff
       //duck Hero
    } else {
       //switch gameState
    }
}

这是处理触摸/点击的函数:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
   /* Called when a touch begins */

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

     //do stuff

     switch gameState {
        case .MainMenu:
        break
        ... //more states
        }
   }
   super.touchesBegan(touches, withEvent: event)
}

如果我将所有内容从touchesBegans 移动到tapRecogniser(上面的空函数),我也必须实现这一点,以转换触摸位置坐标:

func handleTap(recognizer: UIGestureRecognizer) {
    let location = convertPointFromView(CGPoint(x: recognizer.locationInView(nil).x, y: recognizer.locationInView(nil).y))
    print("Converted Coords: ", location)

    //then do all touchesBegan stuff
 }

我都试过了,但后者似乎真的很慢而且很迟钝。也许我忘记实施推荐的东西?

似乎我的 longPress 手势并不总是被调用,这之间会不会有一些冲突?

【问题讨论】:

  • 我不会在 spritekit 游戏中使用任何与 UIKit 相关的东西。如果您想使用更新方法测试一次触摸的时间。尝试在游戏中尽可能多地使用 spritekit 的工具。任何与 UIKit 相关的东西(游戏菜单或控件)我都会放在 UIViewController 中。
  • 一切,包括菜单都是在gameScene中创建的,并通过gameStates(inGame、Menu、gameOver)等来区分。所以你推荐一个定时器在touchesBegan,和if timer &gt; longPressValue duck, else jump?或者SpriteKit有不同的点击手势?
  • 它没有轻触手势..你只需要捕捉你按住手指的时间,并在你放手时重置计时器。那种东西。
  • 我会先给出它,它可能会解决为什么不总是调用 longPress 并将所有内容保留在 touchesBegan... 可能会更好。
  • 如果您需要我写一些代码,请告诉我

标签: ios swift sprite-kit uigesturerecognizer touchesbegan


【解决方案1】:

因此,如果您按住红色方块两秒钟,您将收到一条消息,当您松开时,该消息会消失。您可能需要在其中添加一些布尔值,以确保您的角色在按住 2 秒按钮后每帧都不会重复某些动作。这应该足以让您满怀希望地开始

import SpriteKit

class GameScene: SKScene {

    // time values
    var delta = NSTimeInterval(0)
    var last_update_time = NSTimeInterval(0)

    var longTouchTimer = NSTimeInterval(0)
    var touched = false
    var testLabel = SKLabelNode(text: "you have touched for awhile now bro")

    let touchSprite = SKSpriteNode(color: SKColor.redColor(), size: CGSizeMake(100, 100))

    override func didMoveToView(view: SKView) {
        touchSprite.position = CGPointMake(self.size.width/2, self.size.height/2)
        addChild(touchSprite)

        testLabel.hidden = true
        testLabel.position = touchSprite.position
        testLabel.position.y += 100
        testLabel.fontSize = 20
        addChild(testLabel)
    }


    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        for touch: AnyObject in touches {
            let location = touch.locationInNode(self)

            if touchSprite.containsPoint(location) {
                touched = true
            }
        }
    }

    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        for touch: AnyObject in touches {
            let location = touch.locationInNode(self)

            if !touchSprite.containsPoint(location) {
                touched = false
                longTouchTimer = 0
            }
        }
    }

    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        touched = false
        longTouchTimer = 0
    }

    override func update(currentTime: NSTimeInterval) {
        if last_update_time == 0.0 {
            delta = 0
        } else {
            delta = currentTime - last_update_time
        }

        last_update_time = currentTime

        if touched {
            longTouchTimer += delta
        }

        if longTouchTimer >= 2 {
            testLabel.hidden = false
        } else {
            testLabel.hidden = true
        }
    }
}

【讨论】:

  • 太棒了。谢谢你。我现在试一试。感谢发帖。
  • @hamobi 很棒的文章。只需使用 touches 方法来启动和停止计时器(NSTimeIntervals 不是 NSTimer,不应该在 SpriteKit 中使用)同时使用更新 currentTime 是完美的。请注意,由于您使用的是 currentTime 而不是系统时间,因此无论出于何种原因暂停游戏时,它都能很好地工作。
  • 我只是得到一个空白屏幕..也许我在做一些愚蠢的事情:S
  • 这可能是您特定项目的设置方式。最终重要的部分是使用更新来增加您的时间变量。只需尝试将该部分添加到您的项目中
  • 搞定了,觉得我的项目很奇怪。删除它并重新开始并且工作正常......有没有办法让longTouchTimertouchesBegan中工作?因为就像你说的,如果我只是在更新中 jump() 或 duck() ,它将被每帧调用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-21
  • 2010-12-13
  • 1970-01-01
相关资源
最近更新 更多