Sprite Kit Перемещение узлов с помощью SKAction вызывает проблемы

Я пытаюсь создать блочную игру, в которой у меня есть ряд блоков, я сдвигаю конечный блок справа налево, а каждый из остальных блоков перемещается вправо на 1 позицию. Если я затем снова сдвину блок назад, они все сдвинутся влево на 1 позицию. У меня проблема в том, что если я перетаскиваю медленно, все работает нормально, но если я быстро перетаскиваю вперед и назад, все блоки перепутываются, они перемещаются друг над другом, поэтому вместо ряда из 6 у меня есть ряд из 4. так как 2 блока сидят позади других. Любые советы приветствуются.

Вот код из моего Scene.M

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

self.selectedNode = [self nodeAtPoint:[[touches anyObject] locationInNode:self]];

[self.selectedNode.physicsBody setDynamic:YES];
self.selectedNode.zPosition = 1;
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint currentPoint = CGPointMake([[touches anyObject] locationInNode:self].x , selectedNode.position.y);
CGPoint previousPoint = CGPointMake([[touches anyObject] previousLocationInNode:self].x , selectedNode.position.y);
_deltaPoint = CGPointSubtract(currentPoint, previousPoint);
}

-(void)update:(CFTimeInterval)currentTime {

CGPoint newPoint = CGPointAdd(self.selectedNode.position, _deltaPoint);

self.selectedNode.position = newPoint;

_deltaPoint = CGPointZero;

}

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

SKNode *node = contact.bodyA.node;
if ([node isKindOfClass:[Block class]] && node != selectedNode) {
    [(Block *)node collidedWith:contact.bodyB contact:contact];
}

node = contact.bodyB.node;
if ([node isKindOfClass:[Block class]] && node != selectedNode) {
    [(Block *)node collidedWith:contact.bodyA contact:contact];
}
}

Вот мой код из моего Block.M

-(instancetype)initWithPosition:(CGPoint)pos andType:(NSString *)blockType{

SKTextureAtlas *atlas =
[SKTextureAtlas atlasNamed: @"Blocks"];
SKTexture *texture = [atlas textureNamed:blockType];
texture.filteringMode = SKTextureFilteringNearest;

if (self = [super initWithTexture:texture]){
    self.name = blockType;
    self.position = pos;
    self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(self.size.width - 30, self.size.height - 8)];
    self.physicsBody.usesPreciseCollisionDetection = YES;
    self.physicsBody.categoryBitMask = 1;
    self.physicsBody.collisionBitMask =  0;
    self.physicsBody.contactTestBitMask = 1;

}

return self;
}

- (void)collidedWith:(SKPhysicsBody *)body contact:(SKPhysicsContact*)contact {

CGPoint localContactPoint = [self.scene convertPoint:contact.contactPoint toNode:self];

if (localContactPoint.x < 0) {
    SKAction *moveLeftAction = [SKAction moveByX:-48 y:0 duration:0.0];
    [self runAction:moveLeftAction];
} else {
    SKAction *moveRightAction = [SKAction moveByX:48 y:0 duration:0.0];
    [self runAction:moveRightAction];
}
}

person TazmanNZL    schedule 26.06.2014    source источник
comment
Используйте runAction:withKey:, чтобы убедиться, что на данном узле выполняется только одно действие перемещения. Скорее всего, ваша проблема связана с тем, что несколько действий перемещения сложены.   -  person LearnCocos2D    schedule 26.06.2014


Ответы (1)


У вас может быть несколько действий перемещения, выполняемых одновременно, если вы начинаете столкновение до завершения предыдущих действий перемещения в данном блоке, что может привести к странным анимациям.

Одним из решений является удаление существующих анимаций перед запуском следующих. Что-то вроде этого (не проверено):

- (void)collidedWith:(SKPhysicsBody *)body contact:(SKPhysicsContact*)contact {

CGPoint localContactPoint = [self.scene convertPoint:contact.contactPoint toNode:self];

    // If we have any move actions still in progress, complete them so we can start a new one
    if ([self actionForKey:@"blockMove"]) {
        [self removeActionForKey:@"blockMove"];
        self.position = CGPointMake(_targetX, self.position.y);
    }

    if (localContactPoint.x < 0) {
        _targetX = self.position.x - 48;
    } else {
        _targetX = self.position.x + 48;
    }
    SKAction *moveLeftAction = [SKAction moveToX:_targetX y:0 duration:0.0];
    [self runAction:moveLeftAction withKey:@"blockMove"];
}
person NatL    schedule 26.06.2014
comment
Пробовал, но та же проблема. Некоторые блоки перемещаются более чем на один блок. Все они начинают выстраиваться вместе, а затем, когда я быстро двигаю пальцем вперед и назад по строке, видны только 2 или 3, а остальные пробелы пусты. - person TazmanNZL; 26.06.2014
comment
Я также заметил, что иногда значение localContactPoint положительное, хотя должно быть отрицательным, поэтому блок движется вправо, когда он должен двигаться влево! - person TazmanNZL; 27.06.2014
comment
хм... Интересно, является ли это побочным эффектом использования moveByX и вычисления дельт вместо moveToX с пунктами назначения... использование дельт, если что-то выйдет из строя после того, как они будут отключены навсегда. Я обновил объяснение, чтобы вместо этого использовать moveToX, это работает? - person NatL; 27.06.2014
comment
Ни у одного moveToX нет такой проблемы. Некоторые блоки все еще перемещаются поверх или под другие блоки. Что-то делать со скоростью физики? - person TazmanNZL; 27.06.2014
comment
К сожалению, я не знаю, куда идти дальше, не имею достаточного опыта отладки проблем с физикой. Удачи! - person NatL; 27.06.2014