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

How to detect contact regarding sprite texture

我有一颗子弹应该被挡住。 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])

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

to clarify the code I have defined Textures as a new 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 and BulletClass both hasto inherit from SKNode cause they are a node!

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

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

write the following codes into your didBeginContact method to detect the TextureType of your Node

    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 类型的块和项目符号

几条路要走:

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

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

    要访问它:

    println(bullet.userData?["type"])
    
  2. 您可以创建自定义 Bullet class,它是 SKSpriteNode 的子 class,并创建名为 "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 属性,并在创建时根据bullet/block颜色适当地设置它。稍后在 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
    }
    

编辑:

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

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