我正在制作一个游戏,其中球(玩家)想要避免其他球经过屏幕。基本上我希望球总是跟随触摸的位置。因此,无论我在屏幕上移动手指,都会跟随球。
这是玩家类:
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)
这是一个展示如何实现可拖动精灵的示例项目。:
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)
}
}
}