Sprite Kit + A * pathfinding =波动和冻结

时间:2014-08-14 10:25:36

标签: xcode sprite-kit freeze path-finding

我正在尝试通过使用精灵套件制作游戏来学习xcode并且已经相对较远。我以前做过一些编程,但我很快就学会了,但经过几个小时的调试后,我几乎放弃了。

我已经构建了一个包含许多块(32x32px)和1-4个字符的地图,这些字符使用A * pathfinding来查找路径。

它有效,但我有两个问题:

  1. 正确计算路径并且char移动但是当char动画到下一个块时,有一个小paus并且他移动到下一个块。这个小小的paus让动画看起来不稳定,就像char走路一样 - > micropaus - >步行。 路径存储在nsmutablearray中,并且该方法在完成SKAction(完成)后调用自身以设置下一个动作的动画。在新动作的完成和动画之间,有这个角色的微观。

  2. 当char计算路径时,游戏会冻结一段时间。当我有4个字符时,每次计算新路径时游戏都会冻结。那是为什么?

  3. 当我单击char应该移动到的块时,我调用:

    -(void)moveToward:(tileMap*)selBlock {
        BOOL pathFound = NO;
    
        if (currentStepAction) {
            self.pendingMove = selBlock;
            return;
        }
    
        self.StepListOpen = [NSMutableArray array];
        self.StepListClosed = [NSMutableArray array];
        self.shortestPath = nil;
    
        tileMap *fromTile = self.parentBlock;
        tileMap *toTile = selBlock;
    
        [self addToOpenSteps:[[ShortestPathStep alloc] initWithBlock:fromTile]];
    
        do {
    
            ShortestPathStep *currentStep = [self.StepListOpen objectAtIndex:0];
            [self.StepListClosed addObject:currentStep.theBlock];
            [self.StepListOpen removeObjectAtIndex:0];
    
            if (CGPointEqualToPoint(currentStep.theBlock.position, toTile.position)) {
                pathFound = YES;
                [self constructPathAndMove:currentStep];
                self.StepListOpen = nil;
                self.StepListClosed = nil;
                break;
            }
    
            NSArray *adjSteps = [_scene nearbyBlocks:currentStep.theBlock];
    
            for (tileMap *v in adjSteps) {
                ShortestPathStep *step = [[ShortestPathStep alloc] initWithBlock:v];
                if ([self.StepListClosed containsObject:step.theBlock]) {
                    continue;
                }
    
                int moveCost = [self costToMove:currentStep toAdjacentStep:step];
                NSUInteger index = [self.StepListOpen indexOfObject:step.theBlock];
    
                if (index == NSNotFound) {
                    step.parent = currentStep;
                    step.gScore = currentStep.gScore + moveCost;
                    CGPoint fromBlock = CGPointMake([[step.theBlock.name substringWithRange:NSMakeRange(6,1)] floatValue], [[step.theBlock.name substringWithRange:NSMakeRange(8,1)] floatValue]);
                    CGPoint toBlock = CGPointMake([[toTile.name substringWithRange:NSMakeRange(6,1)] floatValue], [[toTile.name substringWithRange:NSMakeRange(8,1)] floatValue]);
                    step.hScore = [self computeHscore:fromBlock toCoord:toBlock];
                    [self addToOpenSteps:step];
                } else {
                    step = [self.StepListOpen objectAtIndex:index];
                    if ((currentStep.gScore + moveCost) < step.gScore) {
                        step.gScore = currentStep.gScore + moveCost;
                        [self.StepListOpen removeObjectAtIndex:index];
                        [self addToOpenSteps:step];
                    }
                }
            }
        } while ([self.StepListOpen count] > 0);
    
        if (!pathFound) {
           NSLog(@"No path found.");
        }
    }
    

    如果找到它调用的路径

    - (void)constructPathAndMove:(ShortestPathStep *)step {
        self.shortestPath = [NSMutableArray array];
        do {
            if (step.parent != nil) {
                [self.shortestPath insertObject:step atIndex:0];
            }
            step = step.parent;
        } while (step != nil);
    
        [self popStepAndAnimate];
    }
    

    现在我们转到popStepAndAnimate,这是一遍又一遍地调用的方法,直到char到达目的地为止。

    -(void)popStepAndAnimate {
    
        self.currentStepAction = nil;
    
        if (self.pendingMove != nil) {
            tileMap *moveTarget = pendingMove;
            self.pendingMove = nil;
            self.shortestPath = nil;
            [self moveToward:moveTarget];
            return;
        }
    
        if (self.shortestPath == nil) {
            return;
        }
    
    
        // WE HAVE REACHED OUR BLOCK! CHECK IF ITS CLICKED OR STROLLING
        if ([self.shortestPath count] == 0) {
            self.shortestPath = nil;
            return;
        }
    
        ShortestPathStep *s = [self.shortestPath objectAtIndex:0];
    
        CGPoint futurePosition = s.theBlock.position;
        CGPoint currentPosition = self.parentBlock.position;
        CGPoint diff = ccpSub(futurePosition, currentPosition);
    
        if (abs(diff.x) > abs(diff.y)) {
            if (diff.x > 0) { [self runAnimation:_faceRight speed:0.1]; } else { [self runAnimation:_faceLeft speed:0.1]; }
        } else {
            if (diff.y > 0) { [self runAnimation:_faceUp speed:0.2]; } else { [self runAnimation:_faceDown speed:0.2]; }
        }
    
        self.parentBlock = s.theBlock;
    
        SKAction *moveAction = [SKAction moveTo:s.theBlock.position duration:0.7];
        SKAction *callbackAction = [SKAction runBlock:^{ [self popStepAndAnimate]; }];
        self.currentStepAction = [SKAction sequence:@[moveAction, callbackAction]];
        [self.shortestPath removeObjectAtIndex:0];
        [self runAction:currentStepAction];
    }
    

0 个答案:

没有答案