1
votes

I have a top down strategy game. My current physics simulation has nodes that can contact and collide just fine on their own. The issue is I am trying to find a solution where my contact can be further out (larger circle) than the collision. The reason is logical enough, I want to know when one node is within "range" of another.

For instance imagine a sprite with a "range" circle 20 pixels further out from the actual sprite.

I have tried just making the physics body on the sprite larger than the sprites frame but then collisions are based on the "range circle" and not the sprite.

I have also tried adding a SKShapeNode circle to the sprite and adding a physics body with it. Problem is when I do that, the child node still collides with the physics body of another child's node range circle.

Not to mention my performance with only about 20 nodes (and their own physics bodies and the range nodes and their physics bodies) goes south quickly.

I would prefer to keep the contact within the physics simulation and not an adhoc solution.

Any ideas/tips?

  // Mover physics
self.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:(self.frame.size.width/2)];
self.physicsBody.collisionBitMask = self.player == kPlayer_Human ? CATEGORY_HUMAN_MOVER : CATEGORY_AI_MOVER;
self.physicsBody.categoryBitMask = self.player == kPlayer_Human ? CATEGORY_HUMAN_MOVER : CATEGORY_AI_MOVER;
self.physicsBody.contactTestBitMask = 0;

_rangeNode = [SKShapeNode node];
_rangeNode.name = @"rangeNode";
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddArc(path, NULL, 0,0, _range, 0, M_PI*2, YES);
_rangeNode.path = path;
_rangeNode.lineWidth = 1.0;
_rangeNode.fillColor = [SKColor clearColor];
_rangeNode.strokeColor = [SKColor whiteColor];
_rangeNode.hidden = YES;

[self addChild:_rangeNode];

_rangeNode.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:_range];
_rangeNode.physicsBody.dynamic = NO;
_rangeNode.physicsBody.categoryBitMask = self.player == kPlayer_Human ? CATEGORY_HUMAN_MOVER_RANGE : CATEGORY_AI_MOVER_RANGE;
_rangeNode.physicsBody.contactTestBitMask = self.player == kPlayer_Human ? CATEGORY_AI_MOVER | CATEGORY_AI_HERO | CATEGORY_AI_TOWER : CATEGORY_HUMAN_MOVER | CATEGORY_HUMAN_HERO | CATEGORY_HUMAN_TOWER;
_rangeNode.physicsBody.collisionBitMask = 0;

Category defines, set globally:

static const uint32_t CATEGORY_HUMAN_MOVER = 0x1 << 0;
static const uint32_t CATEGORY_AI_MOVER = 0x1 << 1;
static const uint32_t CATEGORY_HUMAN_HERO = 0x1 << 2;
static const uint32_t CATEGORY_AI_HERO = 0x1 << 3;
static const uint32_t CATEGORY_HUMAN_TOWER = 0x1 << 4;
static const uint32_t CATEGORY_AI_TOWER = 0x1 << 5;
static const uint32_t CATEGORY_WALLS = 0x1 << 6;
static const uint32_t CATEGORY_HUMAN_MOVER_RANGE = 0x1 << 7;
static const uint32_t CATEGORY_AI_MOVER_RANGE = 0x1 << 8;

Thanks, E

1
Disable collisions for the SKShapeNode circles and set for contact only.sangony
^ by setting the collisionBitMask of the range circle to zero.0x141E
Definitely a great tip. Collision is not happening anywhere until nodes pool at a point. Once they do (to keep them separate) they have collision only to each other. Even with the range circle set to bit mask = 0, and the nodes body set to collision with themselves the range circle "pushes" the node around. I have added my code above to assist.Calm Turtle
It would be useful if you posted the code that defines the various categories. For performance reasons, you shouldn't set the fill and stroke colors to clear. Instead set the alpha of the range circles to 0. If you want to see the physics bodies (for debugging purposes), set the showPhysics property of the view to YES.0x141E
Thanks for the tip about clear color. I will definitely implement. The big impact on performance comes when the nodes on the same team start to pool (3+ nodes). Each one that enters the pool of range circles impacts greater and greater, which I don't understand since they should only be using contact for enemy nodes, not each other.Calm Turtle

1 Answers

0
votes

I'm not certain what your question actually is, but note that your "mover" node has a SKPhysicsBody set to twice the size of the node itself. That alone may be why your nodes are "pushing" each other around oddly.

Other notes/concerns:

Is there a particular reason you're setting a stroke and fill color for a hidden node?

Why create a parent node of any size for the range physics body? Might performance improve if you had an "empty" node with the same range circle physics body?

If you have a performance hit when an enemy contacts/collides with multiple nodes, take careful note of your contact handling routines (didBeginContact and didEndContact). Does there seem to be anything there that might adversely affect performance?