Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SpriteKit Weird 'PKPhysicsBody' Crash

I am trying to implement a simple category for SKPhysicsBody that will allow me to apply 'perfect bouncing' to a physics body.

What this will simply do is when perfectBouncing = YES the following will happen:

restitution = 1.0

linearDamping = 0.0

friction = 0.0

However, when I try to use my implementation as shown below, I get a weird crash telling me that I can't send perfectBouncing messages to PKPhysicsBody, which is a class that I never refer to and doesn't exist in my project or to my knowledge in the SpriteKit SDK.

And yes, the catagory is being imported.

Crash Message

-[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
)

Category Implementation

#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

Example of Usage

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

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

Any ideas what this elusive PKPhysicsBody is and why I am having this crash?

like image 614
Hamish Avatar asked Sep 29 '22 14:09

Hamish


1 Answers

Internally, Sprite Kit has custom classes for many of the public classes. In this case SKPhysicsBody actually creates an instance of the internal class PKPhysicsBody. Presumably PK stands for "Physics Kit".

That's why your category won't work, and if I remember correctly casting won't do the trick either because SKPhysicsBody does not inherit from PKPhysicsBody, but in case I'm wrong you can try it this way:

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

In any case a category isn't needed here. Instead you can achieve the same effect with a helper class and class methods, for instance:

@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
like image 54
LearnCocos2D Avatar answered Oct 05 '22 08:10

LearnCocos2D