1

Hey so I have a problem detecting collisions. I have this project I am making based on Ray Wenderlich's tutorial on How to Make a game like Mega Jump. So everything is works great at the beginning, where platforms and stars are static in one place. But as you go further in the game, stars and platforms start moving (I am using SKActions for this), tried to do this to make it a little harder. But when I get there, collision is NOT being detected at all, player just passes by through the objects like they weren't there. I've been reading everywhere online, I am using precise collision detection but still I see no difference. Any ideas on what can be wrong or what else can I do? Here is a bit of code on how I am doing this:

    player = SKSpriteNode(texture: firstFrame)
    player.position = (CGPoint(x: self.size.width / 2, y: 50.0))
    player.physicsBody = SKPhysicsBody(circleOfRadius: player.size.width / 2)
    player.physicsBody?.dynamic = true
    player.physicsBody?.allowsRotation = false
    player.physicsBody?.restitution = 1.0
    player.physicsBody?.friction = 0.0
    player.physicsBody?.angularDamping = 0.0
    player.physicsBody?.linearDamping = 0.0
    player.physicsBody?.usesPreciseCollisionDetection = true
    player.physicsBody?.categoryBitMask = CollisionCategoryBitmask.Player
    player.physicsBody?.collisionBitMask = 0
    player.physicsBody?.contactTestBitMask = CollisionCategoryBitmask.Star | CollisionCategoryBitmask.Platform | CollisionCategoryBitmask.Monster
    foregroundNode.addChild(player)  

func createPlatformAtPosition(position: CGPoint, ofType type: PlatformType) -> PlatformNode {

    let node = PlatformNode()
    let thePosition = CGPoint(x: position.x * scaleFactor, y: position.y)
    node.position = thePosition
    node.name = "NODE_PLATFORM"
    node.platformType = type

    var sprite: SKSpriteNode
    var spriteFrames : [SKTexture]!
    if type == .Break {

        let spriteAnimatedAtlas = SKTextureAtlas(named: "CloudBreak")
        var cloudFrames = [SKTexture]()
        spriteFrames = cloudFrames
        let firstFrame = SKTexture(imageNamed: "Cloud02")
        sprite = SKSpriteNode(texture: firstFrame)

        let move = SKAction.moveToX(self.position.x - 160.0, duration:2.0)
        let back = SKAction.moveToX(self.position.x, duration:2.0)
        let sequence = SKAction.sequence([move, back, move, back])
        sprite.runAction(SKAction.repeatActionForever(sequence))

    } else {     
        let spriteAnimatedAtlas = SKTextureAtlas(named: "Cloud")
        var cloudFrames = [SKTexture]()
        spriteFrames = cloudFrames
        let firstFrame = SKTexture(imageNamed: "Cloud")
        sprite = SKSpriteNode(texture: firstFrame)

    }

    node.addChild(sprite)
    node.physicsBody = SKPhysicsBody(rectangleOfSize: sprite.size)
    node.physicsBody?.dynamic = false
    node.physicsBody?.categoryBitMask = CollisionCategoryBitmask.Platform
    node.physicsBody?.contactTestBitMask = CollisionCategoryBitmask.Player
    node.physicsBody?.collisionBitMask = 0

    return node
}

 func didBeginContact(contact: SKPhysicsContact) {

    var updateHUD = false
    let whichNode = (contact.bodyA.node != player) ? contact.bodyA.node : contact.bodyB.node
    let other = whichNode as GameObjectNode
    updateHUD = other.collisionWithPlayer(player)

}

    struct CollisionCategoryBitmask {
      static let Player: UInt32 = 0x00
      static let Star: UInt32 = 0x01
      static let Platform: UInt32 = 0x02
      static let Monster: UInt32 = 0x03
           }

3 Answers3

2

Slow the objects down and see if they collide. I had an issue where I was moving my nodes too fast and they were past the collision points when the new frame was rendered. If they move so fast they pass each other's physics body in the frame cycle they will not register a hit.

To detect a collision in that case, you can compare where they are in each frame, and if they have passed each other or their x/y plane values overlap, you can execute your collision code.

Siriss
  • 3,737
  • 4
  • 32
  • 65
  • thanks and how may I do that? The thing is that I am loading the objects from a Plist. I already tried slowing them down to nearly not moving at all and it is still not working! – Thesaurus03 Apr 22 '15 at 17:30
1

The collision is not detected because you didn't set the collisionBitMask.

player.physicsBody?.collisionBitMask = CollisionCategoryBitmask.Star | CollisionCategoryBitmask.Platform | CollisionCategoryBitmask.Monster
node.physicsBody?.collisionBitMask = CollisionCategoryBitmask.Player

Contact and Collision aren't the same thing. You can find more information online.

If it still doesn't work, please show us your CollisionCategoryBitmask to make sure you created it properly.

Edit :

struct CollisionCategoryBitmask {
    static let Player:    UInt32 = 0
    static let Star:      UInt32 = 0b1
    static let Platform:  UInt32 = 0b10
    static let Monster:   UInt32 = 0b100
}

Here is a table I've made for another question, that might help you too : http://goo.gl/7D8EGY

Community
  • 1
  • 1
lchamp
  • 6,592
  • 2
  • 19
  • 27
  • Hey @lchamp thank you! But that didn't work either.. I added my Collision CategoryBitmask for you to see it. – Thesaurus03 Apr 22 '15 at 07:41
  • Your `Monster` bitmask was _incorrect_. Check my edit and let me know if it works. – lchamp Apr 22 '15 at 07:50
  • Thank you @lchamp but still, this isn't solving my problem! Player still passes by moving objects without collision being detected. The thing is that everything works fine at the beginning, just when the objects start moving that when collision stop working. – Thesaurus03 Apr 22 '15 at 16:50
  • SKPhysicsBody Class Reference (http://goo.gl/oTamRv) : _"[...] The dynamic property controls whether a volume-based body is affected by gravity, friction, **collisions with other objects**, and forces or impulses you directly apply to the object."_ You should try to set `node.physicsBody?.dynamic = true` (instead of false). And if you don't want this node to move you also might want to do the following : `node.physicsBody?.affectedByGravity = false` and `node.physicsBody?.pinned = true`. Let me know :') – lchamp Apr 22 '15 at 17:01
  • it worked the same only made my fps to drop! I also added the usesPreciseCollision to the objects as well but still ... – Thesaurus03 Apr 22 '15 at 17:21
  • It's probably the `usesPreciseCollision` which slowed the FPS down. In your game view controller, try to turn on `skView.showsPhysics = true` to see what is going on. Can you somehow upload your project (github, zip file upload (link in discussion), ... So that I can give a look at the problem ? – lchamp Apr 22 '15 at 17:22
  • Awesome @lchamp, looks like the node stays where it is originally positioned, so it is just the image that moves around. The code I used for that is in the question. I used SKActions but it seems they apply only to the sprite but not the node – Thesaurus03 Apr 22 '15 at 19:54
  • Try to `node.addChild(sprite)` before you apply you run your sequenced action ? – lchamp Apr 22 '15 at 19:56
0

Check out my collision physics engine, it's very simple but has support for continuous/predicting/bullet collisions. You might learn something from the code, and it's written in javascript so it should be easy to read.https://github.com/Murplyx/AAE---Axis-Aligned-Engine