I am trying to write some logic using Swift 4 and SpriteKit to allow the user to move the spaceship around using a drag action while also allowing them to shoot a projectile. I can drag the spaceship around with my left thumb, but once I begin shooting with my right thumb by tapping, the spaceship stops moving.
I have enabled 'enableMultiTouch' in the viewDidLoad(). I feel as though I am very close to having this working, I am just missing a piece to allow a user to do both at the same time. Thanks in advance.
Here is what I have so far:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let touchLocation = touch!.location(in: self)
if player.contains(touchLocation) {
playerIsTouched = true
} else {
// 2 - Set up initial location of projectile
let projectile = SKSpriteNode(imageNamed: "projectile")
projectile.position = player.position
projectile.physicsBody = SKPhysicsBody(circleOfRadius: projectile.size.width/2)
projectile.physicsBody?.isDynamic = true
projectile.physicsBody?.categoryBitMask = PhysicsCategory.projectile
projectile.physicsBody?.contactTestBitMask = PhysicsCategory.monster
projectile.physicsBody?.collisionBitMask = PhysicsCategory.none
projectile.physicsBody?.usesPreciseCollisionDetection = true
// 3 - Determine offset of location to projectile
let offset = touchLocation - projectile.position
// 4 - Bail out if you are shooting down or backwards
if offset.x < 0 {
return
} else {
run(SKAction.playSoundFileNamed("laser-shot-basic.wav", waitForCompletion: false))
shotsFired += 1
accuracyLabel.text = "\(trunc((shotsHit/shotsFired*100) * 10)/10)% Accuracy"
}
// 5 - OK to add now - you've double checked position
addChild(projectile)
// 6 - Get the direction of where to shoot
let direction = offset.normalized()
// 7 - Make it shoot far enough to be guaranteed off screen
let shootAmount = direction * 1000
// 8 - Add the shoot amount to the current position
let realDest = shootAmount + projectile.position
// 9 - Create the actions
let actionMove = SKAction.move(to: realDest, duration: 2.0)
let actionMoveDone = SKAction.removeFromParent()
projectile.run(SKAction.sequence([actionMove, actionMoveDone]))
}
if pauseButton.contains(touchLocation) {
run(gameLostSound, completion: {
let scene = LevelSelectScene(size: self.size)
self.view?.presentScene(scene)
})
}
// for touch: AnyObject in touches {
// let pointOfTouch = touch.location(in: self)
// let previousPointOfTouch = touch.previousLocation(in: self)
//
// let amountDragged = pointOfTouch.x - previousPointOfTouch.x
//
// player.position.x += amountDragged
// }
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if (playerIsTouched == true) {
player.position = (touches.first?.location(in: self))!
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
// 1 - Choose one of the touches to work with
guard let touch = touches.first else {
return
}
let touchLocation = touch.location(in: self)
if playerIsTouched {
playerIsTouched = false
}
}
When you tap-to-fire that will cause two events: a 'begins' and an 'ends' event. However your touchesEnded method does not distinguish which touch has just ended, and sets your playerIsTouched parameter to false, thus further movement ceases.
There are multiple ways of fixing this, depending on the larger and future structure of the app, but one way would be: in touchesEnded , use the location of the touch to determine whether it is the drag touch that has ended and only reset playerIsTouched if that is the case.
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.