swift sprite-kit skphysicsbody

swift - juego de sprite kit rápido cuando disparo a un enemigo a veces la bala atraviesa al enemigo, ¿cómo puedo solucionarlo?



sprite-kit skphysicsbody (4)

Estoy haciendo un juego en el kit de sprites (2D) .

Tengo este código:

meteor.physicsBody = SKPhysicsBody(rectangleOfSize: enemy.size)

y tengo una imagen de meteorito que necesitas destruir, pero a veces, cuando disparo en mi dispositivo al meteoro, la bala atraviesa el meteoro. ¿Es esto un error o hice algo mal? y ¿Cómo puedo solucionar este problema?

gracias por leer mi problema, ¡espero que alguien pueda ayudarme! si no entiendes mi pregunta, por favor comenta lo que no entiendes.

func fireBullet() { let bullet = SKSpriteNode(imageNamed: "bullet") bullet.name = "Bullet" bullet.setScale(2.9) bullet.position = player.position bullet.zPosition = 1 bullet.physicsBody = SKPhysicsBody(rectangleOfSize: bullet.size) bullet.physicsBody!.affectedByGravity = false bullet.physicsBody!.categoryBitMask = PhysicsCategories.Bullet bullet.physicsBody!.collisionBitMask = PhysicsCategories.None bullet.physicsBody!.contactTestBitMask = PhysicsCategories.Meteor self.addChild(bullet) let moveBullet = SKAction.moveToY(self.size.height + bullet.size.height, duration: 1) let deleteBullet = SKAction.removeFromParent() let bulletSequence = SKAction.sequence([bulletSound, moveBullet, deleteBullet]) bullet.runAction(bulletSequence) } func spawnMeteor(){ let randomXStart = random(min: CGRectGetMinX(gameArea), max: CGRectGetMaxX(gameArea)) let randomXEnd = random(min: CGRectGetMinX(gameArea), max: CGRectGetMaxX(gameArea)) let startPoint = CGPoint(x: randomXStart, y: self.size.height * 1.2) let endPoint = CGPoint(x: randomXEnd, y: -self.size.height * 0.2) let Meteor = SKSpriteNode(imageNamed: "Meteor/(arc4random_uniform(2))") Meteor.name = "Meteor" Meteor.setScale(0.2) Meteor.position = startPoint Meteor.zPosition = 2 Meteor.physicsBody = SKPhysicsBody(rectangleOfSize: meteor.size) Meteor.physicsBody!.affectedByGravity = false Meteor.physicsBody!.categoryBitMask = PhysicsCategories.Meteor Meteor.physicsBody!.collisionBitMask = PhysicsCategories.None Meteor.physicsBody!.contactTestBitMask = PhysicsCategories.Player | PhysicsCategories.Bullet self.addChild(Meteor) let moveMeteor = SKAction.moveTo(endPoint, duration: 2) let deleteMeteor = SKAction.removeFromParent() let loseALifeAction = SKAction.runBlock(loseALife) let MeteorSequence = SKAction.sequence([moveMeteor, deleteMeteor, loseALifeAction]) if currentGameState == gameState.inGame{ Meteor.runAction(MeteorSequence) } let dx = endPoint.x - startPoint.x let dy = endPoint.y - startPoint.y let amountToRotate = atan2(dy, dx) enemy.zRotation = amountToRotate } func didBeginContact(contact: SKPhysicsContact) { var body1 = SKPhysicsBody() var body2 = SKPhysicsBody() if contact.bodyA.collisionBitMask < contact.bodyB.categoryBitMask{ body1 = contact.bodyA body2 = contact.bodyB } else{ body1 = contact.bodyB body2 = contact.bodyA } if body1.categoryBitMask == PhysicsCategories.Player && body2.categoryBitMask == PhysicsCategories.Meteor{ //if the player has hit the meteor if body1.node != nil { spawnExplosion(body1.node!.position) } if body2.node != nil { spawnExplosion(body2.node!.position) } body1.node?.removeFromParent() body2.node?.removeFromParent() runGameOver() } if body1.categoryBitMask == PhysicsCategories.Bullet && body2.categoryBitMask == PhysicsCategories.Meteor && body2.node?.position.y < self.size.height { //if the bullet has hit the meteor addScore() if body2.node != nil{ spawnExplosion(body2.node!.position) spawnPlusScore(body2.node!.position) } body1.node?.removeFromParent() body2.node?.removeFromParent() }


Creo que su problema está dentro del código de la bala:

let moveBullet = SKAction.moveToY(self.size.height + bullet.size.height, duration: 1) let deleteBullet = SKAction.removeFromParent() let bulletSequence = SKAction.sequence([bulletSound, moveBullet, deleteBullet]) bullet.runAction(bulletSequence)

Trate de reemplazar con bullet.physicsBody?.applyImpulse(CGVectorMake( 0, 20)) lugar de SKAction.moveToY y elimine la viñeta si sale de la pantalla


Creo que una forma más clara de codificar didBeginContact es la siguiente:

func didBeginContact(contact: SKPhysicsContact) { let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask switch contactMask case PhysicsCategories.Player | PhysicsCategories.Meteor : // The player and the meteor have contacted spawnExplosion(contact.contactPoint) //Create explosion where they touch contact.bodyA.node.removeFromParent() contact.bodyB.node.removeFromParent() runGameOver() case PhysicsCategories.Bullet| PhysicsCategories.Meteor : // The bullet and meteor have contacted // body2.node?.position.y < self.size.height // ?? Not sure what this is addScore() spawnExplosion(contact.contactPoint) //Create explosion where they touch contact.bodyA.node.removeFromParent() contact.bodyB.node.removeFromParent() default: print("Other contact detected") }

Cambié tu código para crear una explosión en el lugar donde tocan los dos cuerpos; si quieres 2 explosiones, cada una centrada en los nodos que tocan, usa:

spawnExplosion(contact.bodyA.node.position) spawnExplosion(contact.bodyB.node.position)

o:

for node in [contact.bodyA.node, contact.bodyB.node] { spawnExplosion(node.position) }


En lugar de configurar tus collisionBitMasks a cero, intenta configurarlas así:

bullet.physicsBody!.collisionBitMask = PhysicsCategories.Meteor Meteor.physicsBody!.collisionBitMask = PhysicsCategories.Bullet

Intenta cambiar el comienzo de tu método didBeginContact a esto:

var body1 = contact.bodyA.node as! SKSpriteNode var body2 = contact.bodyB.node as! SKSpriteNode if (body1.categoryBitMask == PhysicsCategories.Player && body2.categoryBitMask == PhysicsCategories.Meteor) || (body2.categoryBitMask == PhysicsCategories.Player && body1.categoryBitMask == PhysicsCategories.Meteor) { //if the player has hit the meteor spawnExplosion(body1.position) spawnExplosion(body2.position) body1.removeFromParent() body2.removeFromParent() runGameOver() }

No puedo decir que la spawnExplosion funcionará porque no puedo ver lo que hace, pero esto debería eliminar los nodos.