IOS SpriteKit Colision Detection:重置对象的位置

时间:2015-05-30 18:15:31

标签: objective-c sprite-kit collision-detection

我正在进行碰撞检测,希望当Object1向下移动屏幕并最终命中Object2时,它会触发didBeginContact方法,反过来,Object1上的resetPosition会将Object1带回屏幕顶部。我已经使用NSLogs进行测试,以确保程序是否达到了didBeginContact方法,并且确实如此。最重要的是,程序也可以通过调用方法(resetPosition)来工作。唯一的问题是,它不会改变Object1的位置。我试图看看我是否可以在touchesBegan方法中调用方法resetPosition,并且它可以工作。 Object1的位置实际上已重置。你可以在didBeginContact方法中做些什么限制?如果是这样,那么尝试达到预期目标的最佳方法是什么。

以下是我的didBeginContact方法示例:

-(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];
}

为了澄清任何混淆,Category1对应于Object1,Category2对应于Object2。

以下是我的Object1类中的resetPosition方法示例:

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

1 个答案:

答案 0 :(得分:0)

你应该看看run loop。物理模拟完成之前没有任何东西被绘制出来。所以我猜你所做的改变位置会被物理模拟所覆盖。

这是运行循环的顺序:

  • 更新称为
  • 场景评估行动
  • didEvaluateActions被称为
  • 物理模拟就在这里
  • didSimulatePhysics被称为
  • 场景应用约束
  • didApplyConstraints被称为
  • didFinishUpdate被称为
  • 渲染框架

如果你在didSimulatePhysics中移动节点的重新定位而不是在didBeginContact中执行一切都可行,我可以打赌。我想这种情况正在发生,因为你试图在模拟完成之前改变节点的位置。你可以试试这段代码(看看didSimulatePhysics部分):

#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