【问题标题】:Prevent two SKSpriteNodes from overlapping防止两个 SKSpriteNode 重叠
【发布时间】:2016-04-03 21:54:58
【问题描述】:

我想使用 Swift 和 SpriteKit 重现 iOS 版 Super-Mario。我使用 SKPhysics-body 来模拟玩家和环境之间的碰撞。玩家和所有对象都有自己的 SKPhysicsBody(大小为矩形)。但是当玩家跳到一块砖头上(从左上角或右上角)like this 时,玩家会卡在空中。

我的假设是当两个 SKSpriteNode 碰撞时,它们会重叠一点。并且 SKPhysics-Engine 认为玩家在中间砖的顶部,因为玩家在上面的砖里面有一点点,然后跌倒在中间砖上。

所以我的问题是:如何防止 SKSPriteNodes 重叠?或者我该如何解决这个问题?

附:如果您需要更多信息来回答,请告诉我!

编辑:Brick 类的一些代码:

import SpriteKit

class Brick: SKSpriteNode {

    let imgBrick = SKTexture(imageNamed: "Brick")

    init(let xCoor: Float, let yCoor: Float) {
        // position is a global variable wich is 1334/3840
        super.init(texture: imgBrick, color: UIColor.clearColor(), size: CGSize(width: 80*proportion, height: 80*proportion))
        position = CGPoint(x:Int(xCoor*667)+Int(40*proportion), y:Int(375-(yCoor*375))-Int(40*proportion))
        name = "Brick"
        physicsBody = SKPhysicsBody(rectangleOfSize: self.size)
        physicsBody?.affectedByGravity = false
        physicsBody?.dynamic = false
    }

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

还有我的玩家班级

import SpriteKit

class Mario: SKSpriteNode {

    let atlas = SKTextureAtlas(named: "Mario")
    var imgMario = [SKTexture]()
    var action = SKAction()

    init(let xCoor: Float, let yCoor: Float) {
        for(var i = 1; i < 24; i++) {
           imgMario.append(atlas.textureNamed("X\(i)"))
        }

        super.init(texture: imgMario[0], color: UIColor.clearColor(), size: CGSize(width: 120*proportion, height: 160*proportion))
        position = CGPoint(x:Int(xCoor)+Int(60*proportion), y:Int(yCoor)-Int(90*proportion))
        name = "Mario"
        physicsBody = SKPhysicsBody(rectangleOfSize: self.size)
        physicsBody?.allowsRotation = false

        action = SKAction.repeatActionForever(SKAction.animateWithTextures(imgMario, timePerFrame: 0.03, resize: false, restore: true))
        runAction(action, withKey: "walking")
    }

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

以及我的关卡课程的某些部分

class Level: SKScene, SKPhysicsContactDelegate {

    var motionManager = CMMotionManager()

    var mario = Mario(xCoor: 100, yCoor: 90)
    var world = SKSpriteNode()

    let MarioCategory: UInt32 = 0x1 << 0
    let BrickCategory: UInt32 = 0x1 << 1

    /*
    Some more code...
    */

    func setUpPhysics() {
        physicsWorld.contactDelegate = self
        mario.physicsBody!.categoryBitMask = marioCategory
        mario.physicsBody?.collisionBitMask = brickCategory
        mario.physicsBody?.contactTestBitMask = brickCategory

        for(var i = 0; i < world.children.count; i++) {
            if(world.children[i].name == "Brick") {
                world.children[i].physicsBody?.categoryBitMask = brickCategory
                world.children[i].physicsBody?.collisionBitMask = marioCategory
                world.children[i].physicsBody?.contactTestBitMask = marioCategory
                world.children[i].physicsBody?.friction = 0
            }
        }
    }
}

【问题讨论】:

  • 砖都是瓦片吗?它们是多个物理体还是一个大型物理体?
  • 检查物理实体是否按应有的方式排列,如果您不知道该怎么做,请阅读this answer。如果主体没问题,请尝试将block.physicsBody!.friction = 0 设置为块
  • 请提供代码,以便正确评估问题。
  • 所有积木都有自己的(每块积木都有)物理体。我之前检查了安排,似乎一切都正确,请参见此处:link(我移除了左砖!)不幸的是 .physicsBody!.friction = 0 没有帮助。播放器仍然卡住。
  • 试着让你的玩家物理身体变成一个圆圈

标签: ios swift sprite-kit collision overlapping


【解决方案1】:

尝试在你的物理体上将 UsePreciseCollisionDetection 设置为 true。

mario.physicsBody?.usesPreciseCollisionDetection = true

https://developer.apple.com/reference/spritekit/skphysicsbody 有一些例子。

将此属性设置为 true 可能会导致它更准确地检测碰撞,因此只有在您有意时。我还会重新考虑为每个块赋予自己的物理体。您只真正关心一组块的边缘,而不是每个单独块的边缘。

另一个建议是您可以基于纹理创建物理体。因此,如果您的 SKSpriteNode 具有带有透明位的复杂纹理,您可以创建另一个只是简单的黑色块或类似的纹理,这将有助于引擎检测更准确的碰撞。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多