将SKSpriteNode移动到触摸位置

时间:2017-08-14 15:39:10

标签: swift sprite-kit skaction touchesbegan

enter image description here

以上是我游戏的图片。自上而下的比赛。无论玩家在屏幕上的哪个位置接触,我都希望子弹能够持续到达该位置。我还希望玩家能够在屏幕上拖动他的手指,同样的事情发生了。这样玩家每次想要拍摄时都不必触摸屏幕。

到目前为止,我尝试了一些不同的东西,但似乎没有任何效果。

首先,我不知道我是否应该为子弹有一个单独的功能。但无论如何,这是我的子弹功能。

func spawnBullets() {
    let bullet = SKSpriteNode(imageNamed: "Bullet")
    bullet.name = "Bullet"
    bullet.zPosition = 4
    bullet.position = CGPoint(x: player.position.x + 19, y: 
    player.position.y)
    self.addChild(bullet)
}

我还有一个"计时器"对于didMove函数中的项目符号:

var timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, 
selector: Selector("spawnBullets"), userInfo: nil, repeats: true)

最后,这是我的touchesBegan功能:

override func touchesBegan(_ touches: Set<UITouch>, with event: 
UIEvent?) {        
    for  touch in touches {            
        let location = touch.location(in: self)            
        let moveToPoint = SKAction.move(to: location, duration: 0.5)
        let repeatAction = SKAction.repeatForever(moveToPoint)            
        bullet.run(moveToPoint)
    }

}

1 个答案:

答案 0 :(得分:2)

在这里你 - 一个简单的应用程序,你可以在屏幕上拖动一个船,并向触摸位置射击。

如果你碰到船,可以拖动它;触摸船外,导弹将从船上射击到触摸位置。

import SpriteKit

class GameScene: SKScene {

var ship = SKSpriteNode()
var shipIsTouched = false
var missileDestination = CGPoint()
let missileSpeed: CGFloat = 800 // Points per second)
let missileFireRate : TimeInterval = 0.2 // Seconds between each missile

override func didMove(to view: SKView) {
    missileDestination = CGPoint(x: 0, y: (self.size.height / 2))
    createPlayerShip()
    let fire = SKAction.sequence([SKAction.run(fireMissile), SKAction.wait(forDuration: missileFireRate)])
    run(SKAction.repeatForever(fire))
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {
        if ship.contains(touch.location(in: self)) {
            shipIsTouched = true
        } else {
            missileDestination = touch.location(in: self)
            ship.zRotation = direction(to: missileDestination, from: ship.position) - CGFloat(Double.pi/2)
        }
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    if (shipIsTouched == true) {
        ship.position = (touches.first?.location(in: self))!
        ship.zRotation = direction(to: missileDestination, from: ship.position) - CGFloat(Double.pi/2)
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    if shipIsTouched {
        shipIsTouched = false
    }
}

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

func createPlayerShip() {
    ship = SKSpriteNode(imageNamed: "Spaceship")
    ship.zRotation = CGFloat(-Double.pi/2.0)
    ship.scale(to: CGSize(width: 150, height: 150))
    ship.position = CGPoint(x: -size.width/2 + 200, y: 0)

    addChild(ship)
}


func fireMissile() {
    let missile = SKSpriteNode(color: .white, size: CGSize(width: 50, height: 10))
    missile.position = ship.position

    let missileFlightTime = travelTime(to: missileDestination, from: ship.position, atSpeed: missileSpeed)
    missile.zRotation = direction(to: missileDestination, from: missile.position)

    addChild(missile)

    let missileMove = SKAction.move(to: missileDestination,
                                    duration: TimeInterval(missileFlightTime))
    let missileRemove = SKAction.removeFromParent()
    missile.run(SKAction.sequence([missileMove, missileRemove]))
}

func travelTime(to target : CGPoint, from : CGPoint, atSpeed speed : CGFloat) -> TimeInterval {
    let distance = sqrt(pow(abs(target.x - from.x),2) +
        pow(abs(target.y - from.y),2))
    return TimeInterval(distance/speed)
}


func direction(to target : CGPoint, from: CGPoint) -> CGFloat {
    let x = target.x - from.x
    let y = target.y - from.y
    var angle = atan(y / x)
    if x < 0 {
        angle = angle + CGFloat.pi
    }
    return angle
}
}

有一些额外的诡计让导弹速度保持一致(因为moveTo需要一段时间,而不是速度,所以如果目的地关闭,导弹将缓慢移动,如果距离更远,他们会移动更快)并且使导弹旋转以面向目的地。

您可以为导弹创建一个弯曲的路径,以便跟随目的地,这看起来很酷但可能不适合您的应用。

编辑:

如果您希望船舶静止不动,导弹会跟随您的手指,请将所有代码替换为createPlayerShip,这样做(是的,我们丢失了touchesEnded()update()

import SpriteKit

class GameScene: SKScene {

var ship = SKSpriteNode()
var missileDestination = CGPoint()
let missileSpeed: CGFloat = 800 // Points per second)
let missileFireRate : TimeInterval = 0.2 // Seconds between each missile

override func didMove(to view: SKView) {
    missileDestination = CGPoint(x: size.height/2, y: 0)
    createPlayerShip()
    let fire = SKAction.sequence([SKAction.run(fireMissile), SKAction.wait(forDuration: missileFireRate)])
    run(SKAction.repeatForever(fire))
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {
            missileDestination = touch.location(in: self)
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        missileDestination = (touches.first?.location(in: self))!
}