2015-10-14 13 views
7

W iOS 9 Apple wprowadziło collisionBoundsType do UIKit-Dynamics.Ustawianie ścieżki granicznej kolizji w UIView w iOS 9

Nie mam problemu podczas ustawiania tego UIDynamicItemCollisionBoundsTypeRectangle lub gdy ustawię to na UIDynamicItemCollisionBoundsTypeEllipse.

Poniższy zrzut ekranu jest z gry Robię gdzie collisionBoundsType odtwarzacza jest ustawiony na prostokąt i piłka jest ustawiona na elipsy:

enter image description here

Jednakże kiedy ustawić odtwarzacz na collisionBoundsType do ścieżka otrzymuję dziwne zachowanie jak widać tutaj:

enter image description here

widok pojawia się wyższy niż powinien, a ciało jest kolizja w prawo gdzie powinien być.

Obecnie mam collisionBoundingPath zestaw do tego:

- (UIBezierPath *)collisionBoundingPath 
{ 
    maskPath = [[UIBezierPath alloc] init]; 
    [maskPath addArcWithCenter:CGPointMake(SLIME_SIZE, SLIME_SIZE) radius:SLIME_SIZE startAngle:0*M_PI endAngle:M_PI clockwise:NO]; 
    return maskPath; 
} 

Dodatkowo, moja funkcja drawRect wygląda tak:

- (void) drawRect:(CGRect)rect 
{ 
    if (!_color){ 
    [self returnDefualtColor]; 
    } 
    if (!maskPath) maskPath = [[UIBezierPath alloc] init]; 
    [maskPath addArcWithCenter:CGPointMake(SLIME_SIZE, SLIME_SIZE) radius:SLIME_SIZE startAngle:0*M_PI endAngle:M_PI clockwise:NO]; 
    [_color setFill]; 
    [maskPath fill]; 
} 

Dlaczego tak się dzieje? Jak ustawić ścieżkę ciała kolizji tak, aby była taka sama jak rysunek w widoku?

Dodatkowo czerwony to tylko tło widoku (tj. view.backgroundColor = [UIColor redColor];).

+0

Nie jest ekspertem od rysowania, ale dokumentacja sugeruje, że ścieżka powinna być wielokątem.Twój kod dodaje łuk, ale nie zamyka ścieżki. Być może powinieneś wywołać '[maskPath closePath]', aby stworzyć zamkniętą ścieżkę, która może zrobić różnicę? –

+0

Zamyka się automatycznie – WMios

+0

Aby wypełnić "drawRect", tak będzie. Czy jesteś pewien, że twoja 'collisionBoundingPath'? Gdzie jest napisane w dokumentach, że zamyka ścieżkę? –

Odpowiedz

2

Z dokumentacji na UIDynamicItem here następujące oświadczenie o układzie współrzędnych dla ścieżek wydaje się reprezentować co jest nie tak:

Przedmiotem ścieżka utworzyć musi reprezentować wypukłego wielokąta z licznika -w lewo lub w prawo, a ścieżka nie może przecinać się sama. Punkt (0, 0) ścieżki musi znajdować się w środkowym punkcie odpowiedniego dynamicznego elementu. Jeśli punkt centralny nie jest zgodny z punktem początkowym ścieżki, zachowania kolizyjne mogą nie działać tak, jak się oczekuje.

Tutaj stwierdza, że ​​(0,0) dla ścieżki MUSI być punktem środkowym.

Myślę, że środek twojej ścieżki łuku powinien być (0,0), a nie (SLIME_SIZE/2,SLIME_SIZE/2). Czy prawdopodobnie ustawiłeś szerokość i wysokość ramki UIView na SLIME_SIZE zamiast SLIME_SIZE*2?

SLIME_SIZE naprawdę wydaje się definiować promień, więc szerokość ramki powinna wynosić SLIME_SIZE*2. Jeśli jest ustawiony jako SLIME_SIZE, to wyjaśnia to, dlaczego musisz tłumaczyć jako SLIME_SIZE/2 jako korektę.

+0

Świetna odpowiedź, to naprawdę wyjaśniło powody, dla których moja poprawka działała. – WMios

1

byłem w stanie odpowiedzieć na to przez zmianę:

- (UIBezierPath *)collisionBoundingPath 
{ 
    maskPath = [[UIBezierPath alloc] init]; 
    [maskPath addArcWithCenter:CGPointMake(SLIME_SIZE, SLIME_SIZE) radius:SLIME_SIZE startAngle:0*M_PI endAngle:M_PI clockwise:NO]; 
    return maskPath; 
} 

do:

- (UIBezierPath *)collisionBoundingPath 
{ 
    maskPath = [[UIBezierPath alloc] init]; 
    [maskPath addArcWithCenter:CGPointMake(SLIME_SIZE/2, SLIME_SIZE/2) radius:SLIME_SIZE startAngle:0*M_PI endAngle:M_PI clockwise:NO]; 
    return maskPath; 
} 

Kluczową różnicą jest to, że zmodyfikowany środek łuku poprzez podzielenie wartości X i Y przez 2

1

Fizyka debugowania to rzecz. Prawdopodobnie nie jest to coś, o czym użytkownicy systemu iOS mają tendencję do myślenia, ponieważ zwykle robią bardzo proste rzeczy dzięki UIKit Dynamics. To wstyd, ponieważ jest to jeden z najlepszych aspektów ostatnich wydań systemu iOS i oferuje naprawdę zabawny sposób na zwiększenie satysfakcji użytkowników.

Więc ... jak debugować fizykę?

Jednym ze sposobów jest wyobrażenie sobie, co się dzieje, a następnie skorelowanie tego z tym, co się dzieje, i znalezienie dysonansu między wyobrażeniem a rzeczywistością, a następnie rozwiązanie problemu poprzez połączenie procesów eliminacji, psychicznego lub rzeczywistego procesu & błąd i odliczenie, dopóki problem nie zostanie ustalony i rozwiązany.

Innym jest wizualne przedstawienie wszystkiego, co zostało stworzone i współdziałające, przedstawiające wystarczającą informację zwrotną, aby szybciej określić charakter i zakres elementów, ich związki i incydenty/zdarzenia oraz rozwiązać problemy z dosłownym wzrokiem.

W tym celu stworzono różne debuggery wizualne i symulatory fizyki od ich wprowadzenia.

Niestety iOS nie ma takiego edytora ekranowego lub "edytora scen" dla UIKit Dynamics, a to, co jest dostępne dla tego rodzaju debugowania wizualnego w Sprite Kit i Scene Kit, jest w najlepszym wypadku szczątkowe.

Jednak istnieją CALayery, które są obecne we wszystkich widokach UIKit, do których można ręcznie utworzyć i narysować CAShapeLayers, aby dokładnie odwzorować wszystkie fizyczne elementy, ich granice i ich kotwice oraz relacje.

CAShapeLayers są "kontenerem" dla CGPaths i mogą mieć różne kolory dla konturu i wypełnienia oraz więcej niż jeden element CGPath w ramach pojedynczego obiektu CAShapeLayer.

I zacytować wielkiego Roba.

„Jeśli dodać CAShapeLayer jako warstwa do widzenia, nie masz do realizacji jakiegokolwiek kodu rysunkowego samemu wystarczy dodać CAShapeLayer i Możesz nawet później zmienić ścieżkę, a następnie automatycznie przerysuje ją dla ciebie .. CAShapeLayer wyciąga cię z chwastów pisania własnych procedur drawRect lub drawLayer. "

Jeśli masz ogromną liczbę elementów współdziałających i chcesz je debugowania, problemy z wydajnością CAShapeLayer za mogłyby wchodzić w grę, w którym momencie można użyć shouldRasterize przekonwertować każdy na bitmapę i uzyskać znaczną poprawę wydajności podczas trafiając w granice stworzone przez "dynamiczne" możliwości CAShapeLayers.

Co więcej, do przedstawiania elementów, takich jak wiązania i połączenia, istnieje prosty proces tworzenia przerywanych linii na elementach CAShapeLayers, po prostu ustawiając właściwości. Oto podstawowe informacje o ustawianiu właściwości CAShapeLayer i sposobie użycia tablicy do utworzenia konturu kreskowanego 5-5-5 z obrysem bloku o szerokości 3, bez wypełnienia.

CAShapeLayer *shapeLayer = [CAShapeLayer layer]; 
[shapeLayer setBounds:self.bounds]; 
[shapeLayer setPosition:self.center]; 
[shapeLayer setFillColor:[[UIColor clearColor] CGColor]]; 
[shapeLayer setStrokeColor:[[UIColor blackColor] CGColor]]; 
[shapeLayer setLineWidth:3.0f]; 
[shapeLayer setLineJoin:kCALineJoinRound]; 
[shapeLayer setLineDashPattern: 
[NSArray arrayWithObjects:[NSNumber numberWithInt:10], 
    [NSNumber numberWithInt:5],nil]];