我正在开发一个Gameplaykit路径寻找概念验证,我无法让GKObstacleGraph正确地找到路径。
在下面的代码片段中(它应该在Xcode 7.2操场中工作),如果在创建图形时提供了障碍物,则path2始终为空数组。如果我使用空数组障碍创建obGraph对象,则findPathFromNode将返回正确的路径。
创建的障碍物应该是一个简单的U形多边形,其终点位于U内。
import UIKit
import GameplayKit
let pts = [vector_float2(2,2),
vector_float2(3,2),
vector_float2(3,6),
vector_float2(7,6),
vector_float2(7,2),
vector_float2(8,3),
vector_float2(8,7),
vector_float2(2,7),
vector_float2(2,2)]
let obstacle1 = GKPolygonObstacle(points: UnsafeMutablePointer(pts) ,
count: pts.count)
let obGraph = GKObstacleGraph(obstacles: [obstacle1], bufferRadius: 0)
let startPt = GKGraphNode2D(point: vector_float2(5,9))
let endPt = GKGraphNode2D(point: vector_float2(5,5))
let pt3 = GKGraphNode2D(point: vector_float2(0,0))
let pt4 = GKGraphNode2D(point: vector_float2(0,9))
let pt5 = GKGraphNode2D(point: vector_float2(5,0))
let pt6 = GKGraphNode2D(point: vector_float2(10,0))
obGraph.connectNodeUsingObstacles(startPt)
obGraph.connectNodeUsingObstacles(endPt)
obGraph.connectNodeUsingObstacles(pt3)
obGraph.connectNodeUsingObstacles(pt4)
obGraph.connectNodeUsingObstacles(pt5)
obGraph.connectNodeUsingObstacles(pt6)
startPt.connectedNodes
endPt.connectedNodes
pt3.connectedNodes
let path2 = obGraph.findPathFromNode(startPt, toNode: endPt)
print(path2)
答案 0 :(得分:1)
(提前抱歉obj-c不迅捷)
我的印象是,不必将每个顶点添加为连接,只需告诉GKObstacleGraph
关于GKPolygonObstacle
就足以避免生成的polgyon形状。我已经使用了以下内容并收到了3个节点来创建一条围绕我的障碍物(缓冲区为10.0f)的路径:
- (void)findPathWithNode:(SKNode *)nodeToFindPath {
NSMutableArray *obstaclesToAvoid = [NSMutableArray array];
for (SKNode *objectInScene in chapterScene.children) {
if ([objectInScene.name isEqualToString:@"innerMapBoundary"]) {
[obstaclesToAvoid addObject:objectInScene];
}
}
/* FYI: The objectInScene is just a black SKSpriteNode with a
square physics body 100 x 100 rotated at 45°
*/
NSArray *obstacles = [SKNode obstaclesFromNodePhysicsBodies:[NSArray arrayWithArray:obstaclesToAvoid]];
GKObstacleGraph *graph = [GKObstacleGraph graphWithObstacles:obstacles bufferRadius:10.0f];
GKGraphNode2D *end = [GKGraphNode2D nodeWithPoint:vector2((float)character.position.x, (float)character.position.y)];
GKGraphNode2D *start = [GKGraphNode2D nodeWithPoint:vector2((float)nodeToFindPath.position.x, (float)nodeToFindPath.position.y)];
[graph connectNodeUsingObstacles:end];
[graph connectNodeUsingObstacles:start];
NSArray *pathPointsFound = [graph findPathFromNode:enemy toNode:target];
NSLog(@"Path: %@", pathPointsFound);
GKPath *pathFound;
// Make sure that there were at least 2 points found before creating the path
if (pathPointsFound.count > 1) {
for (GKGraphNode2D *nodeFound in pathPointsFound) {
// This is just to create a visual for the points found
vector_float2 v = (vector_float2){(float)nodeFound.position.x, (float)nodeFound.position.y};
CGPoint p = CGPointMake(v.x, v.y);
SKShapeNode *shapetoadd = [SKShapeNode shapeNodeWithCircleOfRadius:4];
shapetoadd.name = @"shapeadded";
shapetoadd.fillColor = [UIColor redColor];
shapetoadd.position = p;
[chapterScene addChild:shapetoadd];
}
pathFound = [GKPath pathWithGraphNodes:pathPointsFound radius:10.0];
}
}
希望这能指引你朝着正确的方向前进!
答案 1 :(得分:1)
我和杰克有同样的问题。我从Will的代码示例开始,然后将其翻译为Xcode 10.3中的Swift 5.0。我将其添加到Xcode的 Game 项目模板中。我仍然得到了相同的结果:findPath(from:to:)
中的一个空数组。
在研究了代码之后,我意识到与物理相关的任何事物都会影响路径。显示适用于所有人的代码的唯一方法是包括创建SKScene
和所有SKNode
实例。请注意,我在gravity
中将SKPhysicsWorld
设置为0,并且没有向任何内容添加SKPhysicsBody
。
在游乐场中运行。您可以通过点击场景中的任意位置来激活动画。
import PlaygroundSupport
import SpriteKit
import GameKit
class GameScene: SKScene {
let nodeToMove:SKShapeNode = {
let n = SKShapeNode(circleOfRadius: 10)
n.lineWidth = 2
n.strokeColor = UIColor.orange
n.position = CGPoint(x: -200, y: 150)
return n
}()
override func sceneDidLoad() {
addChild(nodeToMove)
let nodeToFind = SKShapeNode(circleOfRadius: 5)
nodeToFind.lineWidth = 2
nodeToFind.strokeColor = UIColor.red
addChild(nodeToFind)
nodeToFind.position = CGPoint(x: 200, y: -150)
let nodeToAvoid = SKShapeNode(rectOf: CGSize(width: 100, height: 100))
nodeToAvoid.lineWidth = 4
nodeToAvoid.strokeColor = UIColor.blue
addChild(nodeToAvoid)
nodeToAvoid.position = CGPoint.zero
let polygonObstacles = SKNode.obstacles(fromNodeBounds: [nodeToAvoid])
let graph = GKObstacleGraph(obstacles: polygonObstacles, bufferRadius: 10.0)
let end = GKGraphNode2D(point: vector2(Float(nodeToMove.position.x), Float(nodeToMove.position.y)))
let start = GKGraphNode2D(point: vector2(Float(nodeToFind.position.x), Float(nodeToFind.position.y)))
graph.connectUsingObstacles(node: end)
graph.connectUsingObstacles(node: start)
graphNodes = graph.findPath(from: end, to: start) as! [GKGraphNode2D]
print("graphNodes = \(graphNodes)")
}
var graphNodes = [GKGraphNode2D]()
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
touches.first.flatMap {_ in
let newActions: [SKAction] = graphNodes.map { n in
return SKAction.move(to: CGPoint(x: CGFloat(n.position.x), y: CGFloat(n.position.y)), duration: 2)
}
nodeToMove.run(SKAction.sequence(newActions))
}
}
}
let sceneView = SKView(frame: CGRect(x:0 , y:0, width: 640, height: 480))
let scene = GameScene(size: CGSize(width: 640, height: 480))
scene.scaleMode = .aspectFill
scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
scene.backgroundColor = UIColor.purple
scene.physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)
sceneView.presentScene(scene)
PlaygroundSupport.PlaygroundPage.current.liveView = sceneView
控制台中的输出为:
graphNodes = [GKGraphNode2D: {-200.00, 150.00}, GKGraphNode2D: {62.85, 62.85}, GKGraphNode2D: {200.00, -150.00}]
开始状态:
结束状态:
警告::我不知道为什么在用户轻按和动画开始之间会花费整整一秒钟的时间。性能调整是一个单独的主题。