我正在研究太空侵略者"游戏中,我已经实现了CMMotionManager来倾斜移动我的heroShip(游戏只在横向上运行),但由于某种原因我的船将移出视图,即使
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
应该通过创造物理优势来防止这种情况发生。有什么想法吗?
import SpriteKit
import CoreMotion
class GameScene: SKScene,SKPhysicsContactDelegate{
let collisionBulletCategory: UInt32 = 0x1 << 0
let collisionHeroCategory: UInt32 = 0x1 << 1
let background = SKSpriteNode(imageNamed: "background")
let heroShip = SKSpriteNode(imageNamed: "heroShip")
let enemyShip = SKSpriteNode(imageNamed: "enemyShip")
let MotionManager = CMMotionManager()
override func didMoveToView(view: SKView) {
/* Setup your scene here */
self.physicsWorld.contactDelegate = self
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
background.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame))
heroShip.anchorPoint = CGPointMake(1.0, 0.5)
heroShip.physicsBody?.mass = 0.02
heroShip.physicsBody?.dynamic = true
heroShip.physicsBody = SKPhysicsBody(rectangleOfSize: heroShip.size)
heroShip.physicsBody?.affectedByGravity = false
heroShip.physicsBody?.categoryBitMask = collisionHeroCategory
heroShip.physicsBody?.contactTestBitMask = collisionBulletCategory
heroShip.physicsBody?.collisionBitMask = 0x0
heroShip.position = CGPointMake(self.size.width/6.0, self.size.height/2.0)
enemyShip.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
enemyShip.zPosition = 1.0
self.heroShip.zPosition = 1.0
self.addChild(enemyShip)
self.addChild(background)
self.addChild(heroShip)
if MotionManager.accelerometerAvailable{
MotionManager.startAccelerometerUpdates()
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let bullet = SKSpriteNode(imageNamed: "bullet")
bullet.position = CGPointMake(heroShip.position.x, heroShip.position.y)
bullet.zPosition = 1.0
// Add physics body for collision detection
bullet.physicsBody = SKPhysicsBody(rectangleOfSize: bullet.frame.size)
bullet.physicsBody?.dynamic = true
bullet.physicsBody?.affectedByGravity = false
bullet.physicsBody?.categoryBitMask = collisionBulletCategory
bullet.physicsBody?.contactTestBitMask = collisionHeroCategory
bullet.physicsBody?.collisionBitMask = 0x0;
let action = SKAction.moveToX(CGRectGetMaxX(self.frame) + bullet.size.width, duration: 0.75)
self.addChild(bullet)
bullet.runAction(action, completion: {
bullet.removeAllActions()
bullet.removeFromParent()
})
}
func didBeginContact(contact: SKPhysicsContact) {
}
override func update(currentTime: CFTimeInterval) {
let data = MotionManager.accelerometerData
if data?.acceleration.x == nil{
print("nil")
}
else if fabs((data?.acceleration.x)!) > 0.2 {
self.heroShip.physicsBody?.applyForce(CGVectorMake(0.0, CGFloat(50 * (data?.acceleration.x)!)))
}
}
}
答案 0 :(得分:4)
根据文档,这就是碰撞的发生方式:
当两个物理实体相互接触时,可能会发生碰撞。 该身体的碰撞面具与其他身体的类别进行比较 通过执行逻辑AND操作进行掩码。如果结果是非零 值,这个身体受到碰撞的影响。每个身体独立 选择是否想要受到其他身体的影响。对于 例如,您可以使用它来避免碰撞计算 对身体的速度做出微不足道的改变。
您已将播放器的collisionBitMask设置为0x00000000
(所有位已清除)。默认情况下,categoryBitMask设置为0xFFFFFFFF
(所有位都设置)。因为您没有另外说明,所以场景的物理主体categoryBitMask设置为0xFFFFFFFF
。当在这两者之间执行逻辑AND(&amp;)运算符时,结果将为零,表示无冲突。
要解决此问题,您只需删除此行:
heroShip.physicsBody?.collisionBitMask = 0x0
或者通过定义Wall类别来正确设置......
<强>提示:强>
定位点定义了如何相对于节点的位置绘制纹理。它与物理机构没什么关系。默认情况下,物理主体以节点的位置为中心。如果您打开物理视觉表示(skView.showsPhysics = true
),在您的示例中,您将看到物理主体未按预期定位。
在实际初始化之前设置物理体是没有意义的。你必须先初始化物理体。
答案 1 :(得分:0)
添加Whirlwind的答案,您可能还想在物理机构上启用usesPreciseCollisionDetection
。通过将其设置为true
,如果遇到来自加速度计数据的巨大力量,这将阻止heroShip
突然出现在墙上。
基本上,物理学的计算方法与实际情况相同。因此,如果有一股巨大的力量,它可以说,“哦,这种巨大的力量意味着我应该在边界框外面的路上。”如果启用了精确的碰撞检测,则会强制它计算从该帧的起始位置到计算位置的多个位置的物理。如果它在到达计算位置之前遇到某些东西,那么它会进行调整,以使其无法通过它所击中的任何内容。在大多数情况下,你不必担心这一点,但最好是安全而不是抱歉。
在初始化之后,将此行放在物理主体配置代码中的某处:
heroShip.physicsBody?.usesPreciseCollisionDetection = true