1
votes

Trying to make a stationary turret fire at a moving enemy (tower defense game).

static const uint32_t towerCategory  = 0x1 << 0;
static const uint32_t creepCategory  = 0x1 << 1;

If the above is right, the towerCategory should have the lower category number correct?

tower.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:80];
tower.physicsBody.dynamic = YES;

tower.physicsBody.categoryBitMask = towerCategory;
tower.physicsBody.contactTestBitMask = creepCategory;
tower.physicsBody.collisionBitMask = 0;

This should set the tower node to be in the towerCategory and react to contact between the creep moving into range (range being the 80 radius physics body). Since I also don't want the tower or creep to push each other, I set the collision to 0.

baddie.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:baddie.size];
baddie.physicsBody.dynamic = YES;

baddie.physicsBody.categoryBitMask = creepCategory;
baddie.physicsBody.contactTestBitMask = towerCategory;
baddie.physicsBody.collisionBitMask = 0;

Same thing for the enemy. I switch the category and contact bitMask though since this one should be a creep, and it contacts the tower. Still no collision though so set it to 0.

    SKPhysicsBody* firstBody;
    SKPhysicsBody* secondBody;

if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
    firstBody = contact.bodyA;
    secondBody = contact.bodyB;
}
else
{
    firstBody = contact.bodyB;
    secondBody = contact.bodyA;
}

    if ((firstBody.categoryBitMask & towerCategory) != 0 &&
        (secondBody.categoryBitMask & creepCategory) != 0)
    {
        [secondBody.node removeAllActions];
    }

I am pretty sure the didBeginContact function is where things are failing. Since towerCategory is lower than creepCategory, it should always be placed in firstBody if my code is correct. Then when the creep moves into contact range it should remove all actions from it and stop on the tracks. However he just keeps moving through. Can someone point out what I am missing?

1
If I change the collisionBitMap of either node to be the other, they do collide and end up pushing each other around the scene. But without it, the nodes pass right by each other as if didBeginContact is never called.Klutch
I actually solved my own problem here by figuring out the bitMask for the tower was not actually lower.Klutch
If your collisions & contacts are not working as expected, try adding my checkPhysics() function to your program and calling it after you have sett all of the categories and bitmasks - at the end of didMovetoview is usually a good place. See the code for it here: stackoverflow.com/questions/36570859/…Steve Ives
Remember that a collision results in bodies pushing/bouncing off each other and you don't have to write any code for this - the physics engine does all the work. A contact is when 2 bodies touch (which may or may not result in a collision) and is handled completely by your code.Steve Ives
Also, it's possible for bodyA to collide with bodyB but for bodyB not to collide with bodyA - in this case, when the 2 collide, bodyB will be totally unaffected and be unmoved by the collision but bodyA will be deflected in some way. A contact is when 2 bodies touch (which may or may not result in a collision). If you are interested in being notified for contacts between bodyA and bodyB, you only need to set bodyA to contact bodyB i.e. set bodyA's contactTestbitMask to bodyB's categorybitMask - you don't need to set bodyb to contact bodyA.Steve Ives

1 Answers

1
votes

Try this code for your didBeginContact:

- (void)didBeginContact:(SKPhysicsContact *)contact
{
    NSLog(@"bodyA:%@ bodyB:%@",contact.bodyA.node.name, contact.bodyB.node.name); // <- this gives you who touched who by object name

    uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);

    if (collision == (towerCategory | creepCategory))
    {
        NSLog(@"we got contact...");
    }
}

Remember that contact.bodyA.node.(property) can give you any property of SKNode. Things like name, position, xScale, yScale, alpha, children, parent and so on. You can see them all listed at the SKNode Class Reference.