当前位置: 首页 > 知识库问答 >
问题:

如何在精灵工具包中检测不同类型的碰撞

万俟炯
2023-03-14

我想在SpriteKit中检测两种不同类型的碰撞:

当气球击中目标1和球2击中目标2时:

到目前为止,我已经添加了不同的物理类别:

struct physicsCategory {
    static let ballOne :UInt32 = 0x1 << 0
    static let goalOne :UInt32 = 0x1 << 1
    static let ballTwo :UInt32 = 0x1 << 2
    static let goalTwo :UInt32 = 0x1 << 3
}

以下是我班级的相关部分:

class gameScene: SKScene, SKPhysicsContactDelegate {

    var borderBody:SKPhysicsBody!

    var myscore:Int = 0
    var opponentScore:Int = 10

    override func sceneDidLoad() {

        super.sceneDidLoad()
        physicsWorld.contactDelegate = self

    }

    func didBegin(_ contact: SKPhysicsContact) {

        let firstBody = contact.bodyA.node as! SKSpriteNode
        let secondBody = contact.bodyB.node as! SKSpriteNode

        if ((firstBody.name == "ballOne") && (secondBody.name == "goalOne")) {
            collisionGoalOne(BallOne: firstBody, GoalOne: secondBody)
        }

        else {

        }
    }

    func collisionGoalOne(BallOne: SKSpriteNode, GoalOne: SKSpriteNode) {
        addScore()
    }

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

        let touch = touches.first
        let touchLocation = touch!.location(in: self)

        let ballOne = childNode(withName: "ballOne") as! SKSpriteNode
        ballOne.physicsBody?.categoryBitMask = physicsCategory.ballOne
        ballOne.physicsBody?.collisionBitMask = physicsCategory.goalOne
        ballOne.physicsBody?.contactTestBitMask = physicsCategory.goalOne
        ballOne.physicsBody?.isDynamic = true

        let goalOne = childNode(withName: "goalOne") as! SKSpriteNode
        goalOne.physicsBody?.categoryBitMask = physicsCategory.goalOne
        goalOne.physicsBody?.collisionBitMask = physicsCategory.ballOne
        goalOne.physicsBody?.contactTestBitMask = physicsCategory.ballOne
        goalOne.physicsBody?.isDynamic = false        
    }

}

现在,当球与墙上相撞时,应用程序崩溃

让firstBody=contact.bodyA.node!SKSpriteNode

with“无法将“appname . games scene”(0x 105320)类型的值转换为“SKSpriteNode”(0x 1877 b5c)。”

我很想知道为什么会发生这种崩溃,以及这是否是一种处理碰撞的好方法。谢谢你。

共有2个答案

单于帅
2023-03-14

我认为你可能想做一些改变。

当你的球节点接触墙壁时,我相信你的didBEGIN(_联系人:SK物理接触)方法被调用,一个身体作为球(SKNode),另一个身体作为场景边界(SKScene)。

强制将 SKScene 投射到 SKSprite节点与让第一个正文 = 接触.bodyA.节点作为 !SKS精灵节点崩溃,正如RT5754所指出的那样。

要解决此问题,您可以考虑以下事项:

>

  • 为墙/边框添加一个物理类别。类似于:

     static let sceneBorder :UInt32 = 0x1 << 4
    

    更新边界和球节点以具有碰撞物理效果:

    ballNode.physicsBody?.collisionBitMask = physicsCategory.sceneBorder
    borderNode.physicsBody?.collisionBitMask = physicsCategory.ballOne + physicsCategory.ballTwo
    

    在处理其他联系逻辑时,我的didBegin(_contact:SKPhysicsContact)模式如下:

    func didBegin(_ contact: SKPhysicsContact) {
      var firstBody: SKPhysicsBody = contact.bodyA
      var secondBody: SKPhysicsBody = contact.bodyB
    
      //in did begin contact, order the bodies by physics category
      if firstBody.categoryBitMask > secondBody.categoryBitMask {
        let temp = secondBody
        secondBody = firstBody
        firstBody = temp
      }
    
      //logic to handle contact is based on physicsCategory
      if secondBody.categoryBitMask == physicsCategory.whatever {
        methodToHandleWhatever(thingOne: firstBody, thingTwo: secondBody)
      }
    

  • 仲孙文乐
    2023-03-14

    第一正文可能无法转换为SKSpriteNode,因此只有在检查哪些节点发生冲突后才能创建该变量。

    请注意,ballOne可以是bodyA或bodyB,因此请更改您的代码来检查这两种可能性。

    我稍微更改了您的代码。希望这有帮助

    if ((contact.bodyA.node?.name == "ballOne") && (contact.bodyB.node?.name == "goalOne")) {  
         let firstBody = contact.bodyA.node as! SKSpriteNode
         let secondBody = contact.bodyB.node as! SKSpriteNode
         collisionGoalOne(BallOne: firstBody, GoalOne: secondBody)
     } else if ((contact.bodyA.node?.name == "goalOne") && (contact.bodyB.node?.name == "ballOne")) {
         let firstBody = contact.bodyA.node as! SKSpriteNode
         let secondBody = contact.bodyB.node as! SKSpriteNode
         collisionGoalOne(BallOne: secondBody, GoalOne: firstBody)
    }
    
     类似资料:
    • 我正在使用Sprite Kit中的碰撞检测。它在起作用,防止我的精灵穿越路径。然而,我在didBeginContact中没有收到通知:而且我似乎无法控制物理引擎在发生碰撞时的响应。 我让各种汽车(SKSpriteNodes)使用SKAction followPath沿着以下路径行驶:as offset:oriento path:duration: 以前,如果两辆车相交,它们都会像往常一样继续行驶,

    • 在开始学习相关知识点之前,我们有必要先学习精灵和碰撞检测的含义。 精灵(英文译为 Sprite),其实在一个游戏程序中,精灵本质指的是一张张小尺寸的图片,比如游戏中的各种道具、人物、场景装饰等,它们都可以看做成一张张小的“精灵”图。除此之外,人物的移动也可以看做是一系列小精灵图构成的序列(按帧组成的序列),如下图所示: 图1:动作逐帧分解图 如果将逐帧分解后的动作,按照一定的频率播放,那么就形成了

    • 我的游戏有两个职业,它们都产生精灵,唯一的区别是它们的精灵向不同的方向移动。 然而,我如何检测另一个类的精灵是否与这个类碰撞,两个类都产生了很多精灵。我的想法是也使用池为每个精灵创建一个矩形。

    • 当我尝试检测两个矩形之间的碰撞时当我启动程序时,它只打印“HIT”一次 我还尝试使用但出现此错误: 回溯(最近调用最后): 文件“D:/蟒蛇/PyCharm/test/src/Main/test.py”,第 104 行, 命中 = pygame.sprite.spritecollide(player_sprites,enemy_sprites,1) 文件“D:\程序\蟒蛇\lib\site-pac

    • 使用< code >加速计,我的精灵图像会左右移动,如果我触摸屏幕,精灵会移动到Y轴。我想在不同的精灵之间进行碰撞检测,这样如果精灵穿过一个物体,它就会停下来藏在那个物体里。我已经看了这个https://www.youtube.com/watch?v=T1aN-vTqLc的教程,但什么也没发生。进行碰撞检测的正确方法是什么?我不知道我的编码有什么问题。任何建议或更好的教程谢谢和进步 这是我的编码

    • 我一直在学习一些pygame教程,并且基于这些教程开发了自己的代码。具体如下: 所以我想出了如何让我的家伙跳跃,但是我已经在天空中放置了一个块并试图这样做: 试图让角色停止跳跃。有没有一个内置的函数来测试这一点,或者有没有一个适合我的方法。顺便说一下,这是行不通的,我似乎也不知道该怎么做。非常感谢任何帮助:)