节点过早地从场景中移除(Swift 游戏)
Node prematurely removed from scene (Swift game)
我在 Swift 中有以下代码用于一个简单的平台游戏:
import SpriteKit
import GameplayKit
class GameScene: SKScene, SKPhysicsContactDelegate {
var me : SKSpriteNode?
var ceiling : SKSpriteNode?
var studentTimer : Timer?
var cloudTimer : Timer?
let meCategory : UInt32 = 0x1 << 1
let studentCategory : UInt32 = 0x1 << 2
let cloudCategory : UInt32 = 0x1 << 3
let groundAndCeilingCategory : UInt32 = 0x1 << 4
var numberofStudents = 0
var education = ["edu1", "edu2", "edu3", "edu4"]
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self
me = childNode(withName: "me") as? SKSpriteNode
me?.physicsBody?.categoryBitMask = meCategory
me?.physicsBody?.contactTestBitMask = studentCategory
me?.physicsBody?.collisionBitMask = groundAndCeilingCategory
// make me run
var meRun : [SKTexture] = []
for number in 1...6 {
meRun.append(SKTexture(imageNamed: "Armature_Run_\(number)"))
}
me?.run(SKAction.repeatForever(SKAction.animate(with: meRun, timePerFrame: 0.1)))
ceiling = childNode(withName: "ceiling") as? SKSpriteNode
ceiling?.physicsBody?.categoryBitMask = groundAndCeilingCategory
ceiling?.physicsBody?.collisionBitMask = meCategory
startTimers()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
me?.physicsBody?.applyForce(CGVector(dx: 0, dy: 20000))
var meJump : [SKTexture] = []
for number in 0...9 {
meJump.append(SKTexture(imageNamed: "Armature_Jump_0\(number)"))
}
me?.run(SKAction.animate(with: meJump, timePerFrame: 0.1))
}
func createStudent() {
let student = SKSpriteNode(imageNamed: "student")
student.physicsBody = SKPhysicsBody(rectangleOf: student.size)
student.physicsBody?.affectedByGravity = false
student.physicsBody?.categoryBitMask = studentCategory
student.physicsBody?.contactTestBitMask = meCategory
student.physicsBody?.collisionBitMask = 0
addChild(student)
student.position = CGPoint(x: size.width / 2 + student.size.width, y: (-size.height / 2) + ((student.size.height)*2))
let moveLeft = SKAction.moveBy(x: -size.width - student.size.width, y: 0, duration: 4)
student.run(SKAction.sequence([moveLeft, SKAction.removeFromParent()]))
}
func startTimers() {
studentTimer = Timer.scheduledTimer(withTimeInterval: 4, repeats: true, block: { (timer) in
if self.numberofStudents < 4 {
self.createStudent()
}
})
cloudTimer = Timer.scheduledTimer(withTimeInterval: 2, repeats: true, block: { (timer) in
self.createCloud()
})
}
func createCloud() {
let cloud = SKSpriteNode(imageNamed: "cloud")
cloud.zPosition = -1
cloud.physicsBody = SKPhysicsBody(rectangleOf: cloud.size)
cloud.physicsBody?.affectedByGravity = false
cloud.physicsBody?.collisionBitMask = 0
cloud.physicsBody?.categoryBitMask = cloudCategory
addChild(cloud)
let maxY = size.height / 2 - cloud.size.height / 2
let minY = CGFloat(0)
let range = maxY - minY
let cloudY = maxY - CGFloat(arc4random_uniform(UInt32(range)))
cloud.position = CGPoint(x: size.width / 2 + cloud.size.width / 2, y: cloudY)
let moveLeft = SKAction.moveBy(x: -size.width - cloud.size.width, y: 0, duration: 4)
cloud.run(SKAction.sequence([moveLeft, SKAction.removeFromParent()]))
}
func didBegin(_ contact: SKPhysicsContact) {
if contact.bodyA.categoryBitMask == studentCategory {
contact.bodyA.node?.removeFromParent()
numberofStudents += 1
print(numberofStudents)
print(education[(numberofStudents)-1])
}
if contact.bodyB.categoryBitMask == studentCategory {
contact.bodyB.node?.removeFromParent()
numberofStudents += 1
print(numberofStudents)
print(education[(numberofStudents)-1])
}
}
}
我正在研究当主角 ("me") 与 "student" 相撞时会发生什么。
在添加 'physicsWorld.contactDelegate = self' 之前,"student" 完美显示,在屏幕上移动。但是,当我添加这行代码和 运行 应用程序时,学生是不可见的。我相信它仍然存在于某个地方,因为当角色发生碰撞时,打印公用语仍然是 运行ning,但它并没有明显地与任何东西发生碰撞。
我删除了 contact.bodyB.node?.removeFromParent() 和 运行 它,确实 "student" 确实再次显示,但显然不会在联系时消失。
我已经研究了很久,确信我遗漏了一些明显的东西,但无法弄清楚它是什么。
您没有向我们提供所有信息。
因为您的代码按预期工作。
这是您的代码的视频 运行(我必须使用自己的图片)
下面是我对可能错误的分析。
我删除了所有动画序列项目,因为它们与此无关。
我注意到你没有放置 zPositions...tsk tsk tsk。所有项目都应该有一个 zPosition。
您没有向我们展示如何在 "me" 精灵上定义 physicsBody。大概在编辑器里?下次你应该包括那个信息。
我必须创建 "me" 字符并将其放置在代码中,因为您没有向我们展示它的来源。我还在代码中创建了 physicsBody 以使其工作。
这是我使用的代码
me = SKSpriteNode(imageNamed: "orange")
me.position = CGPoint(x: -400, y: (-size.height / 2) + ((me.size.height) * 2))
me.zPosition = 10
addChild(me)
me.physicsBody = SKPhysicsBody(rectangleOf: me.size)
me.physicsBody?.categoryBitMask = meCategory
me.physicsBody?.contactTestBitMask = studentCategory
me.physicsBody?.collisionBitMask = groundAndCeilingCategory
me.physicsBody?.affectedByGravity = false
func createStudent() {
let student = SKSpriteNode(imageNamed: "apple")
student.setScale(0.5)
student.position = CGPoint(x: size.width / 2 + student.size.width, y: (-size.height / 2) + ((student.size.height) * 2))
student.zPosition = 10
addChild(student)
student.physicsBody = SKPhysicsBody(rectangleOf: student.size)
student.physicsBody?.affectedByGravity = false
student.physicsBody?.categoryBitMask = studentCategory
student.physicsBody?.contactTestBitMask = meCategory
student.physicsBody?.collisionBitMask = 0
let moveLeft = SKAction.moveBy(x: -size.width - student.size.width, y: 0, duration: 4)
student.run(SKAction.sequence([moveLeft, SKAction.removeFromParent()]))
}
附带说明一下,没有必要使用计时器。 SpriteKit 有一个内置功能 "update" func.
我在 Swift 中有以下代码用于一个简单的平台游戏:
import SpriteKit
import GameplayKit
class GameScene: SKScene, SKPhysicsContactDelegate {
var me : SKSpriteNode?
var ceiling : SKSpriteNode?
var studentTimer : Timer?
var cloudTimer : Timer?
let meCategory : UInt32 = 0x1 << 1
let studentCategory : UInt32 = 0x1 << 2
let cloudCategory : UInt32 = 0x1 << 3
let groundAndCeilingCategory : UInt32 = 0x1 << 4
var numberofStudents = 0
var education = ["edu1", "edu2", "edu3", "edu4"]
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self
me = childNode(withName: "me") as? SKSpriteNode
me?.physicsBody?.categoryBitMask = meCategory
me?.physicsBody?.contactTestBitMask = studentCategory
me?.physicsBody?.collisionBitMask = groundAndCeilingCategory
// make me run
var meRun : [SKTexture] = []
for number in 1...6 {
meRun.append(SKTexture(imageNamed: "Armature_Run_\(number)"))
}
me?.run(SKAction.repeatForever(SKAction.animate(with: meRun, timePerFrame: 0.1)))
ceiling = childNode(withName: "ceiling") as? SKSpriteNode
ceiling?.physicsBody?.categoryBitMask = groundAndCeilingCategory
ceiling?.physicsBody?.collisionBitMask = meCategory
startTimers()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
me?.physicsBody?.applyForce(CGVector(dx: 0, dy: 20000))
var meJump : [SKTexture] = []
for number in 0...9 {
meJump.append(SKTexture(imageNamed: "Armature_Jump_0\(number)"))
}
me?.run(SKAction.animate(with: meJump, timePerFrame: 0.1))
}
func createStudent() {
let student = SKSpriteNode(imageNamed: "student")
student.physicsBody = SKPhysicsBody(rectangleOf: student.size)
student.physicsBody?.affectedByGravity = false
student.physicsBody?.categoryBitMask = studentCategory
student.physicsBody?.contactTestBitMask = meCategory
student.physicsBody?.collisionBitMask = 0
addChild(student)
student.position = CGPoint(x: size.width / 2 + student.size.width, y: (-size.height / 2) + ((student.size.height)*2))
let moveLeft = SKAction.moveBy(x: -size.width - student.size.width, y: 0, duration: 4)
student.run(SKAction.sequence([moveLeft, SKAction.removeFromParent()]))
}
func startTimers() {
studentTimer = Timer.scheduledTimer(withTimeInterval: 4, repeats: true, block: { (timer) in
if self.numberofStudents < 4 {
self.createStudent()
}
})
cloudTimer = Timer.scheduledTimer(withTimeInterval: 2, repeats: true, block: { (timer) in
self.createCloud()
})
}
func createCloud() {
let cloud = SKSpriteNode(imageNamed: "cloud")
cloud.zPosition = -1
cloud.physicsBody = SKPhysicsBody(rectangleOf: cloud.size)
cloud.physicsBody?.affectedByGravity = false
cloud.physicsBody?.collisionBitMask = 0
cloud.physicsBody?.categoryBitMask = cloudCategory
addChild(cloud)
let maxY = size.height / 2 - cloud.size.height / 2
let minY = CGFloat(0)
let range = maxY - minY
let cloudY = maxY - CGFloat(arc4random_uniform(UInt32(range)))
cloud.position = CGPoint(x: size.width / 2 + cloud.size.width / 2, y: cloudY)
let moveLeft = SKAction.moveBy(x: -size.width - cloud.size.width, y: 0, duration: 4)
cloud.run(SKAction.sequence([moveLeft, SKAction.removeFromParent()]))
}
func didBegin(_ contact: SKPhysicsContact) {
if contact.bodyA.categoryBitMask == studentCategory {
contact.bodyA.node?.removeFromParent()
numberofStudents += 1
print(numberofStudents)
print(education[(numberofStudents)-1])
}
if contact.bodyB.categoryBitMask == studentCategory {
contact.bodyB.node?.removeFromParent()
numberofStudents += 1
print(numberofStudents)
print(education[(numberofStudents)-1])
}
}
}
我正在研究当主角 ("me") 与 "student" 相撞时会发生什么。
在添加 'physicsWorld.contactDelegate = self' 之前,"student" 完美显示,在屏幕上移动。但是,当我添加这行代码和 运行 应用程序时,学生是不可见的。我相信它仍然存在于某个地方,因为当角色发生碰撞时,打印公用语仍然是 运行ning,但它并没有明显地与任何东西发生碰撞。
我删除了 contact.bodyB.node?.removeFromParent() 和 运行 它,确实 "student" 确实再次显示,但显然不会在联系时消失。
我已经研究了很久,确信我遗漏了一些明显的东西,但无法弄清楚它是什么。
您没有向我们提供所有信息。
因为您的代码按预期工作。
这是您的代码的视频 运行(我必须使用自己的图片)
下面是我对可能错误的分析。
我删除了所有动画序列项目,因为它们与此无关。
我注意到你没有放置 zPositions...tsk tsk tsk。所有项目都应该有一个 zPosition。
您没有向我们展示如何在 "me" 精灵上定义 physicsBody。大概在编辑器里?下次你应该包括那个信息。
我必须创建 "me" 字符并将其放置在代码中,因为您没有向我们展示它的来源。我还在代码中创建了 physicsBody 以使其工作。
这是我使用的代码
me = SKSpriteNode(imageNamed: "orange")
me.position = CGPoint(x: -400, y: (-size.height / 2) + ((me.size.height) * 2))
me.zPosition = 10
addChild(me)
me.physicsBody = SKPhysicsBody(rectangleOf: me.size)
me.physicsBody?.categoryBitMask = meCategory
me.physicsBody?.contactTestBitMask = studentCategory
me.physicsBody?.collisionBitMask = groundAndCeilingCategory
me.physicsBody?.affectedByGravity = false
func createStudent() {
let student = SKSpriteNode(imageNamed: "apple")
student.setScale(0.5)
student.position = CGPoint(x: size.width / 2 + student.size.width, y: (-size.height / 2) + ((student.size.height) * 2))
student.zPosition = 10
addChild(student)
student.physicsBody = SKPhysicsBody(rectangleOf: student.size)
student.physicsBody?.affectedByGravity = false
student.physicsBody?.categoryBitMask = studentCategory
student.physicsBody?.contactTestBitMask = meCategory
student.physicsBody?.collisionBitMask = 0
let moveLeft = SKAction.moveBy(x: -size.width - student.size.width, y: 0, duration: 4)
student.run(SKAction.sequence([moveLeft, SKAction.removeFromParent()]))
}
附带说明一下,没有必要使用计时器。 SpriteKit 有一个内置功能 "update" func.