Sprite Kit 中的碰撞检测 Swift
Collision Detection In Sprite Kit Swift
这是我第一次在 iOS 制作游戏,所以自然而然地遇到了一些问题。我已经设法解决了它们,但现在涉及到马里奥和管道之间的碰撞部分,我遇到了一些麻烦:
我想做什么:
当马里奥撞到管道时,他必须跳过它们才能到达另一边。如果他不这样做,那么管道将继续 'push' 他到游戏结束的屏幕边缘。
实际发生了什么:
没有检测到任何碰撞。
下面是代码:
import SpriteKit
import GameplayKit
class GameScene: SKScene, SKPhysicsContactDelegate {
var mario = SKSpriteNode()
enum ColliderType: UInt32 {
case Mario = 1
case Object = 2
}
func addPipes() {
let pipetexture = SKTexture(imageNamed: "pipes")
let pipes = SKSpriteNode(texture: pipetexture)
let setScale = CGFloat(arc4random_uniform(19) + 15)
pipes.setScale(setScale) //min 15, max 19
pipes.position = CGPoint(x: self.frame.maxX, y: self.frame.minY)
let movePipes = SKAction.move(by: CGVector(dx: -5 * self.frame.width, dy: 0), duration: TimeInterval(self.frame.width/100))
let removePipes = SKAction.removeFromParent()
let moveAndRemovePipes = SKAction.sequence([movePipes, removePipes])
pipes.zPosition = +1
pipes.physicsBody = SKPhysicsBody(rectangleOf: pipes.size)
pipes.physicsBody!.isDynamic = false
pipes.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
pipes.physicsBody!.categoryBitMask = ColliderType.Object.rawValue
pipes.physicsBody!.collisionBitMask = ColliderType.Mario.rawValue
self.addChild(pipes)
pipes.run(moveAndRemovePipes)
}
func didBegin(_ contact: SKPhysicsContact) {
print("contact")
}
override func didMove(to view: SKView) {
self.physicsWorld.contactDelegate = self
_ = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(self.addPipes), userInfo: nil, repeats: true)
let marioTexture = SKTexture(imageNamed: "mariorun0.png")
let marioTexture2 = SKTexture(imageNamed: "mariorun1.png")
let marioTexture3 = SKTexture(imageNamed: "mariorun2.png")
let animation = SKAction.animate(with: [marioTexture, marioTexture2, marioTexture3], timePerFrame: 0.1)
let makeMarioRun = SKAction.repeatForever(animation)
mario = SKSpriteNode(texture: marioTexture)
mario.setScale(10)
mario.position = CGPoint(x: -(self.frame.size.width/3.5), y: -(self.frame.size.height/2.8))
mario.run(makeMarioRun)
mario.physicsBody = SKPhysicsBody(rectangleOf: mario.size)
mario.physicsBody!.isDynamic = false
mario.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
mario.physicsBody!.categoryBitMask = ColliderType.Mario.rawValue
mario.physicsBody!.collisionBitMask = ColliderType.Object.rawValue
self.addChild(mario)
addPipes()
mario.zPosition = +2
}
}
我还实现了一个完美运行的跳转功能。我的问题是我无法在管道和马里奥之间进行碰撞检测。
我试过将两个精灵的 z 位置设置为相同的值,但没有成功。
我最初担心的是图像太小,因此几乎不可能检测到碰撞。但是由于我正在放大两个节点并使用放大图像的物理体,所以不会有问题,但这也无济于事。
提前感谢您的帮助。
physicsBody!.isDynamic = false
意味着这个body不会发生物理activity。其他物体可以与它交互,但它不会与任何东西交互。
这对于管道来说是有意义的,因为管道永远不会移动,所以没有理由是动态的。 (你的世界应该在移动,而不是管道,如果你正在做一个 flappy bird-esc 游戏)
现在对于马里奥来说,这没有意义。马里奥是一个移动的实体,所以他会与周围的物理世界互动。要解决你的问题,你需要让他动态 mario.physicsBody!.isDynamic = true
这是我第一次在 iOS 制作游戏,所以自然而然地遇到了一些问题。我已经设法解决了它们,但现在涉及到马里奥和管道之间的碰撞部分,我遇到了一些麻烦:
我想做什么:
当马里奥撞到管道时,他必须跳过它们才能到达另一边。如果他不这样做,那么管道将继续 'push' 他到游戏结束的屏幕边缘。
实际发生了什么:
没有检测到任何碰撞。
下面是代码:
import SpriteKit
import GameplayKit
class GameScene: SKScene, SKPhysicsContactDelegate {
var mario = SKSpriteNode()
enum ColliderType: UInt32 {
case Mario = 1
case Object = 2
}
func addPipes() {
let pipetexture = SKTexture(imageNamed: "pipes")
let pipes = SKSpriteNode(texture: pipetexture)
let setScale = CGFloat(arc4random_uniform(19) + 15)
pipes.setScale(setScale) //min 15, max 19
pipes.position = CGPoint(x: self.frame.maxX, y: self.frame.minY)
let movePipes = SKAction.move(by: CGVector(dx: -5 * self.frame.width, dy: 0), duration: TimeInterval(self.frame.width/100))
let removePipes = SKAction.removeFromParent()
let moveAndRemovePipes = SKAction.sequence([movePipes, removePipes])
pipes.zPosition = +1
pipes.physicsBody = SKPhysicsBody(rectangleOf: pipes.size)
pipes.physicsBody!.isDynamic = false
pipes.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
pipes.physicsBody!.categoryBitMask = ColliderType.Object.rawValue
pipes.physicsBody!.collisionBitMask = ColliderType.Mario.rawValue
self.addChild(pipes)
pipes.run(moveAndRemovePipes)
}
func didBegin(_ contact: SKPhysicsContact) {
print("contact")
}
override func didMove(to view: SKView) {
self.physicsWorld.contactDelegate = self
_ = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(self.addPipes), userInfo: nil, repeats: true)
let marioTexture = SKTexture(imageNamed: "mariorun0.png")
let marioTexture2 = SKTexture(imageNamed: "mariorun1.png")
let marioTexture3 = SKTexture(imageNamed: "mariorun2.png")
let animation = SKAction.animate(with: [marioTexture, marioTexture2, marioTexture3], timePerFrame: 0.1)
let makeMarioRun = SKAction.repeatForever(animation)
mario = SKSpriteNode(texture: marioTexture)
mario.setScale(10)
mario.position = CGPoint(x: -(self.frame.size.width/3.5), y: -(self.frame.size.height/2.8))
mario.run(makeMarioRun)
mario.physicsBody = SKPhysicsBody(rectangleOf: mario.size)
mario.physicsBody!.isDynamic = false
mario.physicsBody!.contactTestBitMask = ColliderType.Object.rawValue
mario.physicsBody!.categoryBitMask = ColliderType.Mario.rawValue
mario.physicsBody!.collisionBitMask = ColliderType.Object.rawValue
self.addChild(mario)
addPipes()
mario.zPosition = +2
}
}
我还实现了一个完美运行的跳转功能。我的问题是我无法在管道和马里奥之间进行碰撞检测。
我试过将两个精灵的 z 位置设置为相同的值,但没有成功。
我最初担心的是图像太小,因此几乎不可能检测到碰撞。但是由于我正在放大两个节点并使用放大图像的物理体,所以不会有问题,但这也无济于事。
提前感谢您的帮助。
physicsBody!.isDynamic = false
意味着这个body不会发生物理activity。其他物体可以与它交互,但它不会与任何东西交互。
这对于管道来说是有意义的,因为管道永远不会移动,所以没有理由是动态的。 (你的世界应该在移动,而不是管道,如果你正在做一个 flappy bird-esc 游戏)
现在对于马里奥来说,这没有意义。马里奥是一个移动的实体,所以他会与周围的物理世界互动。要解决你的问题,你需要让他动态 mario.physicsBody!.isDynamic = true