2017-08-14 113 views
0

enter image description here將SKSpriteNode移動到觸摸位置

上面是我的遊戲的圖像。自上而下的遊戲。無論玩家在屏幕上觸摸什麼位置,我都希望子彈能夠持續一段時間到達該位置。我也希望玩家能夠在屏幕上拖動他的手指,同樣的事情發生。這樣玩家每次想要拍攝時都不必觸摸屏幕。

到目前爲止,我已經嘗試了一些不同的東西,但似乎沒有任何工作。

首先,我不知道我是否應該有一個單獨的子彈功能。但無論如何,這是我的子彈功能。

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) 
    } 

} 
+0

當你運行這段代碼時會發生什麼?我沒有自己運行這個代碼,或者對它進行了太密切的分析,但是它會編譯嗎?我認爲'touchesBegan'中的'bullet.run'將會無法編譯,沒有'bullet'屬性,我會創建一個'bulletTarget'屬性,將其用作'moveTo'位置,並創建並應用SKActi在你的'spawnBullet'方法中移動buller。 –

+0

我沒有得到任何錯誤,但子彈不動。我對應用程序開發有點新鮮,你是什麼意思的bulletTarget屬性? – Flinigan

+0

你在touchesBegan中定義'bullet.run(moveToPoint)'中使用的'bullet'變量在哪裏?你必須在某個地方定義它(帶'var bullet = ...')。如果它是在任何方法之外定義的(所以在全局範圍內),那麼它被稱爲「財產」。但是這個'子彈'幾乎肯定不是'spawnBullets'中添加到場景中的'子彈',這就是爲什麼它們不會移動。我會稍後嘗試根據您的代碼發佈答案。 –

回答

1

在這裏你去 - 一個簡單的應用程序,您可以在屏幕上拖動屏幕,並向觸摸位置發射導彈。

如果你觸摸船隻,你可以拖動它;觸及船外,導彈將從船上射向觸摸位置。

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))! 
} 
+0

哇,即使我不需要這個遊戲中的所有東西,所有這些在將來肯定對我有價值!謝謝!我希望播放器是靜態的,並且我從你的代碼中改變了一些東西來實現它。但有一個問題,你如何使用touchesMoved來讓玩家在每次想要改變子彈方向時都不必觸摸屏幕?而只是在屏幕上「拖動」手指並將子彈移動到該方向? – Flinigan

+0

@Flinigan我認爲(因爲你已經刪除了代碼來使船可以拖動),你可以在touchesMoved中設置'missileDestination'而不是'ship.position'。 –

+0

@Finegan查看我編輯的「固定船」和「跟隨」你的手指的導彈......任何沒有意義的東西,請問。 –