【问题标题】:turning physics on and off打开和关闭物理
【发布时间】:2017-04-21 14:00:31
【问题描述】:

我正在尝试解决一个精灵节点可以在平台上跳跃但不能向下跳的问题。我尝试使用此代码:

override func didMove(to view: SKView) {
    if (thePlayer.position.y > stonePlatform1.position.y) ==  true {
        stonePlatform1.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: stonePlatform.size.width * 0.9, height: stonePlatform.size.height * 0.75))
        stonePlatform1.physicsBody!.isDynamic = false
        stonePlatform1.physicsBody!.affectedByGravity = false
        stonePlatform1.physicsBody!.categoryBitMask = BodyType.object.rawValue
        stonePlatform1.physicsBody!.contactTestBitMask = BodyType.object.rawValue
        stonePlatform1.physicsBody!.restitution = 0.4
    }
}

这个想法是在玩家在平台上方时打开平台的物理主体。但是,当我使用此代码时,物理学根本不起作用。事实上,我尝试使用这段代码:

override func didMove(to view: SKView) {
    if (thePlayer.position.y < stonePlatform1.position.y) ==  true {
        stonePlatform1.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: stonePlatform.size.width * 0.9, height: stonePlatform.size.height * 0.75))
        stonePlatform1.physicsBody!.isDynamic = false
        stonePlatform1.physicsBody!.affectedByGravity = false
        stonePlatform1.physicsBody!.categoryBitMask = BodyType.object.rawValue
        stonePlatform1.physicsBody!.contactTestBitMask = BodyType.object.rawValue
        stonePlatform1.physicsBody!.restitution = 0.4
    }
}

物理学也没有开启。如果不存在 IF 语句,则物理始终有效。

【问题讨论】:

    标签: swift3 sprite-kit collision-detection


    【解决方案1】:

    您可以在此平台上使用节点速度,如下所示:

    SpriteKit - Swift 3 代码:

    private var up1 : SKSpriteNode!
    private var down1 : SKSpriteNode!
    private var down2 : SKSpriteNode!
    private var player : SKSpriteNode!
    
    override func didMove(to view: SKView) {
        up1 = self.childNode(withName: "up1") as! SKSpriteNode
        down1 = self.childNode(withName: "down1") as! SKSpriteNode
        down2 = self.childNode(withName: "down2") as! SKSpriteNode
        player = self.childNode(withName: "player") as! SKSpriteNode
        up1.physicsBody?.categoryBitMask = 0b0001 // Mask for UoPlatforms
        down1.physicsBody?.categoryBitMask = 0b0010 // Mask for downPlatforms
        down2.physicsBody?.categoryBitMask = 0b0010 // Same mask
    }
    
    override func update(_ currentTime: TimeInterval) {
        player.physicsBody?.collisionBitMask = 0b0000 // Reset the mask
    
        // For UP only Platform
        if (player.physicsBody?.velocity.dy)! < CGFloat(0.0) {
            player.physicsBody?.collisionBitMask |= 0b0001 // The pipe | operator adds the mask by binary operations
        }
    
        // For Down only platforms
        if (player.physicsBody?.velocity.dy)! > CGFloat(0.0) {
            player.physicsBody?.collisionBitMask |= 0b0010  // The pipe | operator adds the mask by binary operations
        }
    
    }
    

    示例源代码:https://github.com/Maetschl/SpriteKitExamples/tree/master/PlatformTest

    示例显示: 绿色平台 -> 仅向下 红色平台 -> 仅向上

    【讨论】:

    • 不是一个糟糕的解决方案,但它不能解决当块停止在另一个块内移动时会发生什么的问题
    • 加 1 只为 |=。太好了。
    • @PierreCourpron 使用此实现它由平台外的引擎推送的块。你在寻找什么行为?
    • |不是管道字符,而是按位或。请参阅此处以通过在 contactTest 或碰撞位掩码中翻转单个位来打开或关闭单个接触和碰撞 - stackoverflow.com/documentation/sprite-kit/6261/…
    【解决方案2】:

    您可以尝试从nil 的物理体开始,然后在玩家位于其上方后为其设置物理值。此外,这种代码应该在更新函数中。将它放在 didMove 中只会让它被调用一次。

    override func update(_ currentTime: TimeInterval){
     if (thePlayer.position.y < stonePlatform1.position.y) && stonePlatform1.physicsBody != nil {
           stonePlatform1.physicsBody = nil
     }else if (thePlayer.position.y > stonePlatform1.position.y) && stonePlatform1.physicsBody == nil{
        setPhysicsOnPlatform(stonePlatform1)
     }
    }
    
    func setPhysicsOnPlatform(_ platform: SKSpriteNode){
       platform.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: stonePlatform.size.width * 0.9, height: stonePlatform.size.height * 0.75))
       ...
       //the rest of your physics settings
    }
    

    您还应该对播放器的高度和锚点进行一些处理。否则,如果您的 anchorPoint 为 (0,0) 并且玩家在平台的中途,则会应用物理并且会出现不希望的结果。

    【讨论】:

    • 为什么不简单地玩一下 collisionBitMask 而不是每次都重新创建物理体?
    • 我以前也这样做过,但我总是更好地看整个身体。此外,像这样的场景通常需要更改多个值,例如contactTest、collision、mass等。这样做可以解决所有这些问题。
    • 这样做会毁掉其他东西的碰撞。如果敌人在那里走怎么办?它会随着玩家的通过而落下。必须有一种更简单的方法来做到这一点。只需将值更改包含在函数中即可。它也会提高 CPU 效率。
    • @BadgerBadger 你会怎么做这样的事情?
    • 只是一个快速的想法:构建所有这些平台的数组。当玩家移动时,计算移动角度。您需要平台让玩家通过的唯一时刻是他是否向上移动。使用角度来确定他是否这样做,并使用带有平台的数组来相应地更新位掩码。如果玩家正在向上移动,则将玩家从 colision 位掩码中移除,如果他正在向下移动,则将玩家添加到位掩码,除非他已经与平台接触:这将避免平台在与角色重叠时变为实心
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-06
    • 2023-03-27
    • 2022-11-14
    • 2015-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多