Вот мой вопрос:
- Как преобразовать
SKSpriteNode
массив в массивGKObstacles
, чтобы агент мог должным образом обходить эти препятствия с помощьюgoalToAvoidObstacles:(nonnull NSArray<GKObstacle *> *) maxPredictionTime:(NSTimeInterval)
/?
Кажется, что способ, которым я создаю массив GKObstacle
, не позволяет GKGoal
правильно идентифицировать их как препятствия, независимо от того, какой вес я придаю цели.
В настоящее время у меня есть несколько SKNode
, которые добавлены в SKScene
chapterScene. Каждый из этих узлов добавляется в сохраняемый мной массив под названием obstaclesArray. Я настроил тест следующим образом, который работает довольно хорошо:
ПРЕПЯТСТВИЯ ДЛЯ РАБОТЫ
- (void)didMoveToView:(nonnull SKView *)view {
[super didMoveToView:view];
// Add three obstacles in a triangle formation around the center of the scene.
NSArray<GKObstacle *> *obstacles = @[
[self addObstacleAtPoint:CGPointMake(CGRectGetMidX(self.frame),
CGRectGetMidY(self.frame) + 150)],
[self addObstacleAtPoint:CGPointMake(CGRectGetMidX(self.frame) - 200,
CGRectGetMidY(self.frame) - 150)],
[self addObstacleAtPoint:CGPointMake(CGRectGetMidX(self.frame) + 200,
CGRectGetMidY(self.frame) - 150)],
];
// The player agent follows the tracking agent.
self.player = [[OPlayer alloc] initWithScene:self
radius:50
position:CGPointMake(CGRectGetMidX(self.frame),
CGRectGetMidY(self.frame))];
self.player.agent.behavior = [[GKBehavior alloc] init];
[self.agentSystem addComponent:self.player.agent];
// Create the seek goal, but add it to the behavior only in -setSeeking:.
self.seekGoal = [GKGoal goalToSeekAgent:self.character];
// Add an avoid-obstacles goal with a high weight to keep the agent from overlapping the obstacles.
[self.player.agent.behavior setWeight:100 forGoal:[GKGoal goalToAvoidObstacles:obstacles maxPredictionTime:1]];
}
- (GKObstacle *)addObstacleAtPoint:(CGPoint)point {
SKShapeNode *circleShape = [SKShapeNode shapeNodeWithCircleOfRadius:50];
circleShape.lineWidth = 2.5;
circleShape.fillColor = [SKColor grayColor];
circleShape.strokeColor = [SKColor redColor];
circleShape.zPosition = 1;
circleShape.position = point;
[self addChild:circleShape];
GKCircleObstacle *obstacle = [GKCircleObstacle obstacleWithRadius:50];
obstacle.position = (vector_float2){point.x, point.y};
return obstacle;
}
Хотя это работает просто отлично, проблема, с которой я сталкиваюсь, заключается в том, что я не могу заставить поведение идентифицировать массив SKNode
тел, который у меня есть как препятствия. Я могу только заставить эти созданные вручную GKCircleObstacle
элементов регистрироваться как действительные препятствия, которых агент избегает. Причина, по которой это проблема, заключается в том, что я полагаюсь на множество препятствий, которые на самом деле не являются простыми кругами, а представляют собой многоугольные структуры, некоторые сложные, некоторые более простые. Тем не менее, я пытался сделать следующее, но мой агент, похоже, не избежал ни одного из препятствий, SKNode
таким образом:
НЕ РАБОТАЮЩИЕ ПРЕПЯТСТВИЯ
NSArray *obstacles = [SKNode obstaclesFromNodePhysicsBodies:obstaclesArray];
/*
The other code seen above
*/
// Add an avoid-obstacles goal with a high weight to keep the agent from overlapping the obstacles.
[self.player.agent.behavior setWeight:100 forGoal:[GKGoal goalToAvoidObstacles:obstacles maxPredictionTime:1]];
К сожалению, похоже, это не работает, так как независимо от того, насколько высок я устанавливаю вес, агент никогда не реагирует на избегание препятствий. Вот журнал массива, который я передаю ему:
2016-07-24 22:32:24.907 <GAME>[1516:475581] obstacles: (
"<GKPolygonObstacle: 0x14d20d70>",
"<GKPolygonObstacle: 0x14d20e10>",
"<GKPolygonObstacle: 0x14d20ba0>",
"<GKPolygonObstacle: 0x14d20bb0>",
"<GKPolygonObstacle: 0x14d20bc0>",
"<GKPolygonObstacle: 0x14d20a60>",
"<GKPolygonObstacle: 0x14d208b0>",
"<GKPolygonObstacle: 0x14d207d0>",
"<GKPolygonObstacle: 0x14d20a70>"
)
Каждый из них был четко и правильно инициализирован и добавлен в сцену. Каждый из этих элементов на самом деле реагирует с помощью метода SpriteKit
didBeginContact:(SKPhysicsContact *)contact
, поэтому кажется, что узлы правильно обрабатывают границы, которые у них должны быть.
Если кто-то знает, что я делаю неправильно, или лучший способ превратить каждый из этих «узлов препятствий» в GKObstacle
, я был бы очень признателен. Заранее спасибо!
ОБНОВЛЕНИЕ: Вот узел с физическим телом, которое я тестирую:
SKSpriteNode *innerMap1 = [SKSpriteNode spriteNodeWithImageNamed:@"test"];
innerMap1.physicsBody = [SKPhysicsBody bodyWithTexture:[SKTexture textureWithImageNamed:@"test"] size:CGSizeMake(innerMap1.frame.size.width*0.92, innerMap1.frame.size.height*0.92)];
innerMap1.position = CGPointMake(-220, -140);
innerMap1.physicsBody.dynamic = NO;
[chapterSKSpriteNodes addObject:innerMap1];
Вот как выглядит тело с skView.showsPhysics = YES;
:
Так что я знаю, что физическое тело — это то, что мне нужно. Однако, когда я пытаюсь создать GKObstacle
из этого тела, оно, кажется, не регистрируется как препятствие при назначении в цели избежать препятствий.
obstaclesFromNodePhysicsBodies
, чтобы увидеть, есть ли у высоких узлов в массиве тела? - person Knight0fDragon   schedule 25.07.2016for (SKNode *node in obstaclesArray) { if (node.physicsBody) { NSLog(@"exists"); }}
и получил их все - person Will Von Ullrich   schedule 25.07.2016