Check if the player is on top of another node?

I'm trying to let the player jump. However, I cannot let him jump in the air, so I need to check if he should stand on top of another node before applying the impulse.

How do other sprite games usually do this?


Now I'm trying two approaches, the first of them is this one. This is great, however, I don’t know how to determine if the node the player really touches is actually below or to the side of the player.

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { var allowJump = false let bodies = player.physicsBody.allContactedBodies() for body : AnyObject in bodies { if let node = body.node { allowJump = true // Player is touching another node but we don't know where (the bottom of the player or it sides) } } } 

This is a different approach, it is effective to find out if the contact has started, and also whether the contact is really with the ground (under the player), and not with the wall or such. However, I do not know how to say when the player ceases to be on top of any nodes, because even if the contact ends, he can still contact another node.

 func didBeginContact(contact: SKPhysicsContact!){ if(contact.bodyA.node.position.y < contact.contactPoint.y) { println("BodyA is on top of another node") } if(contact.bodyB.node.position.y < contact.contactPoint.y) { println("BodyB is on top of another node") } } func didEndContact(contact: SKPhysicsContact!){ if(contact.bodyA.node.position.y < contact.contactPoint.y) { println("BodyA is on no longer on top of BodyB") } if(contact.bodyB.node.position.y < contact.contactPoint.y) { println("BodyB is no longer on top of BodyA") } } 
+6
source share
4 answers
 typedef NS_OPTIONS(uint32_t, CNPhysicsCategory) { CNPhysicsCategoryChick = 1, CNPhysicsCategoryEdge = 2, CNPhysicsCategoryStrawberry = 3, }; @interface MyScene() <SKPhysicsContactDelegate> @end @implementation MyScene { SKSpriteNode *strawberry; SKSpriteNode *chick; } -(id)initWithSize:(CGSize)size { if (self = [super initWithSize:size]) { /* Setup your scene here */ self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame]; self.physicsBody.categoryBitMask = CNPhysicsCategoryEdge; self.physicsWorld.contactDelegate = self; self.physicsBody.restitution = 0.0; chick = [SKSpriteNode spriteNodeWithImageNamed:@"chick"]; [chick setScale:0.3]; chick.position = CGPointMake(self.size.width/2, chick.size.height/2); chick.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:chick.size]; chick.physicsBody.categoryBitMask = CNPhysicsCategoryChick; chick.physicsBody.collisionBitMask = CNPhysicsCategoryEdge; chick.physicsBody.restitution = 0.0; [self addChild:chick]; strawberry = [SKSpriteNode spriteNodeWithImageNamed:@"strawberry"]; strawberry.position = CGPointMake(chick.position.x, chick.position.y - chick.size.height/2 + strawberry.size.height/2); //You should make this hidden //strawberry.hidden = YES; strawberry.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize: CGSizeMake(strawberry.size.width, strawberry.size.height)]; strawberry.physicsBody.categoryBitMask = CNPhysicsCategoryStrawberry; strawberry.physicsBody.collisionBitMask = kNilOptions; strawberry.physicsBody.contactTestBitMask = CNPhysicsCategoryEdge; strawberry.physicsBody.density = 0.001; strawberry.physicsBody.restitution = 0.0; [self addChild:strawberry]; SKPhysicsJointFixed *point = [SKPhysicsJointFixed jointWithBodyA:strawberry.physicsBody bodyB:chick.physicsBody anchor:CGPointZero]; [self.physicsWorld addJoint:point]; } return self; } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [chick.physicsBody applyImpulse:CGVectorMake(0, 60)]; } -(void)didBeginContact:(SKPhysicsContact *)contact { uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask); if (collision == (CNPhysicsCategoryEdge | CNPhysicsCategoryStrawberry)) { NSLog(@"In Contact"); } } -(void)didEndContact:(SKPhysicsContact *)contact { uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask); if (collision == (CNPhysicsCategoryEdge | CNPhysicsCategoryStrawberry)) { NSLog(@"Contact Is Lost"); } } @end 

enter image description hereenter image description here

+2
source

This is what I am doing now, however it does not let me know if the node is touching below / left / right. I could just compare my position with my node, however some nodes are hollow, like edgeLoopFromPath, or have different shapes.

 override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { var allowJump = false let bodies = player.physicsBody.allContactedBodies() for body : AnyObject in bodies { if let node = body.node { // Additionally check contactBitMask allowJump = true } } } 
+2
source

Use states to accomplish this.

Suppose ur player can be in two states - 1. touchingTheGround 2. inTheAir

  • Apply an upward impulse to the player only if its state is touchingTheGround and change the state to inTheAir
  • When a player touches the ground, set its state to by touching TheGround . Also at this stage you can check that the angle passing along the line passing through the center of the player node and the point of contact is an angle of -90 degrees (or about -90) with the + x axis (the player landed on his feet)
  • If the player does not do so , you can send the player to a different state and write a different logical state for him.

To implement states, I recommend using NS_ENUM

0
source

Add another node at the bottom of your node player (legs, if you want) and use this to detect collisions. Make the β€œlegs node” a little narrower than your player so that it does not cause side collisions. When the legs are in contact with bodies other than the player himself, you know that he is standing on something.

0
source

Source: https://habr.com/ru/post/972466/


All Articles