首页 > 解决方案 > 在 GameKit 中更改子父级

问题描述

我正在做一个射箭游戏——玩家需要向一个移动的目标射击 3 支箭(目标从左向右移动)。当箭头击中目标时,它应该随之移动(从左到右)。最明显的做法是将箭头父级更改为目标。由于某种原因,它给我带来了一些麻烦-

  1. 我尝试了 --- arrow.move(toParent:target) ,即使我为它设置了新位置,我也看不到屏幕上的箭头
  2. 如果我只是 --- target.addChild(arrow) 我会失败,因为我没有从其父级中删除箭头(这是本例中的场景)
  3. 当我 --- arrow.removeFromParent() 然后 target.addChild(arrow) 导致其他箭头相互碰撞时,我仍然看不到屏幕上的箭头。

这是我的代码 -

class GameScene: SKScene, SKPhysicsContactDelegate {

var target:SKSpriteNode?
var arrows = [SKSpriteNode]()
var arrowContactPoint:CGPoint?

let noCategory:UInt32 = 0
let arrowCategory:UInt32 = 0b1
let targetCategory:UInt32 = 0b1 << 1
let obstacleCategory:UInt32 = 0b1 << 2

override func didMove(to view: SKView) {
    allowCollisionDetection()
    setTarget()
    moveTargetFromSideToSide()
    newArrow()
}

func didBegin(_ contact: SKPhysicsContact) {
    let categoryBitMaskBodyA:UInt32 = contact.bodyA.categoryBitMask
    let categoryBitMaskBodyB:UInt32 = contact.bodyB.categoryBitMask

    if ((categoryBitMaskBodyA == targetCategory && categoryBitMaskBodyB == arrowCategory) || (categoryBitMaskBodyA == arrowCategory && categoryBitMaskBodyB == targetCategory)) {
        arrowContactPoint = contact.contactPoint
        arrowCollideWithTarget()
    } else if (categoryBitMaskBodyA == obstacleCategory || categoryBitMaskBodyB == obstacleCategory) {
        let obstacleNode:SKNode = ((categoryBitMaskBodyA == arrowCategory) ? contact.bodyA.node! : contact.bodyB.node)!
        arrowCollideWithObstacle(obstacle:obstacleNode)
    } else if (categoryBitMaskBodyA == arrowCategory && categoryBitMaskBodyB == arrowCategory) {
        newGame()
    } else {
        print("Something went wrong")
    }

    newArrow()
}

func touchDown(atPoint pos : CGPoint) {

}

func touchMoved(toPoint pos : CGPoint) {

}

func touchUp(atPoint pos : CGPoint) {
    shootArrow()
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    for t in touches { self.touchDown(atPoint: t.location(in: self)) }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}

override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
    for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}

override func update(_ currentTime: TimeInterval) {
    // Called before each frame is rendered

}

func allowCollisionDetection() {
    self.physicsWorld.contactDelegate = self
}

func setTarget() {
    target = self.childNode(withName: "target") as? SKSpriteNode
    //Set the target bit mask, it's tag
    target?.physicsBody?.categoryBitMask = targetCategory
    //Set with which objects the target collide
    target?.physicsBody?.collisionBitMask = noCategory
    //Set to which coliision we want to responde/handle - didBegin will get triggered
    target?.physicsBody?.contactTestBitMask = arrowCategory
}

func moveTargetFromSideToSide() {
    let moveRight = SKAction.moveBy(x: frame.size.width - (target?.size.width)!, y: 0, duration: 2)
    let moveLeft = SKAction.moveBy(x: -(frame.size.width - (target?.size.width)!), y: 0, duration: 2)
    let moveBackAndForth = SKAction.repeatForever(SKAction.sequence([moveRight, moveLeft]))
    target?.run(moveBackAndForth)
}

func newArrow() {
    let arrow = SKSpriteNode(imageNamed: "arrow1")
    let arrowTexture = SKTexture(imageNamed: "arrow1")
    arrow.position = CGPoint.zero
    self.addChild(arrow)
    arrow.physicsBody = SKPhysicsBody(texture: arrowTexture, size: arrowTexture.size())
    arrow.physicsBody?.isDynamic = true
    arrow.physicsBody?.allowsRotation = true
    arrow.physicsBody?.affectedByGravity = false
    arrow.physicsBody?.friction = 0.2
    arrow.physicsBody?.restitution = 0.2
    arrow.physicsBody?.linearDamping = 0.1
    arrow.physicsBody?.angularDamping = 0.1
    arrow.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
    arrow.physicsBody?.categoryBitMask = arrowCategory
    arrow.physicsBody?.collisionBitMask = noCategory
    arrow.physicsBody?.contactTestBitMask = arrowCategory | obstacleCategory | targetCategory
    arrows.append(arrow)
}

func shootArrow(){
    print("shootArrow")
    arrows.last!.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 80))
}

func arrowCollideWithTarget() {
    print("arrowCollideWithTarget")
    arrows.last!.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
    arrows.last!.move(toParent: target!)
}

func arrowCollideWithObstacle(obstacle:SKNode) {
    print("arrowCollideWithObstacle")
    arrows.last!.removeFromParent()
    arrows.removeLast()
}

func newGame() {
    print("New Game")
    for i in 0 ..< (arrows.count) {
        arrows[i].removeFromParent()
    }
    arrows.removeAll()
}

}

标签: swiftsprite-kit

解决方案


最终为我解决的问题是使用这种方法 --- move(toParent: )

这是我的代码 -

func arrowCollideWithTarget() {
    arrows.last!.move(toParent:target!)
}

推荐阅读