2016-02-04 51 views
5

Utworzono SKSpriteNode o nazwie powiedzmy Mapa, która ma zdefiniowaną ścieżkę krawędzi (prosty kształt wielokąta).SpriteKit SKPhysicsBody z wewnętrznymi krawędziami

Co Próbuję dowiedzieć się, jak dodać kilka inne ścieżki brzegowych, które działają jako wewnętrznych krawędziach mapą. Tak jakby "mapa" jako całość miała w rzeczywistości otwory. Jakiś wewnętrznych kształtach brzegowych, które mogą działać mapą jako całości jednej ścieżki krawędzi (jak pokazano poniżej)

enter image description here ©

I rozumie, że istnieje metoda, która pozwala na utworzenie SKPhysicsBody z ciał (niektóre NSArray), takich jak taki

Czy ta metoda faktycznie generuje to, co pokazałem na obrazie? Zakładając, że bodiesArray zawiera 3 SKSpriteNode jest każdy z określonej drogi z użyciem takiego sposobu:

+ (SKPhysicsBody *)bodyWithEdgeChainFromPath:(CGPathRef)path 

, z utworzeniem ścieżki podobne takie

 SKSpriteNode *innerNode1 = [SKSpriteNode spriteNodeWithImageNamed:@"map"]; 

     CGMutablePathRef innerNode1Path = CGPathCreateMutable(); 

     CGPathMoveToPoint(mapPath, NULL, 1110, 1110); 
     CGPathAddLineToPoint(mapPath, NULL, <some x1>, <some y1>); 
     CGPathAddLineToPoint(mapPath, NULL, <some x2>, <some y2>); 
     CGPathAddLineToPoint(mapPath, NULL, <some x3>, <some y3>); 
     . 
     . 
     . 
     CGPathCloseSubpath(mapPath); 

     innerNode1.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:innerNode1Path]; 
     [bodiesArray addObject:innerNode1]; 

     // Repeat for other 2 nodes 

I zrozumieć, że alternatywą byłoby utworzyć 3 oddzielne węzły z lokalizacją i kształtem zamierzonych "dziur", ale łączę się, aby uniknąć tworzenia większej liczby węzłów niż potrzebuję. Jeśli ktokolwiek może potwierdzić, co próbuję zrobić, jest poprawny, lub może zaproponować alternatywę, której nie jestem świadomy.

UWAGA: czy to, co robię jest poprawne, ale brakuje mi czegoś, byłbym wdzięczny, jeśli ktoś może mi pokazać właściwą drogę do tego, co próbuję zrobić (nawet prosty przykład kwadratu o wewnętrzny mniejszy kwadrat byłby świetny). Dzięki!

EDYCJA 1: Poniżej znajduje się fragment kodu, którego używam jako próbę utworzenia "wewnętrznych granic". W tym przypadku problem polega na tym, że podczas rysowania zarówno zewnętrznego, jak i wewnętrznego prostokąta, gdy dodaję wewnętrzny rect do mapy bodyWithBodies, uzyskuje on pełną kontrolę nad wykrywaniem kolizji, usuwając wszystkie kontrole kontaktowe z zewnętrznej prostokątnej powłoki. Kiedy usunąć bodyWithBodies wraca do normy z pokazując oba prostokąty, zewnętrzna posiada detekcję kolizji (nie pozwala mi przejść), podczas gdy wewnętrzna jeden ma nic ... tak blisko

// 1 Create large outer shell Map 
CGRect mapWithRect = CGRectMake(map.frame.origin.x + offsetX, map.frame.origin.y + offsetY, map.frame.size.width * shrinkage, map.frame.size.height * shrinkage); 

self.physicsWorld.gravity = CGVectorMake(0.0, 0.0); 
self.physicsWorld.contactDelegate = self; 

// 2 Create smaller inner boundary 
CGRect innerRect = CGRectMake(100, 100, 300, 300); 
SKPhysicsBody *body = [SKPhysicsBody bodyWithEdgeLoopFromRect:innerRect]; 
body.categoryBitMask = wallCategory; 
NSArray *bodyArray = [NSArray arrayWithObject:body]; 

// 3 Add bodies to main Map body 
myWorld.physicsBody = [SKPhysicsBody bodyWithBodies:bodyArray]; 
myWorld.physicsBody.categoryBitMask = wallCategory; 


if ([[levelDict objectForKey:@"DebugBorder"] boolValue] == YES) { 
    // This will draw the boundaries for visual reference during testing  
    [self debugPath:mapWithRect]; 
    [self debugPath:innerRect]; 
} 

EDIT 2 podejście works..by tylko dodanie nowego węzła z takich samych właściwościach jak zewnętrzna rect:

SKPhysicsBody *innerRectBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:innerRect]; 
innerRectBody.collisionBitMask = playerCategory; 
innerRectBody.categoryBitMask = wallCategory; 
SKNode *innerBoundary = [SKNode node]; 
innerBoundary.physicsBody = innerRectBody; 
[myWorld addChild: innerBoundary]; 

... ale bardzo chciałbym czystsze rozwiązanie, które nie wymaga dodatkowych węzłów I .. myśli?

+0

To może być to, czego szukasz https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKPhysicsBody_Ref/#//apple_ref/occ/clm/SKPhysicsBody/bodyWithTexture: alphaThreshold: size: – 0x141E

+0

W mojej edycji pokazałem, co zrobiłem, ale (jak wyjaśniono) nie całkiem. Wiem, że mogę utworzyć oddzielny "węzeł", który może naśladować wydajność większej zewnętrznej powłoki, ale znowu, staram się tylko uniknąć większego obciążenia procesora. Pomyślałem, że coś takiego powinno być możliwe, biorąc pod uwagę zakres użyteczności Apples z SpriteKit .. :( –

+0

ponownie sprawdź swoje maski kolizyjne i kontaktowe – dragoneye

Odpowiedz

1

robisz nic złego tu przyjść na przykładzie gdzie stworzyłem dwa ciała krawędź rect z dwóch fizycznych ciał

// dodanie ciała po pewnym czasie korzystania GCD

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
     [self addBodyA]; 
    }); 

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
     [self addBodyB]; 
    }); 
-(void)addBodyB 
{ 
    SKSpriteNode *node=[SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(20, 20)]; 
    node.physicsBody=[SKPhysicsBody bodyWithRectangleOfSize:node.frame.size]; 
    node.position=CGPointMake(550, 420); 
    node.physicsBody.restitution=1; 
    [self addChild:node]; 

} 
-(void)addBodyA 
{ 
    SKSpriteNode *node=[SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(20, 20)]; 
    node.physicsBody=[SKPhysicsBody bodyWithRectangleOfSize:node.frame.size]; 
    node.position=CGPointMake(400, 420); 
    node.physicsBody.restitution=1; 
    [self addChild:node]; 

} 
-(void)addEdgesBodies 
{ 
    SKAction *r=[SKAction rotateByAngle:1.0/60 duration:1.0/60]; 

    SKSpriteNode *rect=[SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:CGSizeMake(300,300)]; 
    rect.physicsBody=[SKPhysicsBody bodyWithEdgeLoopFromRect:rect.frame]; 
    rect.position=CGPointMake(500, 400); 
    [self addChild:rect]; 


    // 
    SKSpriteNode *rect1=[SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:CGSizeMake(100,100)]; 
    rect1.physicsBody=[SKPhysicsBody bodyWithEdgeLoopFromRect:rect1.frame]; 
    rect1.position=CGPointMake(550, 450); 
    [self addChild:rect1]; 


    [rect1 runAction:[SKAction repeatActionForever:r]]; 

} 
[self addEdgesBodies]; 

pamiętać ciał krawędziowe pochodzi z niskim obciążeniem procesora, więc nie przejmuj się wydajnością, dopóki twój wielokąt nie ma tak wielu krawędzi.

+0

dziękuję za pomoc - doceniam to, więc to podejście faktycznie osiągnie wewnętrzne interaktywne * warunki brzegowe (jak pokazano na zdjęciu)? to właśnie utworzyłem tę okoliczność wizualnie –

+0

Stworzyłem duży prostokąt z mniejszym wewnętrznym prostokątem, ale teraz wydaje się, że wewnętrzny rect jest jedynym obszarem, który przyjmuje warunki brzegowe, podczas gdy ja mogę teraz przejść przez zewnętrzne rect. bodyWithBodies (mój kod jest powyżej w edycji do mojej odpowiedzi) –

0

Twój kod do tworzenia ścieżki, a następnie używania go w fizyce wygląda tak, jakby działał. Jak również twoje ciało fizyczne z ciał. Niestety nie wiem, czy SKPhysicsBody może naprawdę wspierać dziury, ponieważ nie można odwrócić normalnych ciał. Sposób, w jaki czytam dokumentację jabłka, polega na tym, że ma on na celu zrobienie dwóch kształtów koła i uczynienie ich jednym ciałem, a następnie stworzenie takiego złożonego kształtu. Problem polegał na tym, że posiadanie otworu wewnątrz większego kształtu oznaczałoby ignorowanie kolizji w tym obszarze.

Oto kilka alternatywnych opcji

Jedna opcja to można zbudować swoje etapy od wielu kształtach. Na przykład, jeśli złamiesz mapę na dwie części (z linią przechodzącą przez każdy kształt) i stworzysz dla niej ciała fizyczne. Następnie niech się pokrywają i przekształcają je w jedno ciało. Zrobiłem diagram pokazujący to (wybacz jej straszną jakość, powinieneś być w stanie zrozumieć, co robi (mam nadzieję)). enter image description here

Inną opcją jest wykonanie z teksturą, może to trochę zaszkodzić wykonaniu, ale jeśli potrafisz nim zarządzać, prawdopodobnie będzie dobrze działać.

Map.physicsBody = SKPhysicsBody(texture: Map.texture, size: Map.size) 
+0

Niestety jestem w absolutnej potrzebie niezależnych organów w ramach głównej granicy. Rozważyłem to jednak, ponieważ byłoby to dziełem dookoła, jeśli nie mogę wymyślić czystej metody osiągnięcia tego, czego potrzebuję :) –