1

Проблема: У меня, кажется, есть небольшая проблема с попыткой моего игрока столкнуться с монетой и добавлением +1 к монетеLabel при столкновении. Игрок должен продолжать движение после соприкосновения с монетой.Базовые Swift SpriteKit Collisions с использованием PhysicsBodys

То, что у меня есть сейчас: С кодом, который у меня есть сейчас, игрок перемещается по монете, но не происходит столкновения, и +1 не добавляется к метке монеты.

Я все еще изучаю быстрый язык, поэтому я ценю любую помощь, которая дается.

Код:

struct ColliderType { 

static let playerCategory: UInt32 = 0x1 << 0 

static let boundary: UInt32 = 0x1 << 1 
​ 
​static let coinCategory: UInt32 = 0x1 << 2 
​ 
​static let bodyA: UInt32 = 0x1 << 4 
​ 
​static let bodyB: UInt32 = 0x1 << 8 

} 

​override func didMoveToView(view: SKView) { 
​ 
var coinInt = 0 
​ 
​ 
​ 
​self.physicsWorld.gravity = CGVectorMake(0.0, -7.0) 
physicsWorld.contactDelegate = self 

player = SKSpriteNode(imageNamed: "player") 
player.zPosition = 1 
player.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)) 
player.physicsBody = SKPhysicsBody(circleOfRadius: player.size.width/5.12) 
player.physicsBody?.dynamic = true 
player.physicsBody?.allowsRotation = false 

self.addChild(player) 

generateCoins() 

​ 
​ 
coin = SKSpriteNode(imageNamed: "coin") 
coin.physicsBody? = SKPhysicsBody(circleOfRadius: coin.size.height/10) 
coin.physicsBody?.dynamic = false 
coin.physicsBody?.allowsRotation = false 
coin.zPosition = 1 
​self.addChild(coin) 
​ 
player.physicsBody?.categoryBitMask = ColliderType.playerCategory 
​player.physicsBody?.contactTestBitMask = ColliderType.boundary 
player.physicsBody?.collisionBitMask = ColliderType.coinCategory | ColliderType.boundary 

coin.physicsBody?.categoryBitMask = ColliderType.coinCategory 
coin.physicsBody?.contactTestBitMask = ColliderType.playerCategory 
coin.physicsBody?.collisionBitMask = ColliderType.playerCategory 

func didPlayerCollideWithCoin(player: SKSpriteNode, coin: SKSpriteNode) { 



self.coin.removeFromParent() 

self.coin += 1 

coinLabel.text = "\(coinInt)" 

} 

​ 
​  
​ 
​func generateCoins() { 

if(self.actionForKey("spawning") != nil){return} 

let coinTimer = SKAction.waitForDuration(7, withRange: 2) 

let spawnCoin = SKAction.runBlock { 

self.coin = SKSpriteNode(imageNamed: "coin") 

self.coin.physicsBody = SKPhysicsBody(circleOfRadius: self.coin.size.height/10) 

self.coin.name = "coin" 

self.coin.physicsBody?.dynamic = false 

self.coin.physicsBody?.allowsRotation = false 

var coinPosition = Array<CGPoint>() 

coinPosition.append((CGPoint(x:340, y:103))) 

coinPosition.append((CGPoint(x:340, y:148))) 

coinPosition.append((CGPoint(x:340, y:218))) 

coinPosition.append((CGPoint(x: 340, y:343))) 

let spawnLocation =  coinPosition[Int(arc4random_uniform(UInt32(coinPosition.count)))] 

let action = SKAction.repeatActionForever(SKAction.moveToX(+self.xScale, duration: 4.4)) 

self.coin.runAction(action) 

self.coin.position = spawnLocation 

self.addChild(self.coin) 

print(spawnLocation) 

} 

let sequence = SKAction.sequence([coinTimer, spawnCoin]) 

self.runAction(SKAction.repeatActionForever(sequence), withKey: "spawning") 

} 
​​ 
func didBeginContact(contact:SKPhysicsContact) { 

let bodyA: SKPhysicsBody = contact.bodyA 

let bodyB: SKPhysicsBody = contact.bodyB 

if ((bodyA.categoryBitMask == ColliderType.playerCategory) &&  (bodyB.categoryBitMask == ColliderType.coinCategory)){ 

didPlayerCollideWithCoin(bodyA.node as! SKSpriteNode, coin: bodyB.node as! SKSpriteNode) 

} 
    ​   
​} 
+0

Почему '(circleOfRadius: coinOne.size.height/10) 'не должно быть' (circleOfRadius: coinOne.size.height/2) '? –

+0

Я думал, что число, которое приходит после «/», контролирует, насколько велика физика? Например, если вы используете/2 или/3, физическое устройство будет больше по сравнению с использованием большего числа. Я могу ошибаться. –

+0

Радиус (это то, что вам нужно) - диаметр/2. Если высота вашей монеты == диаметр монеты (что она, вероятно, делает), то это значение, деленное на 2, вероятно, дает вам размер, который вам нужен. –

ответ

2

Вы можете попробовать оставить ваши contactTestBitmasks то же самое, но удалить collisionBitmasks между игроком и монеты:

player.physicsBody?.categoryBitMask = ColliderType.playerCategory 
​player.physicsBody?.contactTestBitMask = ColliderType.boundary 
player.physicsBody?.collisionBitMask = ColliderType.boundary 


coin.physicsBody?.categoryBitMask = ColliderType.coinCategory 
coin.physicsBody?.contactTestBitMask = ColliderType.playerCategory 

Таким образом, когда игрок сталкивается с монетой она будет зарегистрируйтесь, но он не будет «отскакивать» и продолжит движение в том же направлении.

* Примечание: Использование этого может потребоваться использовать метод

func didBeginContact(contact: SKPhysicsContact) { 

вместо

func didPlayerCollideWithCoin(player: SKSpriteNode, coin: SKSpriteNode) { 

Но я рекомендую попробовать его с помощью метода didPlayerCollideWithCoin() первым.

В случае, если вам это нужно, это реализовано так:

func didBeginContact(contact: SKPhysicsContact) { 

var firstBody: SKPhysicsBody 
var secondBody: SKPhysicsBody 

if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask { 
    firstBody = contact.bodyA 
    secondBody = contact.bodyB 
} else { 
firstBody = contact.bodyB 
secondBody = contact.bodyA 
} 

if firstBody.categoryBitMask == playerCategory && secondBody.categoryBitMask == coinCategory { 
print("Your player passes through the coin") 
score = score + 1 
} 
} 

Для получения более подробной информации см этот учебник от Ray Wenderlich: https://www.raywenderlich.com/123393/how-to-create-a-breakout-game-with-sprite-kit-and-swift

+0

Привет, hb22, спасибо за ваш ответ! Я отредактировал свой код, чтобы он соответствовал тому, что вы написали в своем ответе (сначала попробовал его с didPlayerCollideWithCoin, затем попробовал didBeginContact), но ничего не изменилось. Поэтому я использовал 'view.showsPhysics = true', чтобы проверить физикуBodys, и я заметил, что физическое устройство игрока видимо, но физическое устройство для монеты, похоже, не появляется, хотя у меня есть монетоприемник, настроенный с физикой. ' своя. Я думаю, что это может быть проблемой, препятствующей столкновению работать должным образом. –