SpriteKit中SKSpritenode子类中使用touchesMoved时不稳定

4
我正在使用Swift子类化SKSpritenode来创建可以拖动的彩色块。这个子类被称为SoundNode。
import SpriteKit

class SoundNode: SKSpriteNode {

init() {
    super.init(texture: nil, color: UIColor.blue, size: CGSize(width: 100, height: 100))
    self.isUserInteractionEnabled = true

    }

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



override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    print("touch began")
    }

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    print("touches moved")
    guard let touch = touches.first else {
        return
        }   
    let touchLocation = touch.location(in: self)
    self.position = touchLocation
    }


override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    print("touch ended")
    }


}

在GameScene.swift文件中

import SpriteKit

class GameScene: SKScene {

  override func didMove(to view: SKView) {
    addSoundBlock()
  }


  func addSoundBlock() {
    let soundBlock = SoundNode()
    soundBlock.position = CGPoint(x: 800, y: 800)
    addChild(soundBlock)
    }
}

这可以运行,有些小问题。
soundBlock已添加,可以在场景中拖动。但是它会闪烁并且有时会消失。我已经尝试了touchesMoved中的其他方法,但都没达到平滑效果。
如果我不继承touchesBegan, touchesMoved, touchesEnded并在GameScene中实现操作,则拖动将变得平滑。但未来计划需要能够继承这些操作。
Xcode 8,Swift 3,iOS10。

嗨Rich,你解决了这个问题吗?我在考虑类似的事情。 - Confused
我的直觉告诉我,这个代码:let touchLocation = touch.location(in: self) 应该是指场景框架中的触摸位置,而不是精灵的框架位置(self)。 - Confused
我只能通过不继承行为来解决它。所以我把touchesBegan和其他操作移到了GameScene.swift中。这样做虽然有效,但感觉有点凌乱。不确定是否应该将其保持公开或发布为解决方案。 - RIch English
3个回答

0
我创建了一个类方法来处理SKSpriteNode子类的移动,例如我的'Player',并将触摸位置传递给了GameScene.swift中的该方法。
在Player.swift中声明的类方法:
    func movePlayer(location: CGPoint) {
        //movement code
    }

在GameScene.swift中调用该函数:

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

         guard let location = touches.first?.location(in: self) else { return }
         player.movePlayer(location: location)

    }

我想应该更加简洁,同时也允许进一步的子类化。


0

我曾经遇到过这个问题,子类 SKNode 作为 GameScene 父节点上的 SKNode 的子元素:

  1. GameScene(顶级父节点)
  2. GridNode(SKNode 子类,是 GameScene 的子元素)
  3. TileNode(SKNode 子类,是 GridNode 的子元素)

当在直线上滑动时,从 TileNode 调用的 touchesMoved 方法返回的 touches.first.location 值不稳定:

134.6666259765625
-42.33331298828125
133.6666259765625
-41.6666259765625
132.33331298828125
-40.6666259765625
131.6666259765625
-40.33331298828125

我相信问题源于TileNode的大小(因此位置)从GameScene的角度来看实际上为0。

我是这样解决的(在TileNode类中):

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }
    guard let parent = self.parent as? GridNode else { return }
    let movingPoint: CGPoint = touch.location(in: parent)

    ...
}

注意 touch.location(in: parent)touch.location(in: self) 的区别。 GridNode 在其GameScene父级中有一个固定的位置,而TileNode则没有。

现在movingPoint返回平滑的值,没有抖动。

希望这能对某人有所帮助。


-1
有时候我发现当zPosition没有设置确保精灵在其他节点前面时,精灵的外观会出现不一致的情况(即有时可见,有时不可见)。我认为这可能是因为如果两个节点具有相同的zPosition,则图形引擎无法确定哪一个在顶部。 尝试将zPosition设置为某个数字,以确保它在其他节点前面。 例如,在此之后:
soundBlock.position = CGPoint(x: 800, y: 800)

添加:

soundBlock.zPosition = 1000

我还没有尝试运行这个,但也许值得一试?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接