Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 如何确定两个圆的最精确碰撞?_Swift_Collision - Fatal编程技术网

Swift 如何确定两个圆的最精确碰撞?

Swift 如何确定两个圆的最精确碰撞?,swift,collision,Swift,Collision,我正在用代码创建一个新的游戏应用程序! 我用spriteKit创建了一些气泡。我用了这个纹理。 他们在运动场上随意飞行。当它们彼此相交时,它们必须碰撞并改变路径 第一个问题:当然,是圆形气泡的图像。但在碰撞中,气泡彼此接触的面不是圆形,而是正方形 第二个问题:他们互相依附,我想这是第一个问题的问题 如果你知道如何解决这个问题,请帮助我,因为我找不到解决这个问题的方法。 我认为这个问题可以用面具来解决,但我不知道如何解决。(非常感谢) 这是我的泡泡糖: class SKButton: SKSpri

我正在用代码创建一个新的游戏应用程序! 我用spriteKit创建了一些气泡。我用了这个纹理。 他们在运动场上随意飞行。当它们彼此相交时,它们必须碰撞并改变路径

第一个问题:当然,是圆形气泡的图像。但在碰撞中,气泡彼此接触的面不是圆形,而是正方形

第二个问题:他们互相依附,我想这是第一个问题的问题

如果你知道如何解决这个问题,请帮助我,因为我找不到解决这个问题的方法。 我认为这个问题可以用面具来解决,但我不知道如何解决。(非常感谢)

这是我的泡泡糖:

class SKButton: SKSpriteNode{

private var buttonTexture:SKTexture

override init(texture: SKTexture?, color: UIColor, size: CGSize) {
    self.buttonTexture = texture!

    super.init(texture:buttonTexture , color: .black, size: buttonTexture.size())

}

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

class GameViewController: UIViewController {

@IBOutlet weak var mySKView: SKView!

override func viewDidLoad() {
    super.viewDidLoad()

    if let view = mySKView {
        let scene = GameScene(size: CGSize(width: 2048, height: 1536))
        scene.scaleMode = .aspectFill
        view.presentScene(scene)
        view.ignoresSiblingOrder = true

        view.showsFPS = true
        view.showsNodeCount = true
    }
}}
这是游戏场景:

class GameScene: SKScene {
private var arrayBubbles = [SKButton?]()
private var arrayVelosity = [CGPoint]()
private var bubbleMovePointsPerSecX = [CGFloat]()
private var bubbleMovePointsPerSecY = [CGFloat]()

private var currentVelosity:CGPoint!

private var lastUpdateTime: TimeInterval = 0
private var dt: TimeInterval = 0
private let min = 0
private let max = 3

private let bubbleTexture = SKTexture(imageNamed: "bubble")
private let playableRect: CGRect!

lazy var background: SKSpriteNode = {
    let back = SKSpriteNode(imageNamed: "back")
    back.position = CGPoint(x: self.size.width/2, y: size.height/2)
    back.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    back.zPosition = -1
    return back
}()

lazy var bubble1: SKButton = {
    var button = SKButton(texture: bubbleTexture, color: .clear, size: bubbleTexture.size())
    button.position = CGPoint(x: size.width/2, y: size.height - (size.height/3))
    button.setScale(0)
    button.zPosition = 1
    button.name = "bubble1"
    return button
}()

lazy var bubble2: SKButton = {
    var button = SKButton(texture: bubbleTexture, color: .clear, size: bubbleTexture.size())
    button.position = CGPoint(x: size.width/3, y: size.height/2)
    button.setScale(0)
    button.zPosition = 1
    button.name = "bubble2"
    return button
}()

lazy var bubble3: SKButton = {
    var button = SKButton(texture: bubbleTexture, color: .clear, size: bubbleTexture.size())
    button.position = CGPoint(x: size.width - (size.width/3), y: size.height/2)
    button.setScale(0)
    button.zPosition = 1
    button.name = "bubble3"
    return button
}()

override init(size: CGSize) {
    let playableHeight = size.width/(16.0/9.0)
    let playableMargin = (size.height - playableHeight)/2

    playableRect = CGRect(x: 0, y: playableMargin, width: size.width, height: playableHeight)
    super.init(size:size)
}

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


override func didMove(to view: SKView) {
    addChilds()
    appendBubblesToArray()
    setRandomBubbleSpead()
    appendVelosityToArray()
    showApearBubble()

}
private func addChilds(){
    addChild(background)
    addChild(bubble1)
    addChild(bubble2)
    addChild(bubble3)
}

private func appendBubblesToArray(){
    arrayBubbles.append(bubble1)
    arrayBubbles.append(bubble2)
    arrayBubbles.append(bubble3)
}

private func setRandomBubbleSpead(){
    for _ in min..<arrayBubbles.count{
        let randomSpeadX = CGFloat.random(in: -200..<200)/CGFloat(Double.pi)
        bubbleMovePointsPerSecX.append(randomSpeadX)

        let randomSpeadY = CGFloat.random(in: -200..<200)/CGFloat(Double.pi)
        bubbleMovePointsPerSecY.append(randomSpeadY)
    }
}

private func appendVelosityToArray(){
    for index in min..<arrayBubbles.count{
        currentVelosity = CGPoint(x: bubbleMovePointsPerSecX[index], y: bubbleMovePointsPerSecY[index])
        arrayVelosity.append(currentVelosity)
    }
}

private func showApearBubble(){
    let apearBubble = SKAction.scale(to: 1, duration: 0.5)
    let action = [apearBubble]

    bubble1.run(SKAction.sequence(action))
    bubble2.run(SKAction.sequence(action))
    bubble3.run(SKAction.sequence(action))
}

override func didEvaluateActions() {
    checkColisions()
}

private func checkColisions(){
    enumerateChildNodes(withName: "//*") { [weak self] node, _ in
        guard let self = self else { return }

        switch node.name{
        case "bubble1":
            self.checkBubbleIntersection(self.bubble1)
            break
        case "bubble2":
            self.checkBubbleIntersection(self.bubble2)
            break
        case "bubble3":
            self.checkBubbleIntersection(self.bubble3)
            break
        default:
            return
        }
    }
}

private func hitBubble(_ index: Int){
    arrayVelosity[index].y = -arrayVelosity[index].y
    arrayVelosity[index].x = -arrayVelosity[index].x
}

private func checkBubbleIntersection(_ firstBubble: SKButton){
    for bubble in arrayBubbles {
        if firstBubble.name != bubble!.name{
            if firstBubble.frame.insetBy(dx: 80,dy: 80).intersects(bubble!.frame){
                guard let indexBubble = self.arrayBubbles.firstIndex(of: bubble) else { return }
                self.hitBubble(indexBubble)
            }
        }
    }
}

override func update(_ currentTime: TimeInterval) {

    if lastUpdateTime > 0{
        dt = currentTime - lastUpdateTime

    } else{
        dt = 0
    }
    lastUpdateTime = currentTime

    for bubble in arrayBubbles{
        if bubble != nil {
            guard let index = arrayBubbles.firstIndex(of: bubble) else { return }

            moveSprite(sprite: arrayBubbles[index]!, velosity: arrayVelosity[index])
            boundsCheckBubbles(sprite: arrayBubbles[index]!, index: index)
        }
    }
}

private func moveSprite(sprite: SKButton, velosity: CGPoint){
    let amountToMove = CGPoint(x: velosity.x * CGFloat(dt), y: velosity.y * CGFloat(dt))
    sprite.position = CGPoint(x: sprite.position.x + amountToMove.x,
                              y: sprite.position.y + amountToMove.y)

}

private func boundsCheckBubbles(sprite: SKButton, index: Int){
    let bottomLeft = CGPoint(x: 80, y: playableRect.minY)
    let topRight = CGPoint(x: size.width-80, y: playableRect.maxY)

    if sprite.position.x <= bottomLeft.x{
        sprite.position.x = bottomLeft.x
        arrayVelosity[index].x = -arrayVelosity[index].x
    }
    if sprite.position.x >= topRight.x{
        sprite.position.x = topRight.x
        arrayVelosity[index].x = -arrayVelosity[index].x
    }
    if sprite.position.y <= bottomLeft.y{
        sprite.position.y = bottomLeft.y
        arrayVelosity[index].y = -arrayVelosity[index].y
    }
    if sprite.position.y >= topRight.y{
        sprite.position.y = topRight.y
        arrayVelosity[index].y = -arrayVelosity[index].y
    }
}}
class游戏场景:SKScene{
私有变量arrayBubbles=[SKButton?]()
私有变量arrayVelosity=[CGPoint]()
私有变量bubbleMovePointsPerSecX=[CGFloat]()
私有变量bubbleMovePointsPerSecY=[CGFloat]()
私有变量currentVelocity:CGPoint!
私有变量lastUpdateTime:TimeInterval=0
私有变量dt:TimeInterval=0
私有let最小值=0
私人出租最大值=3
private let bubbleTexture=SKTexture(图像名为:“bubble”)
私人let playableRect:CGRect!
惰性变量背景:SKSpriteNode={
let back=SKSpriteNode(图像名为“back”)
back.position=CGPoint(x:self.size.width/2,y:size.height/2)
back.anchorPoint=CGPoint(x:0.5,y:0.5)
back.zPosition=-1
返回
}()
惰性变量bubble1:SKButton={
var button=SKButton(纹理:bubbleTexture,颜色:。清除,大小:bubbleTexture.size())
button.position=CGPoint(x:size.width/2,y:size.height-(size.height/3))
按钮。设置刻度(0)
button.zPosition=1
button.name=“bubble1”
返回按钮
}()
惰性变量bubble2:SKButton={
var button=SKButton(纹理:bubbleTexture,颜色:。清除,大小:bubbleTexture.size())
button.position=CGPoint(x:size.width/3,y:size.height/2)
按钮。设置刻度(0)
button.zPosition=1
button.name=“bubble2”
返回按钮
}()
惰性变量bubble3:SKButton={
var button=SKButton(纹理:bubbleTexture,颜色:。清除,大小:bubbleTexture.size())
button.position=CGPoint(x:size.width-(size.width/3),y:size.height/2)
按钮。设置刻度(0)
button.zPosition=1
button.name=“bubble3”
返回按钮
}()
重写初始化(大小:CGSize){
让可玩高度=尺寸、宽度/(16.0/9.0)
让可玩边距=(size.height-可玩高度)/2
playableRect=CGRect(x:0,y:playableMargin,宽度:size.width,高度:playableHeight)
super.init(大小:size)
}
必需的初始化?(编码器aDecoder:NSCoder){
fatalError(“初始化(编码者:)尚未实现”)
}
覆盖func didMove(到视图:SKView){
addChilds()
附体
setRandomBubbleSpead()
AppendVelocityToArray()
showapearubble()
}
私有函数addChilds(){
addChild(背景)
addChild(bubble1)
addChild(bubble2)
addChild(bubble3)
}
私有函数appendBubbleStoreray(){
arrayBubbles.append(bubble1)
arrayBubbles.append(bubble2)
arrayBubbles.append(bubble3)
}
私有函数setRandomBubbleSpead(){

因为我自己能够解决这个问题。 但我找到了另一种方法来解决这个问题。我使用位掩码和冲突

class GameScene: SKScene, SKPhysicsContactDelegate {

private var arrayBubbles = [SKButton?]()

private var bubbleTexture = SKTexture(image: #imageLiteral(resourceName: "Oval"))
private let playableRect: CGRect!

let bubble1Category:UInt32 = 0x1 << 0;
let bubble2Category:UInt32 = 0x1 << 1;
let bubble3Category:UInt32 = 0x1 << 2;
let borderCategory:UInt32 = 0x1 << 10

var borderBody: SKPhysicsBody!

lazy var bubble1: SKButton = {
    var button = SKButton(texture: bubbleTexture, color: .clear, size: bubbleTexture.size())
    button.position = CGPoint(x: size.width/2, y: size.height - (size.height/3))
    button.zPosition = 1
    button.name = "bubble1"
    button.physicsBody = SKPhysicsBody(circleOfRadius: bubbleTexture.size().width/2)
    button.physicsBody?.categoryBitMask = bubble1Category
    button.physicsBody?.contactTestBitMask = bubble2Category | bubble3Category | borderCategory
    button.physicsBody!.collisionBitMask = bubble2Category | bubble3Category | borderCategory
    button.physicsBody?.affectedByGravity = false
    button.physicsBody?.linearDamping = 0.0
    button.physicsBody?.restitution = 0.0
    return button
}()

lazy var bubble2: SKButton = {
    var button = SKButton(texture: bubbleTexture, color: .clear, size: bubbleTexture.size())
    button.position = CGPoint(x: size.width/3, y: size.height/2)
    button.zPosition = 1
    button.name = "bubble2"
    button.physicsBody = SKPhysicsBody(circleOfRadius: bubbleTexture.size().width/2)
    button.physicsBody?.categoryBitMask = bubble2Category
    button.physicsBody?.contactTestBitMask = bubble1Category | bubble3Category | borderCategory
    button.physicsBody!.collisionBitMask = bubble1Category | bubble3Category | borderCategory
    button.physicsBody?.affectedByGravity = false
    button.physicsBody?.linearDamping = 0.0
    button.physicsBody?.restitution = 0.0
    return button
}()

lazy var bubble3: SKButton = {
    var button = SKButton(texture: bubbleTexture, color: .clear , size: bubbleTexture.size())
    button.position = CGPoint(x: size.width - (size.width/3), y: size.height/2)
    button.zPosition = 1
    button.name = "bubble3"
    button.physicsBody = SKPhysicsBody(circleOfRadius: bubbleTexture.size().width/2)
    button.physicsBody?.categoryBitMask = bubble3Category
    button.physicsBody?.contactTestBitMask = bubble1Category | bubble2Category | borderCategory
    button.physicsBody!.collisionBitMask = bubble1Category | bubble2Category | borderCategory
    button.physicsBody?.affectedByGravity = false
    button.physicsBody?.linearDamping = 0.0
    button.physicsBody?.restitution = 0.0
    return button
}()

override init(size: CGSize) {
    let playableHeight = size.width/(16.0/9.0)
    let playableMargin = (size.height - playableHeight)/2

    playableRect = CGRect(x: 0, y: playableMargin, width: size.width, height: playableHeight)
    super.init(size:size)
}

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

override func didMove(to view: SKView) {
    self.physicsWorld.contactDelegate = self
    physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)

    // Set border property
    setBorderBody()

    addChilds()
    appendBubblesToArray()
    showApearBubble()

    setFirstBubbleVelosity()
}

func setFirstBubbleVelosity(){
    for bubble in arrayBubbles{
        bubble!.physicsBody?.velocity = calculateRandomBubbleVelosity()
    }
}

func setBorderBody(){
    borderBody = SKPhysicsBody(edgeLoopFrom: self.frame)
    borderBody.categoryBitMask = borderCategory
    borderBody.friction = 0.0
    self.physicsBody = borderBody
}

func didBegin(_ contact: SKPhysicsContact) {
    let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

    switch contactMask {
    case bubble1Category | bubble2Category:
        bubble1.physicsBody?.velocity = calculateRandomBubbleVelosity()
    case bubble1Category | bubble3Category:
        bubble1.physicsBody?.velocity = calculateRandomBubbleVelosity()
    case bubble1Category | borderCategory:
        bubble1.physicsBody?.velocity = calculateRandomBubbleVelosity()

    case bubble2Category | bubble1Category:
        bubble2.physicsBody?.velocity = calculateRandomBubbleVelosity()
    case bubble2Category | bubble3Category:
        bubble2.physicsBody?.velocity = calculateRandomBubbleVelosity()
    case bubble2Category | borderCategory:
        bubble2.physicsBody?.velocity = calculateRandomBubbleVelosity()

    case bubble3Category | bubble1Category:
        bubble3.physicsBody?.velocity = calculateRandomBubbleVelosity()
    case bubble3Category | bubble2Category:
        bubble3.physicsBody?.velocity = calculateRandomBubbleVelosity()
    case bubble3Category | borderCategory:
        bubble3.physicsBody?.velocity = calculateRandomBubbleVelosity()
    default: print("Unknown contact detected")
    }
}

private func addChilds(){
    addChild(bubble1)
    addChild(bubble2)
    addChild(bubble3)
}

private func appendBubblesToArray(){
    arrayBubbles.append(bubble1)
    arrayBubbles.append(bubble2)
    arrayBubbles.append(bubble3)
}

private func calculateRandomBubbleVelosity() -> CGVector{
    let randomVelosityByX = CGFloat.random(in: -200..<200)
    let randomVelosityByY = CGFloat.random(in: -200..<200)
    let randomVelosity = CGVector(dx: randomVelosityByX * cos(100.0), dy: randomVelosityByY * sin(100.0))
    return randomVelosity
}

private func showApearBubble(){
    bubble1.setScale(1.5)
    bubble2.setScale(1.5)
    bubble3.setScale(1.5)
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first{
        enumerateChildNodes(withName: "bubble1") {  node, _ in

            let bubble = node as! SKButton
            if bubble.contains(touch.location(in: self)){

                //Some your logic

            }
        }
    }
}}
类游戏场景:SKScene,skphysiccontactdelegate{
私有变量arrayBubbles=[SKButton?]()
私有变量bubbleTexture=SKTexture(图像:#imageLiteral(资源名称:“椭圆形”))
私人let playableRect:CGRect!

让bubble1Category:UInt32=0x1共享的代码的上下文确实不够。您共享碰撞函数,但不共享它的使用位置,因此很难判断实际发生了什么。