I'm making a game in sprite kit (2D)
.
I have this code:
meteor.physicsBody = SKPhysicsBody(rectangleOfSize: enemy.size)
and I have a meteor image that you need to destroy but sometimes when I shoot on my device to the meteor the bullet goes through the meteor is this a bug or did I do something wrong? and How can I fix this issue?
thanks for reading my problem, I hope someone can help me! if you don't understand my question plz comment what you don't understand.
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()
}
Instead of setting your collisionBitMasks to zero, try setting them to this:
And try changing your the beginning of your didBeginContact method to this:
I can't say the spawnExplosion will work since I can't see what it does, but this should remove the nodes.
I think a neater way to code didBeginContact is as follows:
I changed your code to create one explosion wwhere the 2 bodies touch; if you want 2 explosions, each centered on the nodes that touch, use:
or:
I think your problem is inside the bullet code:
Try to replace with
bullet.physicsBody?.applyImpulse(CGVectorMake( 0, 20))
instead ofSKAction.moveToY
and remove bullet if go out the screenSpriteKit doesn't perform precise collision detection because it aims to achieve faster performance. You can make the physicsBody's property
usesPreciseCollisionDetection
to true, like this:https://developer.apple.com/reference/spritekit/skphysicsbody/1520014-usesprecisecollisiondetection
I don't know if it works, please let me know.