IOS SpriteKit Colision Detection: Resetting Position of an Object

核能气质少年 提交于 2019-12-02 08:56:14

问题


I'm working on Collision Detection where the hope is when Object1 moves down the screen and eventually hits Object2 it triggers the didBeginContact method and in turn, the resetPosition on Object1 which will bring Object1 back to the top of the screen. I've used NSLogs to test to make sure if the program reaches the didBeginContact method, and it does. On top of that, the program also works through the called upon method (resetPosition) as well. The only problem is, it does not change the position of Object1. I the tried to see if I could call the method resetPosition in the touchesBegan method, and it works. Object1's position is actually reset. Are there limitations to what you can do in the didBeginContact method? And if so, what would be the best way of trying to achieve my intended goal.

Here is a sample of my didBeginContact Method:

-(void)didBeginContact: (SKPhyicsContacts *)contact { 
SKPhysicsBody *firstBody, *secondBody;
if(contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask){
    firstBody = contact.bodyA;
    secondBody = contact.bodyB;
} else {
    firstBody = contact.bodyB; 
    secondBody = contact.bodyA;
}

if(firstBody.categoryBitMask == Category1 && secondBody.categoryBitMask == Category2){
    NSLog(@"Collision Detected!");
    [Object1 resetPosition];
}

To clarify any confusion, Category1 corresponds to Object1, Category2 corresponds to Object2.

Here is a sample of my resetPosition method inside of my Object1 class:

-(void)resetPosition{
    self.position = CGPointMake(0, 200);
    NSLog(@"Reached Method!");
}

回答1:


You should take a look at run loop. Nothing is drawn before physics simulation is done. So I guess that changing position like you are doing is overwritten by physics simulation.

This is the order of run loop:

  • update is called
  • scene evaluate actions
  • didEvaluateActions is called
  • physics simulation goes here
  • didSimulatePhysics is called
  • scene applies constraints
  • didApplyConstraints is called
  • didFinishUpdate is called
  • rendering the frame

I could bet if you move repositioning of node in didSimulatePhysics instead of doing it in didBeginContact that everything will work. I guess this is happening because you are trying to change node's position before simulation is done. You can try this code (look at didSimulatePhysics part):

#import "GameScene.h"

typedef enum uint_8{
    ColliderWall = 1,
    ColliderPlayer = 2,
    ColliderBrick =  4
}CollisionCategory;


@interface Object1 : SKSpriteNode

@end

@implementation Object1

-(instancetype)initWithColor:(UIColor *)color size:(CGSize)size{

    if(self = [super initWithColor:color size:size]){


        self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:size];

        self.physicsBody.categoryBitMask = ColliderPlayer;
        self.physicsBody.contactTestBitMask = ColliderBrick;
        self.physicsBody.collisionBitMask = ColliderBrick | ColliderWall;
        self.physicsBody.dynamic = YES;
        self.physicsBody.affectedByGravity = YES;
        self.physicsBody.allowsRotation = NO;

    }
    return self;
}



@end

@interface GameScene  ()<SKPhysicsContactDelegate>

@property (nonatomic, strong) Object1 *player;
@property (nonatomic, strong) SKSpriteNode *brick;

@property (nonatomic, assign) BOOL shouldMove;

@end

@implementation GameScene

-(void)didMoveToView:(SKView *)view {
    /* Setup your scene here */

    _shouldMove = NO;

    self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
    self.physicsBody.contactTestBitMask = 0;
    self.physicsBody.collisionBitMask =  ColliderPlayer;
    self.physicsBody.categoryBitMask = ColliderWall;

    self.physicsWorld.contactDelegate = self;

    _player = [[Object1 alloc] initWithColor:[SKColor greenColor] size:CGSizeMake(50,30)];
    _player.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMaxY(self.frame)- _player.size.height-30);
    [self addChild:_player];

    _brick = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(330,80)];
    _brick.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_brick.size];
    _brick.position = CGPointMake(CGRectGetMidX(self.frame),100);
    _brick.physicsBody.contactTestBitMask = ColliderPlayer;
    _brick.physicsBody.collisionBitMask = ColliderPlayer;
    _brick.physicsBody.categoryBitMask = ColliderBrick;
    _brick.physicsBody.affectedByGravity = NO;
    _brick.physicsBody.dynamic = NO;

    [self addChild:_brick];


}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */

    for (UITouch *touch in touches) {

        [self.player.physicsBody applyImpulse:CGVectorMake(0,55)];

    }
}

-(void)didBeginContact:(SKPhysicsContact *)contact{

    NSLog(@"Contact");

    self.shouldMove = YES;

}

-(void)didSimulatePhysics{

    if(self.shouldMove){


        self.player.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMaxY(self.frame)- _player.size.height-30);


        self.shouldMove = NO;
    }
}


@end


来源:https://stackoverflow.com/questions/30549679/ios-spritekit-colision-detection-resetting-position-of-an-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!