如何检测关于精灵纹理的接触

时间:2015-08-30 17:33:07

标签: sprite-kit collision-detection

我有一颗应该在街区被解雇的子弹。 Bullet有6种不同的随机纹理来模仿不同的子弹。并且块具有随机选择的3种不同纹理,看起来有3种不同的块。我想在代码中指定如果子弹纹理是红色,并且块纹理是红色则分数应该增加,但如果子弹是红色并且块是绿色则将是游戏结束。我真的不知道如何在didBeginContact中告诉游戏。

到现在为止我有这个: 在GameScene& didMoveToView:

struct PhysicsCategory {
static let None      : UInt32 = 0
static let All       : UInt32 = UInt32.max
static let CgyBlock  : UInt32 = 0b1       
static let Bullet    : UInt32 = 0b10
}

bullet.physicsBody = SKPhysicsBody(texture: bullet.texture, size: self.bullet.size)
bullet.physicsBody?.categoryBitMask = PhysicsCategory.Bullet
bullet.physicsBody?.contactTestBitMask = PhysicsCategory.CgyBlock
bullet.physicsBody?.collisionBitMask = PhysicsCategory.None
bullet.physicsBody?.affectedByGravity = false
bullet.physicsBody?.usesPreciseCollisionDetection = true

在didBeginContact中:

func didBeginContact(contact: SKPhysicsContact) {

var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}


    if ((firstBody.categoryBitMask & PhysicsCategory.CgyBlock != 0) &&
        (secondBody.categoryBitMask & PhysicsCategory.Bullet != 0)) 
  //and here I suppose I need to implement somehow something like
 // && (bullet.texture = "redBullet") && (CgyBlock.texture = "greenBlock" || "blackBlock")
 {
   gameOver()        
    }

但我知道它不起作用。我也尝试在大括号内创建一个switch语句,它也不起作用。如何实现?

更新:这是一个块的制作方式:

var cgyBlock = SKSpriteNode()

let cgyArray = ["cyanBox", "greenBox", "yellowBox"]

func addCgyLine () {
    cgyBlock = SKSpriteNode(imageNamed: "cyanBox")
    var randomCGY = Int(arc4random_uniform(3))
    cgyBlock.texture = SKTexture(imageNamed: cgyArray[randomCGY])

    cgyBlock.physicsBody = SKPhysicsBody(texture: cgyBlock.texture, size: cgyBlock.size)
    cgyBlock.physicsBody?.dynamic = true
    cgyBlock.physicsBody?.categoryBitMask = PhysicsCategory.CgyBlock
    cgyBlock.physicsBody?.contactTestBitMask = PhysicsCategory.Bullet
    cgyBlock.physicsBody?.collisionBitMask = PhysicsCategory.None

    cgyBlock.position = CGPointMake(size.width + cgyBlock.size.width/2, CGRectGetMidY(self.frame) + 60) 
    addChild(cgyBlock)

    let actionMove = SKAction.moveTo(CGPoint(x: -cgyBlock.size.width/2, y: CGRectGetMidY(self.frame) + 60), duration: 3) 
    let actionDone = SKAction.removeFromParent()
    cgyBlock.runAction(SKAction.sequence([actionMove, actionDone]))
    SKActionTimingMode.EaseOut
}

然后我在didMoveToView中执行runAction。

子弹:

var cannon = SKSpriteNode(imageNamed: "cannon")
var bulletInCannon = SKSpriteNode()
var bullet = SKSpriteNode()

let bulletArray = ["redBullet","magentaBullet", "blueBullet", "cyanBullet", "greenBullet", "yellowBullet"]

//didMoveToView:
 var randomBullet = Int(arc4random_uniform(6))
 bulletInCannon = SKSpriteNode(imageNamed: bulletArray[randomBullet])
 bulletInCannon.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
 addChild(bulletInCannon)

 //touchesEnded:
var randomBullet = Int(arc4random_uniform(6))
        bullet = SKSpriteNode(texture: bulletInCannon.texture)
        bullet.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
        bullet.name = bulletArray[randomBullet]
        bullet.physicsBody = SKPhysicsBody(texture: bullet.texture, size: self.bullet.size)
        bullet.physicsBody?.dynamic = true
        bullet.physicsBody?.categoryBitMask = PhysicsCategory.Bullet
        bullet.physicsBody?.contactTestBitMask = PhysicsCategory.CgyBlock
        bullet.physicsBody?.collisionBitMask = PhysicsCategory.None
        bullet.physicsBody?.affectedByGravity = false
        bullet.physicsBody?.usesPreciseCollisionDetection = true

        addChild(bullet)
 bulletInCannon.texture = SKTexture(imageNamed: bulletArray[randomBullet])

2 个答案:

答案 0 :(得分:3)

几乎没有办法:

  1. 您可以使用节点的userData属性。

    bullet.userData = ["type" : "white"]
    

    要访问它:

    println(bullet.userData?["type"])
    
  2. 您可以创建自定义Bullet类,它是SKSpriteNode的子类,并创建名为“type”的属性,并在didBeginContact中创建以访问该属性。

    class Bullet: SKSpriteNode {
    
        var type:String = ""
    
    
         init(type:String) {
             self.type = type //later you are accessing this with bulletNode.type
            //This is just an simple example to give you a basic idea  what you can do.
            //In real app you should probably implement some kind of security check to avoid wrong type
            let texture = SKTexture(imageNamed: type)
    
            super.init(texture: texture, color: nil, size: texture.size())
        }
    
        required init(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    
  3. 您也可以使用bullet.name属性,并在创建时根据项目符号/块颜色适当地设置它。稍后在didBeginContact中,您将检查bullet.name以查找项目符号类型。块也一样。

    func spawnBulletWithType(type:String) -> SKSpriteNode{
    
         //set texture based on type
         //you can pass here something like white_bullet
    
         let atlas = SKTextureAtlas(named: "myAtlas")
    
    
         //here, if passed white_bullet string, SpriteKit will search for texture called white_bullet.png
         let bullet = SKSpriteNode(texture:atlas.textureNamed(type))
    
    
         bullet.name = type // name will be white_bullet, and that is what you will search for in didBeginContact
    
         bullet.physicsBody = SKPhysicsBody(texture: bullet.texture, size: bullet.size)
         bullet.physicsBody?.categoryBitMask = PhysicsCategory.Bullet
         bullet.physicsBody?.contactTestBitMask = PhysicsCategory.CgyBlock
         bullet.physicsBody?.collisionBitMask = PhysicsCategory.None
         bullet.physicsBody?.affectedByGravity = false
         bullet.physicsBody?.usesPreciseCollisionDetection = true
    
         return bullet
    }
    
  4. 编辑:

    根据您最近的评论,您可能会这样做:

    let bulletArray = ["redBullet","magentaBullet", "blueBullet", "cyanBullet", "greenBullet", "yellowBullet"]
    
    //didMoveToView:
     var randomBullet = Int(arc4random_uniform(6))
     let bulletType = bulletArray[randomBullet]
     bulletInCannon.name = bulletType
     bulletInCannon = SKSpriteNode(imageNamed: bulletType )
     bulletInCannon.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
     addChild(bulletInCannon)
    
    
    //touchesEnded:
    var randomBullet = Int(arc4random_uniform(6))
            bullet = SKSpriteNode(texture: bulletInCannon.texture)
            bullet.name = bulletInCannon.name
            bullet.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
    
            bullet.physicsBody = SKPhysicsBody(texture: bullet.texture, size: self.bullet.size)
            bullet.physicsBody?.dynamic = true
            bullet.physicsBody?.categoryBitMask = PhysicsCategory.Bullet
            bullet.physicsBody?.contactTestBitMask = PhysicsCategory.CgyBlock
            bullet.physicsBody?.collisionBitMask = PhysicsCategory.None
            bullet.physicsBody?.affectedByGravity = false
            bullet.physicsBody?.usesPreciseCollisionDetection = true
    
            addChild(bullet)
    let bulletType = bulletArray[randomBullet]
     bulletInCannon.texture = SKTexture(imageNamed: bulletType)
     bulletInCannon.name = bulletType
    

答案 1 :(得分:2)

首先,您需要为项目符号和块定义一个类 然后,您可以定义TextureTypes来存储纹理类型(红色,绿色,......),并将随机方法生成的任何内容设置为此类型的类变量。 然后,您应该管理联系人并找出BodyA和BodyB的节点。之后,根据节点的纹理类型,很容易做任何你喜欢的事情,

  

澄清我已将Textures定义为新Type

的代码
enum TextureTypes: String {
    case Red,Green 
    var description:String {
        switch self {
        case Red:return “Red"
        case Green:return “Green”
        case Green:return “Blue"
        }
    }
}
  

Blockclass和BulletClass都从SKNode继承,因为它们是一个节点!

class BlockClass:SKNode {
    var NodesTexture : TextureTypes = TextureTypes.Red
}

class BulletClass:SKNode {
    var NodesTexture : TextureTypes = TextureTypes.Red
}
  

将以下代码写入didBeginContact方法以检测节点的TextureType

    if (contact.bodyA.categoryBitMask == PhysicsCategory.Bullet) &&    
       (contact.bodyB.categoryBitMask == PhysicsCategory.CgyBlock)
    {
        Ablock = (BlockClass *) contact.bodyB.node;
        Abullet = (BulletClass *) contact.bodyA.node;
    }
    if (contact.bodyA.categoryBitMask == PhysicsCategory.CgyBlock) &&    
       (contact.bodyB.categoryBitMask == PhysicsCategory.Bullet)
    {
        Ablock = (BlockClass *) contact.bodyA.node;
        Abullet = (BulletClass *) contact.bodyB.node;
        if ( Ablock.NodesTexture = TextureTypes.Red )
        {
            NSLOG(“A Red Block Detected”)

        }
    } 

不要忘记定义BlocksClass和BulletClass

类型的块和项目符号