SpriteKit &Swift:通过 didBeginContact 创建节点会弄乱定位 [英] SpriteKit & Swift: Creating nodes via didBeginContact messes up the positioning

查看:23
本文介绍了SpriteKit &Swift:通过 didBeginContact 创建节点会弄乱定位的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不知道这是 Xcode 中的一个奇怪的错误,还是我不明白 SpriteKit 的坐标系有什么问题.

I don't know if this is a weird bug in Xcode or there's something about the SpriteKit's coordinate system I don't understand.

前提是节点的位置总是相对于它的父节点.但是,每当我从 SKPhysicsContactDelegate 的didBeginContact"调用一个创建和定位具有物理体的节点的块时,该节点总是相对于场景(而不是其父节点)定位.请注意,在除didBeginContact"之外的任何地方触发时,调用相同的块都会按预期工作.另一件事是,如果我移除所述节点的物理实体,即使从didBeginContact"调用,该块现在也可以按预期工作.

The premise is that the position of a node is always relative to its parent. However, whenever I call a block that creates and positions a node with a physics body from "didBeginContact" of SKPhysicsContactDelegate, the node is always positioned relative to the scene (instead of its parent). Note that calling this same block works as intended when triggered anywhere but "didBeginContact". Another thing is that, if I remove the physics body of the said node, the block will now work as intended even when called from "didBeginContact".

我已经被这个问题困住了两天,提供有关我的实际代码的其他详细信息太拖沓了.所以我做了一个非常简单的项目来演示这个异常.只需使用 Spritekit 模板在 Xcode 6 中创建一个新项目,然后将 GameViewController.swift 和 GameSwift.swift 替换为下面发布的代码.只需在 iPad Air 中运行,其他一切都应该一目了然.

I've been stuck with this issue for two days and it would be too draggy to give other details about my actual code. So I've made a very simple project demonstrating this anomaly. Just create a new project in Xcode 6 with Spritekit Template, and replace GameViewController.swift and GameSwift.swift with the codes posted below. Just run in iPad Air and everything else should be self explanatory.

最后说明:

  1. 当您按下第一个按钮并与第二个按钮接触时按钮,看看屏幕的左下角.你会看见盒子被错误地"定位在那里.
  2. 尝试移除AddBox"中盒子的物理实体.现在它将按预期工作.
  3. 如果您认为这是一个错误,或者坐标系或物理世界中存在我不理解的内容,请告诉我

GameViewController.swift:

GameViewController.swift:

import SpriteKit

class GameViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let scene = GameScene()
        scene.size = view.frame.size
        let skView = self.view as SKView
        scene.scaleMode = .AspectFill
        skView.presentScene(scene)
    }
}

GameScene.swift:

GameScene.swift:

import SpriteKit

let kButtonSize = CGSize(width: 500, height: 100)
let kContainerSize = CGSize(width: 500, height: 300)
let kBoxSize = CGSize(width: 25, height: 25)

class GameScene: SKScene, SKPhysicsContactDelegate {

    override func didMoveToView(view: SKView) {
        physicsWorld.contactDelegate = self
        addFirstButton()
        addSecondButton()
        addContainer()
    }

    func addFirstButton() {
        let button = SKSpriteNode(color: SKColor.blueColor(), size: kButtonSize)
        let label = SKLabelNode(text: "Call 'addBox' from didBeginContact")
        button.name = "firstButton"
        label.name = "firstLabel"
        button.position = CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame))
        button.physicsBody = SKPhysicsBody(rectangleOfSize: button.size)
        button.physicsBody.allowsRotation = false
        button.physicsBody.affectedByGravity = false
        button.physicsBody.categoryBitMask = 0x1
        button.physicsBody.contactTestBitMask = 0x1
        button.addChild(label)
        addChild(button)
    }

    func addSecondButton() {
        let button = SKSpriteNode(color: SKColor.blueColor(), size: kButtonSize)
        let label = SKLabelNode(text: "Call 'addBox' from touchesBegan")
        button.name = "secondButton"
        label.name = "secondLabel"
        button.position = CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame)-200)
        button.physicsBody = SKPhysicsBody(rectangleOfSize: button.size)
        button.physicsBody.dynamic = false
        button.physicsBody.categoryBitMask = 0x1
        button.physicsBody.contactTestBitMask = 0x1
        button.addChild(label)
        addChild(button)
    }

    func addContainer() {
        let container = SKSpriteNode(color: SKColor.greenColor(), size:kContainerSize)
        let label = SKLabelNode(text: "Created node should fall here")
        label.fontColor = SKColor.blackColor()
        container.name = "container"
        container.physicsBody = SKPhysicsBody(edgeLoopFromRect: container.frame)
        container.position = CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame)+300)
        container.addChild(label)
        addChild(container)
    }

    func addBox() {
        let container = childNodeWithName("container")
        let box = SKSpriteNode(color: SKColor.blueColor(), size: kBoxSize)
        box.physicsBody = SKPhysicsBody(rectangleOfSize: box.size)
        box.position = CGPointMake(0, 100)
        container.addChild(box)
    }

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        let touch = touches.anyObject() as UITouch
        let point = touch.locationInNode(self)
        let node = nodeAtPoint(point)
        if node.name == nil {return}

        switch node.name! {
        case "firstButton", "firstLabel":
            let button = childNodeWithName("firstButton") as SKSpriteNode
            button.physicsBody.applyImpulse(CGVectorMake(0, -500))
        case "secondButton", "secondLabel":
            addBox()
        default:
            break
        }
    }

    func didBeginContact(contact: SKPhysicsContact!) {
        addBox()
    }
}

推荐答案

我已通过 Apple 错误报告提交了关于此问题的票证.我希望这可以帮助遇到相同问题的任何人.以下是他们的回复:

I have submitted a ticket regardomg this issue with Apple Bug Report. I hope this helps anyone who is encountering the same issue. Here is their response:

Apple 开发者关系 24-Sep-2014 04:40 AM

Apple Developer Relations24-Sep-2014 04:40 AM

工程已确定这是一个需要您解决的问题基于以下几点:

Engineering has determined that this is an issue for you to resolve based on the following:

您不能修改正在模拟的树,这是编程指南中明确说明.

You can't modify a tree which it is being simulated, and this is clearly stated in Programming Guide.

这篇关于SpriteKit &Swift:通过 didBeginContact 创建节点会弄乱定位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆