如何在没有物理的情况下检测碰撞

Posted

技术标签:

【中文标题】如何在没有物理的情况下检测碰撞【英文标题】:How to detect collision without physics 【发布时间】:2015-07-24 07:25:08 【问题描述】:

我想在不使用 didBeginContact() 函数的情况下检测两个物体何时接触

我尝试使用 CGRectIntersectsRect() 没有任何效果。

class GameScene: SKScene, SKPhysicsContactDelegate 

    // Player
    var _player = SKNode()
    var platform = SKNode()

    let heroCategory: UInt32 = 1 << 0
    let platformCategory: UInt32 = 1 << 1

    override func didMoveToView(view: SKView) 

        /* Setup your scene here */

        // Setup
        self.anchorPoint = CGPointMake(0.5, 0.5)
        self.physicsWorld.gravity = CGVectorMake(0.0, -2.0);
        self.physicsWorld.contactDelegate = self

        // Start populating
        _player = creatPlayer()
        self.addChild(_player)

        platform = creatPlatform(1, atPosition: CGPoint(x: 0, y: -200))
        self.addChild(platform)


        let platformTwo = creatPlatform(2, atPosition: CGPoint(x: 0, y: 200))
        self.addChild(platformTwo)

    

    func creatPlatform(type: Int, atPosition: CGPoint) -> PlatformNode 

        let node = PlatformNode()
        node.platformType = type
        node.position = atPosition
        let sprite = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: 200, height: 50))
        node.addChild(sprite)

        node.physicsBody = SKPhysicsBody(rectangleOfSize: sprite.size)
        node.physicsBody?.dynamic = false;
        node.physicsBody?.categoryBitMask = platformCategory
        node.physicsBody?.contactTestBitMask = heroCategory
        node.physicsBody?.collisionBitMask = 0;

        return node

    

    func creatPlayer() -> SKNode 

        let playerNode = SKNode()
        let sprite = SKSpriteNode(color: UIColor.whiteColor(), size: CGSize(width: 50, height: 50))
        playerNode.addChild(sprite)

        playerNode.physicsBody = SKPhysicsBody(rectangleOfSize: sprite.size)
        playerNode.physicsBody?.dynamic = false
        playerNode.physicsBody?.allowsRotation = false
        playerNode.physicsBody?.restitution = 1.0
        playerNode.physicsBody?.friction = 0.0
        playerNode.physicsBody?.angularDamping = 0.0
        playerNode.physicsBody?.linearDamping = 0.0
        playerNode.physicsBody?.categoryBitMask = heroCategory
        playerNode.physicsBody?.contactTestBitMask = platformCategory
        playerNode.physicsBody?.collisionBitMask = 0;

        return playerNode

    

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) 

        /* Called when a touch begins */
        _player.physicsBody?.dynamic = true

    

    override func update(currentTime: CFTimeInterval) 

        /* Called before each frame is rendered */
        if(CGRectIntersectsRect(platform.frame, _player.frame))
            println("Collision")
        
    


也许使用 CGRectIntersectsRect 是一种错误的方法,但我可以用它代替吗?

【问题讨论】:

我刚刚测试了你的代码,它可以工作。我只需要将 PlatformNode 修改为 SKSpriteNode 即可运行它。你确定调试区没有打印“碰撞”? 否,但问题是平台框架为 0 是的,这是因为 SKNode 的 frame 属性。您的播放器节点的框架也是 (0,0,0,0) 我添加了描述此行为的答案。 【参考方案1】:

框架属性

frame 属性是父坐标系中的一个矩形 包含节点的内容,忽略节点的子节点。

也来自文档:

如果节点的类绘制内容,则框架非空。

因为SKNode 类不执行任何自己的绘图,并且您的平台可能是 SKNode 的子类,而播放器是 SKNode,所以 frame 属性始终为 (0,0,0,0)。

您可以通过以下几种方式访问​​框架的实际大小:

您可以将播放器和平台设为SKSpriteNode 的子类。 您可以让它们保持原样并访问其中的子 SKSpriteNode。 您可以保持原样并使用calcualteAccumulatedFrame() 方法。

关于文档中的 calcualteAccumulatedFrame():

一个节点的累积帧,通过调用 calculateAccumulatedFrame 方法,是最大的矩形 包括节点的框架及其所有后代的框架。

【讨论】:

以上是关于如何在没有物理的情况下检测碰撞的主要内容,如果未能解决你的问题,请参考以下文章

如何加入两个碰撞的 SKSpriteNode

Unity 在没有 IsTrigger 的情况下使用 OnCollisionEnter2D 检测碰撞

仅在矩形物理体的一侧检测碰撞 - Swift3

俄罗斯方块游戏开发系列教程4:形状碰撞检测(上)

Three.js 进阶之旅:物理效果-碰撞和声音 💥

如何在没有敌人与它们互动的情况下产生能量提升并检测它们何时被拾取