我创建了一个SKSpriteNode对象,但是创建了多个对象,它们以字符串的形式出现。来自SKAudioNode对象的声音也会被复制很多次,以产生回响效果。
这是下面的代码。当我添加代码以在didBegin回调方法中将PhysicsBody对象的固定属性设置为true时,我注意到它这样做。
这是屏幕截图。请注意,有多个爆炸SKSpriteNode对象。我只为爆炸创建了一个SKSpriteNode对象。
我怀疑可以更改某个设置以禁用此效果。
import UIKit
import SpriteKit
class GameScene: SKScene {
let player = SKSpriteNode(imageNamed: "player")
var moveRate: CGFloat!
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self
if UIDevice.current.userInterfaceIdiom == .phone {
moveRate = 5
} else {
moveRate = 15
}
player.physicsBody = SKPhysicsBody(rectangleOf: player.size)
player.physicsBody?.isDynamic = true
player.physicsBody?.affectedByGravity = false
player.physicsBody?.categoryBitMask = 0b00001
// player.physicsBody?.collisionBitMask = 0b00001
player.physicsBody?.contactTestBitMask = 0b00001
player.position = CGPoint(x: 20 + player.size.width/2, y: view.frame.height / 2)
addChild(player)
let carEngineStart = SKAudioNode(fileNamed: "car_engine_running")
addChild(carEngineStart)
run(SKAction.repeatForever(
SKAction.sequence([
SKAction.run(addCompetitor),
SKAction.wait(forDuration: 4)
])
))
}
override func update(_ currentTime: TimeInterval) {
let internalRollSign = TrialSpriteKit.sign(internalRoll)
switch internalRollSign {
case .zero:
break
case .positive:
if player.position.y < self.size.height {
player.position.y += moveRate
}
case .negative:
if player.position.y > 0 {
player.position.y -= moveRate
}
}
}
enum Car: String, CaseIterable {
case blue = "blue"
case green = "green"
case orange = "orange"
case purple = "purple"
case utili = "utili"
case white = "white"
case yellow = "yellow"
static func random<G: RandomNumberGenerator>(using generator: inout G) -> Car {
return Car.allCases.randomElement(using: &generator)!
}
static func random() -> Car {
var g = SystemRandomNumberGenerator()
return Car.random(using: &g)
}
}
func random() -> CGFloat {
return CGFloat(Float(arc4random()) / /* 0xFFFFFFFF */ 4294967296)
}
func random(min: CGFloat, max: CGFloat) -> CGFloat {
return random() * (max - min) + min
}
func addCompetitor() {
// Create sprite
let carString = Car.random().rawValue
let car = SKSpriteNode(imageNamed: carString)
car.physicsBody = SKPhysicsBody(rectangleOf: car.size) // 1
car.physicsBody?.isDynamic = true
car.physicsBody?.affectedByGravity = false
// car.physicsBody?.categoryBitMask = 0b00001
car.physicsBody?.collisionBitMask = 0b00001
car.physicsBody?.contactTestBitMask = 0b00001
// Determine where to spawn the car along the Y axis
let actualY = random(min: car.size.height/2, max: size.height - car.size.height/2)
// Position the car slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated above
car.position = CGPoint(x: size.width + car.size.width/2, y: actualY)
// Add the car to the scene
addChild(car)
// Determine speed of the car
let actualDuration = random(min: CGFloat(2.0), max: CGFloat(4.0))
// Create the actions
let actionMove = SKAction.move(to: CGPoint(x: -car.size.width/2, y: actualY), duration: TimeInterval(actualDuration))
let actionMoveDone = SKAction.removeFromParent()
car.run(SKAction.sequence([actionMove, actionMoveDone]))
}
}
extension GameScene: SKPhysicsContactDelegate {
func didBegin(_ contact: SKPhysicsContact) {
contact.bodyA.pinned = true
player.physicsBody?.pinned = true
let explosion = SKSpriteNode(imageNamed: "explosion")
explosion.position = contact.contactPoint
addChild(explosion)
run(
SKAction.sequence(
[
SKAction.playSoundFileNamed("car_explosion", waitForCompletion: true),
SKAction.run({
explosion.removeFromParent()
contact.bodyB.node?.removeFromParent()
}),
SKAction.wait(forDuration: 1),
SKAction.run({
self.player.zRotation = 0
self.player.position = CGPoint(x: 20 + self.player.size.width/2, y: self.view!.frame.height / 2)
self.player.physicsBody?.pinned = false
})
]
)
)
}
}
答案 0 :(得分:1)
您有问题中包含多个节点的原因。
当我添加代码以设置固定时,我注意到它正在执行此操作 在didBegin回调中将PhysicsBody对象的属性设置为true 方法。
根据SpriteKit文档,当您将pinned
属性设置为true并且父节点具有物理实体时,将这两个实体视为通过销钉连接。
由于两个主体已连接,即使没有碰撞也要反复进行接触,从而导致对didBegin
函数的反复调用。每次对didBegin
的调用都会创建一个新的sprite节点。游戏调用didBegin
的次数比您预期的次数多,因此最终导致的sprite节点数超出预期。
一般的解决方案是仅在发生碰撞时创建爆炸精灵节点,并且每次碰撞仅创建一次精灵节点。