SpriteKit Странный сбой PKPhysicsBody

Я пытаюсь реализовать простую категорию для SKPhysicsBody, которая позволит мне применить «идеальный отскок» к физическому телу.

Это просто произойдет, когда perfectBouncing = YES произойдет следующее:

restitution = 1.0

linearDamping = 0.0

friction = 0.0

Однако, когда я пытаюсь использовать свою реализацию, как показано ниже, я получаю странный сбой, говорящий мне, что я не могу отправить perfectBouncing сообщения в PKPhysicsBody, который является классом, на который я никогда не ссылаюсь и который не существует в моем проекте или в мои знания в SpriteKit SDK.

И да, категория импортируется.

Сообщение о сбое

-[PKPhysicsBody setPerfectBouncing:]: unrecognized selector sent to instance 0x7fa828f84610

*** First throw call stack:
(
    0   CoreFoundation                      0x000000010882b3f5 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x0000000107dbfbb7 objc_exception_throw + 45
    2   CoreFoundation                      0x000000010883250d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
    3   CoreFoundation                      0x000000010878a7fc ___forwarding___ + 988
    4   CoreFoundation                      0x000000010878a398 _CF_forwarding_prep_0 + 120
    5   Squash The Dot                      0x000000010785662c -[gameNode viewDidAnimateIn] + 1116
    6   Squash The Dot                      0x000000010783e709 -[lzyViewHandler initViewChild:] + 3305
    7   Squash The Dot                      0x000000010783d93d -[lzyViewHandler initViewChildren:] + 573
    8   Squash The Dot                      0x000000010785d3e0 __28-[splashVC viewDidAnimateIn]_block_invoke + 256
    9   SpriteKit                           0x000000010933837e _ZN9SKCAction25didFinishWithTargetAtTimeEP9SKCSprited + 44
    10  SpriteKit                           0x0000000109399638 _ZN9SKCSprite6updateEd + 170
    11  SpriteKit                           0x0000000109352dd4 -[SKScene _update:] + 119
    12  SpriteKit                           0x000000010936d299 -[SKView(Private) _update:] + 563
    13  SpriteKit                           0x000000010936ac2f -[SKView renderCallback:] + 829
    14  SpriteKit                           0x0000000109367cec __29-[SKView setUpRenderCallback]_block_invoke + 54
    15  SpriteKit                           0x0000000109394744 -[SKDisplayLink _callbackForNextFrame:] + 256
    16  QuartzCore                          0x00000001091f88f7 _ZN2CA7Display15DisplayLinkItem8dispatchEv + 37
    17  QuartzCore                          0x00000001091f87bf _ZN2CA7Display11DisplayLink14dispatch_itemsEyyy + 315
    18  CoreFoundation                      0x00000001087934e4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
    19  CoreFoundation                      0x00000001087930a5 __CFRunLoopDoTimer + 1045
    20  CoreFoundation                      0x00000001087563dd __CFRunLoopRun + 1901
    21  CoreFoundation                      0x0000000108755a06 CFRunLoopRunSpecific + 470
    22  GraphicsServices                    0x000000010be319f0 GSEventRunModal + 161
    23  UIKit                               0x000000010953f550 UIApplicationMain + 1282
    24  Squash The Dot                      0x00000001078550a3 main + 115
    25  libdyld.dylib                       0x000000010b6cb145 start + 1
)

Внедрение категории

#import <SpriteKit/SpriteKit.h>

@interface SKPhysicsBody (lzySKPhysics)

// Enables perfect boucing by setting friction = 0, linearDamping = 0 and restitution = 1.
@property (nonatomic) BOOL perfectBouncing;

@end


@implementation SKPhysicsBody (lzySKPhysics)

-(BOOL) perfectBouncing {
    return (self.restitution == 1 && self.linearDamping == 0 && self.friction == 0);
}

-(void) setPerfectBouncing:(BOOL)perfectBouncing {
    self.restitution = perfectBouncing;
    self.linearDamping = !perfectBouncing;
    self.friction = !perfectBouncing;
}

@end

Пример использования

hero = [[SKSpriteNode alloc] initWithColor:[SKColor blueColor] size:CGSizeMake(heroRadius*2, heroRadius*2)];

hero.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:heroRadius];
hero.physicsBody.perfectBouncing = YES;

Есть идеи, что это за неуловимый PKPhysicsBody и почему у меня происходит этот сбой?


person Hamish    schedule 21.10.2014    source источник


Ответы (1)


Внутри Sprite Kit есть пользовательские классы для многих общедоступных классов. В этом случае SKPhysicsBody фактически создает экземпляр внутреннего класса PKPhysicsBody. Предположительно PK означает «Physics Kit».

Вот почему ваша категория не будет работать, и, если я правильно помню, кастинг тоже не поможет, потому что SKPhysicsBody не наследуется от PKPhysicsBody, но в случае, если я ошибаюсь, вы можете попробовать это следующим образом:

((SKPhysicsBody)hero.physicsBody).perfectBouncing = YES;

В любом случае категория здесь не нужна. Вместо этого вы можете добиться того же эффекта с помощью вспомогательного класса и методов класса, например:

@implementation SKPhysicsHelper

+(BOOL) perfectBouncingWithBody:(SKPhysicsBody*)body {
    return (body.restitution == 1 && body.linearDamping == 0 && body.friction == 0);
}

+(void) setPerfectBouncing:(BOOL)perfectBouncing body:(SKPhysicsBody*)body {
    body.restitution = perfectBouncing;
    body.linearDamping = !perfectBouncing;
    body.friction = !perfectBouncing;
}

@end
person LearnCocos2D    schedule 21.10.2014
comment
Ах, хорошо, спасибо, и да, вы правы в том, что кастинг не работает. На самом деле, я только что обнаружил, что использование категории SKSpriteNode для достижения той же цели работает, хотя это будет раздражать меня, поскольку не все узлы спрайтов используют физику. Я нахожу помощников немного неуклюжими, когда дело доходит до использования, я, вероятно, в конечном итоге буду использовать функцию для этого. Тем не менее спасибо за оперативный и лаконичный ответ! - person Hamish; 21.10.2014