在整个屏幕上自由移动播放器

时间:2017-07-02 20:47:05

标签: ios swift sprite-kit

我正在制作一个游戏,其中球(玩家)想要避免其他球经过屏幕。基本上我希望球总是跟随触摸的位置。因此,无论我在屏幕上移动手指,都会跟随球。

这是玩家类:

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)

}

}

3 个答案:

答案 0 :(得分:0)

这是一个展示如何实现可拖动精灵的示例项目。:

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协议或某些内容来限制可以拖动哪些精灵。

答案 1 :(得分: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
}

答案 2 :(得分: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)
            }
        }
    }