【AI】A star(A 星)算法在手机游戏开发中的使用

写了一个项目用到两套AI,其中一套从思路构建到实现全部由自己实现,没有参考任何资料,这个暂且不提,因为不具有广泛性,另外一套用到了A star算法,并加以修改。修改后的算法可以解决1,2,3,...,n个格子单位的位置移动问题,现在把核心代码贴出来,供参考交流
-(void)aStarBegining:(CGPoint)_startPoint{
    allNodes = [[NSMutableArray alloc]init];
    for (int i=0; i<32; i++) {
        for (int j=0; j<18; j++) {
            PathfindingNode *node = [[PathfindingNode alloc] initWithPosition:ccp(i, j)];
            [allNodes addObject:node];
        }
    }
    [self setStartCell:_startPoint];
}
- (void)setStartCell:(CGPoint)_startPoint{
    _start = [[PathfindingNode alloc] initWithPosition:_startPoint];
}
- (BOOL)findPathFromStartNode:(PathfindingNode *)startNode toTargetNode:(PathfindingNode *)targetNode {
    NSMutableSet *openSet = [NSMutableSet new];
    NSMutableSet *closedSet = [NSMutableSet new];
    
    startNode.g = 0;
    startNode.h = [self calculateManhattanDistanceBetweenStartNode:startNode targetNode:targetNode];
    startNode.f = startNode.g + startNode.h;
    [openSet addObject:startNode];
    
    while ([openSet count] > 0) {
        PathfindingNode *node = [self lowestFScoreNodeInSet:openSet];
        if ([self node:node isEqualToNode:targetNode]) {
            isHavePath=YES;
            [self reversePathFromNode:targetNode];
            
            return YES;
        }
        else{
            isHavePath=NO;
        }
        
        [openSet removeObject:node];
        [closedSet addObject:node];
        for (PathfindingNode *adjacent in [self findAdjacentSquares:node]) {
            if ([closedSet containsObject:adjacent]) {
                continue;
            }
            int g = node.g + 1;
            BOOL isBetter;
            if (![openSet containsObject:adjacent]) {
                [openSet addObject:adjacent];
                
                isBetter = YES;
            } else if (g < adjacent.g) {
                isBetter = YES;
            } else {
                isBetter = NO;
            }
            
            if (isBetter == YES) {
                adjacent.parentNode = node;
                adjacent.g = g;
                adjacent.h = [self calculateManhattanDistanceBetweenStartNode:adjacent targetNode:targetNode];
                adjacent.f = adjacent.g + adjacent.h;
            }
        }
    }
    return NO;
}

- (void)reversePathFromNode:(PathfindingNode *)endNode {
    for (int i=0; i<50; i++) {
        if ([self getChildByTag:2000+i]) {
            [self removeChildByTag:2000+i cleanup:YES];
        }
    }
    NSMutableArray *finalPath = [NSMutableArray new];
    PathfindingNode *node = endNode;
    int i=0;
    do {
      //  CCLOG(@"X: %i, Y: %i", node.x, node.y);
        CCSprite *roadSp=[CCSprite spriteWithFile:@"bt.png"];
        roadSp.position=ccp(node.x*32+16, node.y*32+16);
        roadSp.color=ccc3(0, 255, 0);
        [self addChild:roadSp z:5 tag:2000+(++i)];
        [finalPath addObject:node];
        node = node.parentNode;
    } while (node.parentNode != nil);
    _pathPointArray=finalPath;
}

- (int)calculateManhattanDistanceBetweenStartNode:(PathfindingNode *)currentNode targetNode:(PathfindingNode *)targetNode {
    int x1 = currentNode.x;
    int x0 = targetNode.x;
    int y1 = currentNode.y;
    int y0 = targetNode.y;
    int distance = abs(x1-x0) + abs(y1-y0);
    return distance;
}

- (PathfindingNode *)lowestFScoreNodeInSet:(NSMutableSet *)set {
    PathfindingNode *lowestScoreNode = [set anyObject];
    for (PathfindingNode *node in [set allObjects]) {
        if (node.f < lowestScoreNode.f) {
            lowestScoreNode = node;
        }
    }
    
    return lowestScoreNode;
}

- (BOOL)node:(PathfindingNode *)node1 isEqualToNode:(PathfindingNode *)node2 {
    if (node1.x == node2.x && node1.y == node2.y) {
        return YES;
    }
    return NO;
}

- (NSArray *)findAdjacentSquares:(PathfindingNode *)node {
    NSMutableArray *squares = @[].mutableCopy;
    
    for (PathfindingNode *n in self.allNodes) {
        if (n.x == node.x-1 && n.y == node.y) {
            if (selSprite) {
                moveUpdatePoint.x=[self tileCoordForPosition:selSprite.position].x;
                moveUpdatePoint.y=[self tileCoordForPosition:selSprite.position].y;
                if ((map32Pix[n.x][n.y]==-1)&&!((moveUpdatePoint.x==n.x)&&(moveUpdatePoint.y==n.y))) {
                    [squares addObject:n];
                }
            }
            else
            {
                int AILoop=2;
                int allPointCnt=0;
                for (int i=0; i<AILoop; i++) {
                    if (map32Pix[n.x][n.y-i]==-1) {
                        allPointCnt++;
                    }
                }
                if (allPointCnt==AILoop) {
                    [squares addObject:n];
                }
            }
        }
        if (n.x == node.x+1 && n.y == node.y) {
            if (selSprite) {
                moveUpdatePoint.x=[self tileCoordForPosition:selSprite.position].x;
                moveUpdatePoint.y=[self tileCoordForPosition:selSprite.position].y;
                if ((map32Pix[n.x][n.y]==-1)&&!((moveUpdatePoint.x==n.x)&&(moveUpdatePoint.y==n.y))) {
                    [squares addObject:n];
                }
            }
            else
            {
                int AILoop=2;
                int allPointCnt=0;
                for (int i=0; i<AILoop; i++) {
                    if (map32Pix[n.x+1][n.y-i]==-1) {
                        allPointCnt++;
                    }
                }
                if (allPointCnt==AILoop) {
                    [squares addObject:n];
                }
            }
        }
        if (n.y == node.y-1 && n.x == node.x) {
            if (selSprite) {
                moveUpdatePoint.x=[self tileCoordForPosition:selSprite.position].x;
                moveUpdatePoint.y=[self tileCoordForPosition:selSprite.position].y;
                if ((map32Pix[n.x][n.y]==-1)&&!((moveUpdatePoint.x==n.x)&&(moveUpdatePoint.y==n.y))) {
                    [squares addObject:n];
                }
            }
            else
            {
                int AILoop=2;
                int allPointCnt=0;
                for (int i=0; i<AILoop; i++) {
                    if (map32Pix[n.x+i][n.y-1]==-1) {
                        allPointCnt++;
                    }
                }
                if (allPointCnt==AILoop) {
                    [squares addObject:n];
                }
            }
        }
        if (n.y == node.y+1 && n.x == node.x) {
            if (selSprite) {
                moveUpdatePoint.x=[self tileCoordForPosition:selSprite.position].x;
                moveUpdatePoint.y=[self tileCoordForPosition:selSprite.position].y;
                if ((map32Pix[n.x][n.y]==-1)&&!((moveUpdatePoint.x==n.x)&&(moveUpdatePoint.y==n.y))) {
                    [squares addObject:n];
                }
            }
            else
            {
                int AILoop=2;
                int allPointCnt=0;
                for (int i=0; i<AILoop; i++) {
                    if (map32Pix[n.x+i][n.y]==-1) {
                        allPointCnt++;
                    }
                }
                if (allPointCnt==AILoop) {
                    [squares addObject:n];
                    
                }
            }
        }

    }
    return squares.copy;
}
需要注意的是,我没有把走斜线的方法贴出来,因为我在调试过程中,发现把走斜线的算法加入进去之后,玩家的从视觉上体验的效果不好,希望有心人提出想法,当然如果需要我也可以提供斜线的走法,看起来更智能
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值