ios - 如何在 Swift、Sprite 套件中检测碰撞
问题描述
我一直在用 Swift 编写这个简单的太空游戏,直到遇到检测碰撞的问题。在浏览了论坛、教程等之后,我尝试通过像这样声明位掩码来实现冲突:
对象 1
enemy?.physicsBody = SKPhysicsBody(circleOfRadius: ((enemy?.size.width)!/2))
enemy?.physicsBody?.categoryBitMask = enemyBitMask
enemy?.physicsBody?.contactTestBitMask = bulletBitMask
enemy?.physicsBody?.collisionBitMask = 0
对象 2
bullet?.physicsBody? = SKPhysicsBody(rectangleOf: (bullet?.size)!)
bullet?.physicsBody?.categoryBitMask = bulletBitMask
bullet?.physicsBody?.contactTestBitMask = enemyBitMask
bullet?.physicsBody?.collisionBitMask = 0
bullet?.physicsBody?.usesPreciseCollisionDetection = true
我还在
func didBegin(_ contact: SKPhysicsContact) { print("Hello") }
这是我配置精灵的方式:
func CreateNewEnemy() {
var enemy : SKSpriteNode?
let moveEnemyDown = SKAction.repeatForever(SKAction.moveBy(x: 0, y: -1, duration: 0.01))
let rotateEnemy = SKAction.repeatForever(SKAction.rotate(byAngle: 25, duration: 5))
let enemyXpos = randomNum(high: self.frame.size.width/2, low: -1 * self.frame.size.width/2)
let enemyYpos = randomNum(high: 2.5*self.frame.size.height, low: self.frame.size.height/2)
let enemyOrigin : CGPoint = CGPoint(x: enemyXpos, y: enemyYpos)
enemy = SKSpriteNode(imageNamed: possibleEnemyImage[Int(arc4random_uniform(4))])
print(enemy?.size.height)
enemy?.scale(to: CGSize(width: player.size.height, height: player.size.height))
print(enemy?.size.height)
enemy?.position = enemyOrigin
enemy?.run(moveEnemyDown)
enemy?.run(rotateEnemy)
let enemyRadius : CGFloat = (enemy?.size.width)!/2
print(enemyRadius)
enemy?.physicsBody? = SKPhysicsBody(circleOfRadius: enemyRadius)
enemy?.physicsBody?.categoryBitMask = enemyCategory
enemy?.physicsBody?.contactTestBitMask = bulletCategory
enemy?.physicsBody?.collisionBitMask = 0
enemy?.zPosition = 1
enemiesArray.append(enemy!)
self.addChild(enemy!)
}
创建敌人(调用确实移动到查看功能)
func CreateAllEnemies(amountOfEnemies : UInt8) {
for _ in 0...amountOfEnemies {
CreateNewEnemy()
}
}
和另一个精灵
func CreateNewBullet() {
let bulletOrigin : CGPoint = CGPoint(x: player.position.x, y: player.position.y+player.size.height/2)
let moveBulletUp = SKAction.repeatForever(SKAction.moveBy(x: 0, y: 3, duration: 0.01))
var bullet : SKSpriteNode?
bullet = SKSpriteNode(imageNamed: "bulletImage")
bullet?.position = bulletOrigin
bullet?.run(moveBulletUp)
bullet?.physicsBody? = SKPhysicsBody(rectangleOf: (bullet?.size)!)
bullet?.physicsBody?.categoryBitMask = bulletCategory
bullet?.physicsBody?.contactTestBitMask = enemyCategory
bullet?.physicsBody?.collisionBitMask = 0
bullet?.physicsBody?.isDynamic = true
bullet?.physicsBody?.usesPreciseCollisionDetection = true
bullet?.zPosition = 1
bulletsArray.append(bullet!)
self.addChild(bullet!)
}
这个是用计时器创建的
bulletTimer = Timer.scheduledTimer(timeInterval: 0.25, target: self, selector: #selector(CreateNewBullet) , userInfo: nil, repeats: true)
不幸的是,在我看到两个对象接触后,它不会在控制台中打印任何内容。
解决方案
- 定义独特的类别,确保您的课程是一个
SKPhysicsContactDelegate
并让自己成为物理联系人代表:
//Physics categories
let enemyCategory: UInt32 = 1 << 1
let bulletCategory: UInt32 = 1 << 2
class GameScene: SKScene, SKPhysicsContactDelegate {
physicsWorld.contactDelegate = self
分配类别(通常在
didMove(to view:)
:enemy.physicsBody.catgeoryBitMask = enemyCategory bullet.physicsBody.catgeoryBitMask = bulletCategory
(确保您已经为每个节点创建了物理实体)
- 设置碰撞:
enemy.physicsBody?.collisionBitMask = 0 // enemy collides with nothing
bullet.physicsBody?.collisionBitMask = 0 // bullet collides with nothing
甚至:
for node in [enemy, bullet] {
node.physicsBody?.collisionBitMask = 0 // collides with nothing
}
设置联系人
bullet.physicsBody?.collisionBitMask = enemyCategory // bullet contacts enemy
确保每个潜在接触中涉及的至少一个对象将isDynamic
其物理体上的属性设置为true
,否则将不会生成任何接触。两个对象不必都是动态的。
你现在应该didBegin
在子弹和敌人接触时被召唤。你可以这样编码didBegin
:
func didBegin(_ contact: SKPhysicsContact) {
print("didBeginContact entered for \(String(describing: contact.bodyA.node!.name)) and \(String(describing: contact.bodyB.node!.name))")
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case bulletCategory | enemyCategory:
print("bullet and enemy have contacted.")
let bulletNode = contact.bodyA.categoryBitMask == bulletCategory ? contact.bodyA.node : contact.bodyB.node
enemyHealth -= 10
bulletNode.removeFromParent
default:
print("Some other contact occurred")
}
}
推荐阅读
- spring - Spring如何在没有spring security的情况下维护登录用户
- c - time_t 和 LONG_MAX:ctime() 和 difftime() 的问题
- python - Pandas 使用四分位数删除带有 Groupby 两列的行
- javascript - 数组未在 javascript 中作为参数传递。(类型错误:无法读取未定义的属性“长度”)
- angular - 如何将材质输入与嵌套的 FormControl 绑定?
- symfony - 将 sylius 商店域从基于区域设置更改为基于国家代码
- android - 颤振:按下手机返回按钮时,如何关闭键盘和页面
- javascript - 如何在 nextjs getStaticprops 或 getServerSideProps 中使用 dispatch
- typo3-9.x - TYPO3 tx_news 不存在新闻的错误处理
- awk - awk 多个模式匹配并将输出格式化为输入文件中的列