I have three nodes in my game-
The Player -
This is a boat that you drag around using a joystick.
let collisionPlayer : UInt32 = 0x1 << 1
let apple = SKSpriteNode(texture: texture)
apple.position = position
apple.physicsBody = SKPhysicsBody(circleOfRadius: apple.size.width / 2.0)
apple.physicsBody?.affectedByGravity = false
apple.physicsBody?.isDynamic = true
apple.setScale(0.1)
addChild(apple)
("apple" is the boat)
The Enemy Boat -
This is a CPU boat that randomly follows the player around.
let collisionNPC : UInt32 = 0x1 << 0
appleNPC.position = position
appleNPC.physicsBody = SKPhysicsBody(circleOfRadius: appleNPC.size.width / 2.0)
appleNPC.physicsBody?.isDynamic = true
appleNPC.physicsBody?.affectedByGravity = false
appleNPC.position = CGPoint(x: 600, y: 200)
appleNPC.setScale(0.1)
addChild(appleNPC)
The Bullet (self-explanatory)
let collisionBullet : UInt32 = 0x1 << 2
(The following code is in TouchesEnded)
bullet?.name = "Bullet"
bullet?.position = (appleNode?.position)!
bullet?.setScale(0.05)
bullet?.zPosition = 1
bullet?.physicsBody = SKPhysicsBody(circleOfRadius: (bullet?.size.width)!/2)
bullet?.physicsBody?.isDynamic = true
bullet?.physicsBody?.affectedByGravity = false
bullet?.physicsBody?.usesPreciseCollisionDetection = true
To move the bullet I use the code:
// Your code with delay
if bulletNumbers > 0 {
let offset = CGPoint(x: touchLocation.x - (bullet?.position.x)! , y: touchLocation.y - (bullet?.position.y)!)
//Stops Bullet from shooting backwards
//Get the direction of where to shoot
let direction = offset
//Make it shoot far enough to be guaranteed off screen
let shootAmount = CGPoint(x: direction.x * 10, y: direction.y * 10)
//Add the shoot amount to the current position
let realDest = CGPoint(x: shootAmount.x + (bullet?.position.x)!, y: shootAmount.y + (bullet?.position.y)!)
//Create the actions
addChild(bullet!)
self.bulletNumbers -= 1
let distance = sqrt(pow(realDest.x - (appleNode?.position.x)!, 2) +
pow(realDest.y - (appleNode?.position.y)!, 2))
// run the sequence of actions for the firing
let duration = TimeInterval(distance / PlayerMissileSpeed)
let missileMoveAction = SKAction.move(to: realDest, duration: duration)
let when = DispatchTime.now() + 10 // change 2 to desired number of seconds
DispatchQueue.main.asyncAfter(deadline: when) { self.bulletNumbers += 1
}
bullet?.run(missileMoveAction) {
self.bullet?.isHidden = true
self.bullet?.removeFromParent()
print("\(self.bulletNumbers)")
}}
else if bulletNumbers <= 0 {
print("reload")
let when = DispatchTime.now() + 2 // change 2 to desired number of seconds
DispatchQueue.main.asyncAfter(deadline: when) {
}
}
}
func didBegin(_ contact: SKPhysicsContact) {
print("test")
}
func setRandomStickColor() {
let randomColor = UIColor.random()
moveAnalogStick.stick.color = randomColor
}
func setRandomSubstrateColor() {
let randomColor = UIColor.random()
moveAnalogStick.substrate.color = randomColor
}
override func update(_ currentTime: TimeInterval) {
/* Called before each frame is rendered */
super.update(currentTime)
let _:UInt32 = arc4random_uniform(1) //
appleNodeCpuSpeed = CGFloat(1)
var locationx : CGFloat
var locationy: CGFloat
locationx = (appleNode?.position.x)!
locationy = (appleNode?.position.y)!
let dx = locationx - (appleNodeNPC?.position.x)!
let dy = locationy - (appleNodeNPC?.position.y)!
let angle = atan2(dy, dx)
let vx = cos(angle) * appleNodeCpuSpeed
let vy = sin(angle) * appleNodeCpuSpeed
self.appleNodeNPC?.position.x += vx
self.appleNodeNPC?.position.y += vy
let when = DispatchTime.now() + 0.25 // change 2 to desired number of seconds
DispatchQueue.main.asyncAfter(deadline: when) {
self.appleNodeNPC?.zRotation = angle + 90
}
//2
This works fine. The bullet is launched from the boat to the touch location, however, things start to go wrong when I tried to introduce collisions. Here is my code below:
appleNode?.physicsBody?.categoryBitMask = collisionPlayer
appleNode?.physicsBody?.collisionBitMask = collisionNPC
appleNode?.physicsBody?.contactTestBitMask = 0
appleNodeNPC?.physicsBody?.categoryBitMask = collisionNPC
appleNodeNPC?.physicsBody?.collisionBitMask = collisionPlayer
appleNodeNPC?.physicsBody?.contactTestBitMask = collisionBullet
bullet?.physicsBody?.categoryBitMask = collisionBullet
bullet?.physicsBody?.collisionBitMask = 0
bullet?.physicsBody?.contactTestBitMask = collisionNPC
physicsWorld.contactDelegate = self
view.showsPhysics = true
Then in my didBegin function I have:
func didBegin(_ contact: SKPhysicsContact) {
print("test")
}
Let's start from the beginning. I tap the screen and the bullet is launched. The bullet does not collide with the Player, which is what I originally wanted. However, when the bullet makes contact with the Enemy ship it DOES collide. It goes around the ship and keeps going on to its original destination. I want the bullet to contact the ship and nothing else - no collisions. I would hope to assume that my error here is because of my code for moving the bullet, but i'm not sure. Any help is appreciated.
SKPhysicsContactDelegate
and make yourself the physics contact delegate: //Physics categories
let appleCategory: UInt32 = 1 << 0
let enemyCategory: UInt32 = 1 << 1
let bulletCategory: UInt32 = 1 << 2
class GameScene: SKScene, SKPhysicsContactDelegate {
physicsWorld.contactDelegate = self
Assign the categories (usually in didMove(to view:)
:
apple.physicsBody.catgeoryBitMask = appleCategory enemy.physicsBody.catgeoryBitMask = enemyCategory bullet.physicsBody.catgeoryBitMask = bulletCategory
(Make sure you've created physics bodies for each node)
apple.physicsBody?.collisionBitMask = 0 // apple/player collides with nothing enemy.physicsBody?.collisionBitMask = 0 // enemy collides with nothing bullet.physicsBody?.collisionBitMask = 0 // bullet collides with nothing
or even:
for node in [apple, enemy, bullet] {
node.physicsBody?.collisionBitMask = 0 // collides with nothing
}
Set up contacts
bullet.physicsBody?.collisionBitMask = enemyCategory // bullet contacts enemy
Make sure that at least one of the objects involved in each potential contact has the isDynamic
property on its physics body set to true
, or no contact will be generated. It is not necessary for both of the objects to be dynamic.
You should now get didBegin
called when the bullet and the enemy make contact. You could code didBegin
like this:
func didBegin(_ contact: SKPhysicsContact) {
print("didBeginContact entered for \(String(describing: contact.bodyA.node!.name)) and \(String(describing: contact.bodyB.node!.name))")
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case bulletCategory | enemyCategory:
print("bullet and enemy have contacted.")
let bulletNode = contact.bodyA.categoryBitMask == bulletCategory ? contact.bodyA.node : contact.bodyB.node
enemyHealth -= 10
bulletNode.removeFromParent
default:
print("Some other contact occurred")
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.