2017-07-02 62 views
1

我正在製作一個遊戲,其中球(玩家)設想避免其他球通過屏幕。基本上我希望球始終跟隨觸摸的位置。所以無論我將手指移動到屏幕上的哪個位置,都會有球。在整個屏幕上自由移動播放器

這是球員類:

import SpriteKit 

struct ColliderType { 

static let Player: UInt32 = 1 
static let Blue: UInt32 = 2 
static let Green: UInt32 = 3 
static let Yellow: UInt32 = 4 
static let Red: UInt32 = 5 

} 

class Player: SKSpriteNode { 

func initialize() { 
    self.name = "Player" 
    self.zPosition = 1 
    self.anchorPoint = CGPoint(x: 0.5, y: 0.5) 
    self.physicsBody = SKPhysicsBody(circleOfRadius: self.size.height/
2) 
    self.physicsBody?.affectedByGravity = false 
    self.physicsBody?.categoryBitMask = ColliderType.Player 
    self.physicsBody?.collisionBitMask = ColliderType.Blue | 
ColliderType.Green | ColliderType.Red | ColliderType.Yellow 
    self.physicsBody?.contactTestBitMask = ColliderType.Blue | 
ColliderType.Green | ColliderType.Red | ColliderType.Yellow 
} 

} 

這是GameplayScene:

import SpriteKit 

class GameplayScene: SKScene, SKPhysicsContactDelegate { 

var player = Player() 

var ball = SKSpriteNode() 

var scoreLabel = SKLabelNode() 
var score = 0 

var counter = Timer() 

override func didMove(to view: SKView) { 
    initialize() 
} 

override func update(_ currentTime: TimeInterval) { 

} 

override func touchesBegan(_ touches: Set<UITouch>, with event: 
UIEvent?) { 


    for touch in touches { 

     let location = touch.location(in: self) 

     if atPoint(location).name == "Retry" { 
      self.removeAllActions() 
      self.removeAllChildren() 
      initialize() 
     } 

     if atPoint(location).name == "Quit" { 
      let mainmenu = MainMenuScene(fileNamed: "MainMenuScene") 
      mainmenu!.scaleMode = .aspectFill 
      self.view?.presentScene(mainmenu!, transition: 
SKTransition.fade(withDuration: TimeInterval(1))) 
     } 

    } 

} 

override func touchesEnded(_ touches: Set<UITouch>, with event: 
UIEvent?) { 

} 

override func touchesMoved(_ touches: Set<UITouch>, with event: 
UIEvent?) { 

} 

func didBegin(_ contact: SKPhysicsContact) { 

    var firstBody = SKPhysicsBody() 
    var secondBody = SKPhysicsBody() 

    if contact.bodyA.node?.name == "Player" { 
     firstBody = contact.bodyA 
     secondBody = contact.bodyB 
    } else { 
     firstBody = contact.bodyB 
     secondBody = contact.bodyA 
    } 

    if firstBody.node?.name == "Player" && secondBody.node?.name == 
"Red" { 
     playerDied() 
     firstBody.node?.removeFromParent() 
    } 

    if firstBody.node?.name == "Player" && secondBody.node?.name == 
"Blue" { 
     playerDied() 
     firstBody.node?.removeFromParent() 
    } 

    if firstBody.node?.name == "Player" && secondBody.node?.name == 
"Green" { 
     playerDied() 
     firstBody.node?.removeFromParent() 
    } 

    if firstBody.node?.name == "Player" && secondBody.node?.name == 
"Yellow" { 
     playerDied() 
     firstBody.node?.removeFromParent() 
    } 

} 

func initialize() { 

    score = 0 

    physicsWorld.contactDelegate = self 

    createPlayer() 
    createBackground() 
    spawnRedBall() 
    spawnBlueBall() 
    spawnGreenBall() 
    spawnYellowBall() 
    createLabel() 

    counter = Timer.scheduledTimer(timeInterval: TimeInterval(0.7), 
target: self, selector: "incrementScore", userInfo: nil, repeats: true) 
} 

func createPlayer() { 
    player = Player(imageNamed: "Player") 
    player.initialize() 
    player.position = CGPoint(x: 0, y: 0) 
    self.addChild(player) 
} 

func createBackground() { 
    let bg = SKSpriteNode(imageNamed: "BG") 
    bg.name = "BG" 
    bg.anchorPoint = CGPoint(x: 0.5, y: 0.5) 
    bg.position = CGPoint(x: 0, y: 0) 
    self.addChild(bg) 
} 

func createRedBall() { 
    let ball = SKSpriteNode(imageNamed: "Red") 
    ball.name = "Red" 
    ball.anchorPoint = CGPoint(x: 0.5, y: 0.5) 
    ball.zPosition = 1 
    ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height/
2) 
    ball.physicsBody?.categoryBitMask = ColliderType.Red 
    ball.physicsBody?.affectedByGravity = false 
    ball.physicsBody?.isDynamic = false 

    ball.position.y = self.size.height + 100 
    ball.position.x = CGFloat.randomBetweenNumbers(firstNum: -345, 
secondNum: 345) 

    self.addChild(ball) 

    let destination = self.frame.height * 2 
    let move = SKAction.moveTo(y: -destination, duration: 
TimeInterval(10)) 
    let remove = SKAction.removeFromParent() 

    ball.run(SKAction.sequence([move, remove]), withKey: "MoveRed") 
} 

func spawnRedBall() { 

    let spawn = SKAction.run({() -> Void in 
     self.createRedBall() 
    }) 

    let delay = SKAction.wait(forDuration: TimeInterval(0.5)) 
    let sequence = SKAction.sequence([spawn, delay]) 

    self.run(SKAction.repeatForever(sequence), withKey: "SpawnRed") 
} 

func createBlueBall() { 
    let ball = SKSpriteNode(imageNamed: "Blue") 
    ball.name = "Blue" 
    ball.anchorPoint = CGPoint(x: 0.5, y: 0.5) 
    ball.zPosition = 1 
    ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height/
2) 
    ball.physicsBody?.categoryBitMask = ColliderType.Blue 
    ball.physicsBody?.affectedByGravity = false 
    ball.physicsBody?.isDynamic = false 

    ball.position.y = -self.size.height + 100 
    ball.position.x = CGFloat.randomBetweenNumbers(firstNum: -345, 
secondNum: 345) 

    self.addChild(ball) 

    let destination = self.frame.height * 2 
    let move = SKAction.moveTo(y: destination, duration: 
TimeInterval(10)) 
    let remove = SKAction.removeFromParent() 

    ball.run(SKAction.sequence([move, remove]), withKey: "MoveBlue") 
} 

func spawnBlueBall() { 

    let spawn = SKAction.run({() -> Void in 
     self.createBlueBall() 
    }) 

    let delay = SKAction.wait(forDuration: TimeInterval(0.5)) 
    let sequence = SKAction.sequence([spawn, delay]) 

    self.run(SKAction.repeatForever(sequence), withKey: "SpawnBlue") 
} 

func createGreenBall() { 
    let ball = SKSpriteNode(imageNamed: "Green") 
    ball.name = "Green" 
    ball.anchorPoint = CGPoint(x: 0.5, y: 0.5) 
    ball.zPosition = 1 
    ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height/
2) 
    ball.physicsBody?.categoryBitMask = ColliderType.Green 
    ball.physicsBody?.affectedByGravity = false 
    ball.physicsBody?.isDynamic = false 

    ball.position.x = -self.size.width + 200 
    ball.position.y = CGFloat.randomBetweenNumbers(firstNum: -637, 
secondNum: 637) 

    self.addChild(ball) 

    let destination = self.frame.height * 2 
    let move = SKAction.moveTo(x: destination, duration: 
TimeInterval(10)) 
    let remove = SKAction.removeFromParent() 

    ball.run(SKAction.sequence([move, remove]), withKey: "MoveGreen") 
} 

func spawnGreenBall() { 

    let spawn = SKAction.run({() -> Void in 
     self.createGreenBall() 
    }) 

    let delay = SKAction.wait(forDuration: TimeInterval(0.5)) 
    let sequence = SKAction.sequence([spawn, delay]) 

    self.run(SKAction.repeatForever(sequence), withKey: "SpawnGreen") 
} 

func createYellowBall() { 
    let ball = SKSpriteNode(imageNamed: "Yellow") 
    ball.name = "Yellow" 
    ball.anchorPoint = CGPoint(x: 0.5, y: 0.5) 
    ball.zPosition = 1 
    ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height/
2) 
    ball.physicsBody?.categoryBitMask = ColliderType.Green 
    ball.physicsBody?.affectedByGravity = false 
    ball.physicsBody?.isDynamic = false 

    ball.position.x = self.size.width + 200 
    ball.position.y = CGFloat.randomBetweenNumbers(firstNum: -637, 
secondNum: 637) 

    self.addChild(ball) 

    let destination = self.frame.height * 2 
    let move = SKAction.moveTo(x: -destination, duration: 
TimeInterval(10)) 
    let remove = SKAction.removeFromParent() 

    ball.run(SKAction.sequence([move, remove]), withKey: "MoveYellow") 
} 

func spawnYellowBall() { 

    let spawn = SKAction.run({() -> Void in 
     self.createYellowBall() 
    }) 

    let delay = SKAction.wait(forDuration: TimeInterval(0.5)) 
    let sequence = SKAction.sequence([spawn, delay]) 

    self.run(SKAction.repeatForever(sequence), withKey: "SpawnYellow") 
} 

func createLabel() { 
    scoreLabel.zPosition = 3 
    scoreLabel.position = CGPoint(x: -320, y: 600) 
    scoreLabel.fontName = "Verdana" 
    scoreLabel.fontSize = 70 
    scoreLabel.text = "0" 
    self.addChild(scoreLabel) 
} 

func incrementScore() { 
    score += 1 
    scoreLabel.text = String(score) 
} 

func playerDied() { 

    counter.invalidate() 

    let highscore = GameManager.instance.getHighscore() 

    if highscore < score { 
     GameManager.instance.setHighscore(highscore: score) 
    } 

    let retry = SKSpriteNode(imageNamed: "Retry") 
    let quit = SKSpriteNode(imageNamed: "Quit") 

    retry.name = "Retry" 
    retry.anchorPoint = CGPoint(x: 0.5, y: 0.5) 
    retry.position = CGPoint(x: -150, y: -50) 
    retry.zPosition = 2 
    retry.setScale(0) 

    quit.name = "Quit" 
    quit.anchorPoint = CGPoint(x: 0.5, y: 0.5) 
    quit.position = CGPoint(x: 150, y: -50) 
    quit.zPosition = 2 
    quit.setScale(0) 

    let scaleUp = SKAction.scale(to: 1, duration: TimeInterval(0.5)) 

    retry.run(scaleUp) 
    quit.run(scaleUp) 

    self.addChild(retry) 
    self.addChild(quit) 

} 

} 
+0

你的問題是什麼? –

+0

你想讓球移動到你觸摸屏幕的任何地方,或者你想實現「拖放」,因此你必須首先觸摸球,然後拖動它? –

+0

當比賽開始時,球在中央。然後玩家將他的手指放在球上,然後拖動它。所以他只能點擊屏幕上的一個位置,球就會到達那裏。不,球沿着手指在屏幕上。因此,例如,當他放開觸摸時,球將保持放置。 – Flinigan

回答

0

下面是一個示例項目,以顯示如何實現可拖動的Sprite:

import SpriteKit 
import GameplayKit 

class GameScene: SKScene { 

var ballIsTouched = false 
var ball = SKSpriteNode() 

override func didMove(to view: SKView) { 
    ball = SKSpriteNode(color: .blue, size: CGSize(width:100, height:100)) 
    ball.position = CGPoint(x: 0, y: 0) 
    addChild(ball) 
} 

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

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

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


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

這隻允許拖動單個指定的精靈。這裏是一個多精靈的例子可以拖動:

import SpriteKit 
import GameplayKit 

extension SKColor { 

static func random() -> SKColor { 
    let colours = [SKColor.lightGray, SKColor.white, SKColor.gray, SKColor.red, SKColor.green, SKColor.blue, SKColor.cyan, SKColor.yellow, SKColor.magenta, SKColor.orange, SKColor.purple, SKColor.brown] 
    return colours[Int(arc4random_uniform(UInt32(colours.count)))] 
} 

} 

class GameScene: SKScene { 

var touchedSprite : SKSpriteNode? 

override func didMove(to view: SKView) { 

    for i in -1...1 { 
    let ball = SKSpriteNode(color: SKColor.random(), size: CGSize(width:100, height:100)) 
    ball.position = CGPoint(x: 0, y: i * 200) 
    addChild(ball) 
    } 
} 

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

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

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { 
       touchedSprite?.setScale(1) 
    touchedSprite = nil 
} 


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

你也可以實現一個draggable協議或東西來限制哪些精靈可以拖動。

+0

這是行不通的 - 你測試觸摸是否在球內,然後移動球,但球不會移動很遠。如果觸摸位於屏幕的另一側,則不會發生任何事情。 –

+0

這就是OP想要的 –

+0

這隻能讓你移動球,如果你碰它 –

0

添加以下屬性:

var ballIsTouched = false 

,然後實現touch方法:

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

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

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

我試過了,但球是靜態的。它根本不動。 :( – Flinigan

+0

@Flinigan。對不起,沒有回覆你。你可以發佈你正在使用的代碼來移動球嗎? –

+0

觸摸(觸摸){ 讓位置= touch.location(in:self)如果玩家有 。包含(位置){ player.position =位置 } } – Flinigan

0

我想實現一個拖動時,從觸摸位置拖動一個精靈,而它更自然比從精靈的中心。要做到這一點,你應該計算偏移量並將它添加到新精靈的位置,如下所示:

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { 

     for touch in touches { 

      let current = touch.location(in: self) 
      let previous = touch.previousLocation(in: self) 

      if ball.contains(current) { 

       let offset = CGPoint(x: current.x - previous.x , y: current.y - previous.y) 
       ball.position = CGPoint(x: ball.position.x + offset.x , y: ball.position.y + offset.y) 
      } 
     } 
    }