检测旋转何时完成并移动到新场景

Posted

技术标签:

【中文标题】检测旋转何时完成并移动到新场景【英文标题】:Detect when rotation has completed and move to new Scene 【发布时间】:2017-04-24 04:57:23 【问题描述】:

我正在尝试在车轮停止旋转时移动到另一个场景。我的代码如下所示。我不知道如何检测速度何时达到 0.0?

import SpriteKit
import GameplayKit

class GameplayScene: SKScene 

    var player: Player?;

    override func didMove(to view: SKView) 
        player = self.childNode(withName: "spinner") as! Player?;
    

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) 
        for touch in touches 
            let location = touch.location(in: self)
            if atPoint(location).name == "play_button" 
               spin()
            
        
    

    func spin () 
        let random = GKRandomDistribution(lowestValue: 20, highestValue: 90)
        let r = random.nextInt()
        player?.physicsBody = SKPhysicsBody(circleOfRadius: CGFloat(self.frame.width))
        player?.physicsBody?.affectedByGravity = false
        player?.physicsBody?.isDynamic = true
        player?.physicsBody?.allowsRotation = true
        player?.physicsBody?.angularVelocity = CGFloat(r)
        player?.physicsBody?.angularDamping = 1.0
    

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

     

所以从这里开始,我想在车轮停止旋转时执行以下操作:

let play_scene = Questions(fileNamed: "QuestionsScene")
play_scene?.scaleMode = .aspectFill
self.view?.presentScene(play_scene!, transition: SKTransition.doorsOpenVertical(withDuration: 1))

我现在已经编辑了这个类,它看起来如下:

import SpriteKit
import GameplayKit

class GameplayScene: SKScene, SKSceneDelegate 


var player: Player?

override func didMove(to view: SKView) 
    self.delegate = self
    player = self.childNode(withName: "spinner") as! Player?;



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

    for touch in touches 
        let location = touch.location(in: self)
        if atPoint(location).name == "play_button" 
            spin()
        
    

    func spin () 
        let random = GKRandomDistribution(lowestValue: 20, highestValue: 90)
    let r = random.nextInt()
    player?.physicsBody = SKPhysicsBody(circleOfRadius: CGFloat(self.frame.width))
    player?.physicsBody?.affectedByGravity = false
    player?.physicsBody?.isDynamic = true
    player?.physicsBody?.allowsRotation = true
    player?.physicsBody?.pinned = true
    player?.physicsBody?.angularVelocity = CGFloat(r)
    player?.physicsBody?.angularDamping = 1.0



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


    override func didSimulatePhysics() 
        if ((player?.physicsBody?.angularVelocity)! <= CGFloat(0.01)) 
        
            print("Got it")
        
    

问题是我仍然收到关于 didSimulatePhysics 函数中的 if 语句的错误。我收到的错误是“线程 1:EXC_BAD_INSTRUCTION....”

【问题讨论】:

【参考方案1】:

您的***的SKPhysicsBody 有一个内置属性angularVelocity,它告诉您它的旋转速度。当您将其设置为 r 以开始旋转时,您已经在使用它了。

要观看angularVelocity,您可以使用didSimulatePhysics()。它每帧调用一次,就在物理计算完成之后。看起来像这样:

func didSimulatePhysics() 
    if wheelIsSpinning && angularVelocity != nil && angularVelocity! <= CGFloat(0.001) 
        wheelIsSpinning = false
        // wheel has stopped
        // add your code here
    

由于物理建模的变幻莫测,angularVelocity 可能永远不会完全为零。因此,我们改为观察它是否小于某个任意阈值,在本例中为 0.001。

您不希望它在***不移动时执行每一帧,所以我添加了一个属性wheelIsSpinning 来跟踪。您需要将其作为实例属性添加到GameplayScene,并在spin() 中将其设置为true。

【讨论】:

谢谢罗伯特。后来我发现,即使当我将速度打印到控制台时,***看起来已经停止了,但它看起来仍然旋转得如此缓慢。它从未真正停止过 @Nick 只需检查.angularVelocity &lt;= 0.001 或其他任意低值。 @Robert 将场景设置为自己的委托没有意义。在SKSceneDelegate 协议中找到的所有方法,包括didSimulatePhysics(),都会在SKScene 及其子类上自动调用。设置一些其他类来实现这个协议会更有意义...... @Nick 除了您不需要该行之外,如果您仍然想要类似的东西,请将self.delegate = self 放入init() 或其他适当的方法中。你不能在类的主体中使用 self。 @Nick 从场景的定义中删除 SKSceneDelegate 一致性(你的场景应该看起来像这样 class GameplayScene: SKScene 。从你的代码中删除 self.delegate = self。当你这样做时,告诉我错误是什么。一切否则罗伯特说,应该工作。符合SKSceneDelegate 是不必要的。这就是我的观点。

以上是关于检测旋转何时完成并移动到新场景的主要内容,如果未能解决你的问题,请参考以下文章

每天一个Js小demo之移动端全景图场景实现-全景装修图。主要知识点:css3,旋转角度检测

如何检测 UINavigationController 动画何时完成?

panda3d 键盘移动场景

panda3d 键盘移动场景

检测用户何时停止/暂停在 TextField 中写入 - SwiftUI

如何检测用户何时在 Swift 中完成移动 Range 滑块