3

SKNode をサブクラス化して、ジョイントで接続された複数のボディ (たとえば、車) を含める方法を (ネイティブに) 考え出した人はいますか?

サブクラスの関節を親シーンのphysicsWorldプロパティに追加する方法はないようです。

また、以下のオブジェクトをコンパイルして実行しようとすると、ジョイントがなくても BAD_EXC_ACCESS エラーが発生します。

ここに投稿された最初の車両コードについて @Smick に感謝します:スプライト キットのピン ジョイントが正しくないアンカーを持っているようです

トラック クラス:

#import "Truck.h"

@implementation Truck


-(id)initWithPosition:(CGPoint)pos {


SKSpriteNode *carBody = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:CGSizeMake(120, 8)];
carBody.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:carBody.size];
carBody.position = pos;
carBody.physicsBody.mass = 1.0;


SKSpriteNode *carTop = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:CGSizeMake(50, 8)];
carTop.position = CGPointMake(230, 708);
carTop.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:carTop.size];
carTop.physicsBody.mass = 0;

SKPhysicsJointFixed *carBodyJoint = [SKPhysicsJointFixed jointWithBodyA:carBody.physicsBody
                                                                  bodyB:carTop.physicsBody
                                                                 anchor:CGPointMake(0, 0)];



return self;
}

+(Truck*)initWithPosition:(CGPoint)pos {
return [[self alloc] initWithPosition:pos];
}


@end

私のシーン: ここに画像の説明を入力

4

4 に答える 4

5

投稿が遅れて申し訳ありませんが、自分でこれを押してください。

アタッチされているノードが SKScene のシーン グラフに既に追加されていない限り、物理ジョイントは機能しません。

上記の initWithPosition の間は、そうではありません。SKScene を渡してもうまくいきませんでした。Vehicle ノードがまだシーン グラフに追加されていないためと思われます。

クラス内に物理ジョイントをカプセル化することはできますが、後で別のメソッドを呼び出す必要があります。

[self addChild:car]

これがあなたがすでに持っていたものに関する私の改良です:

Vehicle.h

@interface Vehicle : SKNode

@property (nonatomic) SKSpriteNode *leftWheel;
@property (nonatomic) SKSpriteNode *ctop;

-(id)initWithPosition:(CGPoint)pos;
-(void)initPhysics;

@end

Vehicle.m

//

#import "Vehicle.h"

@implementation Vehicle {
    SKSpriteNode *chassis;
    SKSpriteNode *rightWheel;
    SKSpriteNode *leftShockPost;
    SKSpriteNode *rightShockPost;
    int wheelOffsetY;
    CGFloat damping;
    CGFloat frequency;
}

- (SKSpriteNode*) makeWheel
{
    SKSpriteNode *wheel = [SKSpriteNode spriteNodeWithImageNamed:@"Wheel.png"];
    //    wheel.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:wheel.size.width/2];
    return wheel;
}

-(id)initWithPosition:(CGPoint)pos {

    if (self = [super init]) {

        wheelOffsetY    =   60;
        damping         =   1;
        frequency       =   4;

        chassis = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:CGSizeMake(120, 8)];
        chassis.position = pos;
        [self addChild:chassis];

        _ctop = [SKSpriteNode spriteNodeWithColor:[UIColor greenColor] size:CGSizeMake(70, 16)];
        _ctop.position = CGPointMake(chassis.position.x+20, chassis.position.y+12);

        [self addChild:_ctop];

        _leftWheel = [self makeWheel];
        _leftWheel.position = CGPointMake(chassis.position.x - chassis.size.width / 2, chassis.position.y - wheelOffsetY);  //Always set position before physicsBody

        [self addChild:_leftWheel];

        rightWheel = [self makeWheel];
        rightWheel.position = CGPointMake(chassis.position.x + chassis.size.width / 2, chassis.position.y - wheelOffsetY);
        [self addChild:rightWheel];

        //------------- LEFT SUSPENSION ----------------------------------------------------------------------------------------------- //

        leftShockPost = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(7, wheelOffsetY)];
        leftShockPost.position = CGPointMake(chassis.position.x - chassis.size.width / 2, chassis.position.y - leftShockPost.size.height/2);
        [self addChild:leftShockPost];


        //------------- RIGHT SUSPENSION ----------------------------------------------------------------------------------------------- //

        rightShockPost = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(7, wheelOffsetY)];
        rightShockPost.position = CGPointMake(chassis.position.x + chassis.size.width / 2, chassis.position.y - rightShockPost.size.height/2);
        [self addChild:rightShockPost];

    }

    return self;
}

-(void) initPhysics {

    chassis.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:chassis.size];
    _ctop.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_ctop.size];

    SKPhysicsJointFixed *cJoint = [SKPhysicsJointFixed jointWithBodyA:chassis.physicsBody
                                                                bodyB:_ctop.physicsBody
                                                               anchor:CGPointMake(_ctop.position.x, _ctop.position.y)];

    _leftWheel.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:_leftWheel.size.width/2];
    _leftWheel.physicsBody.allowsRotation = YES;

    rightWheel.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:rightWheel.size.width/2];
    rightWheel.physicsBody.allowsRotation = YES;

    leftShockPost.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:leftShockPost.size];
    SKPhysicsJointSliding  *leftSlide = [SKPhysicsJointSliding jointWithBodyA:chassis.physicsBody
                                                                        bodyB:leftShockPost.physicsBody
                                                                       anchor:CGPointMake(leftShockPost.position.x, leftShockPost.position.y)
                                                                         axis:CGVectorMake(0, 1)];

    leftSlide.shouldEnableLimits = TRUE;
    leftSlide.lowerDistanceLimit = 5;
    leftSlide.upperDistanceLimit = wheelOffsetY;


    SKPhysicsJointSpring *leftSpring = [SKPhysicsJointSpring jointWithBodyA:chassis.physicsBody bodyB:_leftWheel.physicsBody
                                                                    anchorA:CGPointMake(chassis.position.x - chassis.size.width / 2, chassis.position.y)
                                                                    anchorB:_leftWheel.position];
    leftSpring.damping = damping;
    leftSpring.frequency = frequency;

    SKPhysicsJointPin *lPin = [SKPhysicsJointPin jointWithBodyA:leftShockPost.physicsBody bodyB:_leftWheel.physicsBody anchor:_leftWheel.position];

    rightShockPost.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:rightShockPost.size];
    SKPhysicsJointSliding  *rightSlide = [SKPhysicsJointSliding jointWithBodyA:chassis.physicsBody
                                                                         bodyB:rightShockPost.physicsBody
                                                                        anchor:CGPointMake(rightShockPost.position.x, rightShockPost.position.y)
                                                                          axis:CGVectorMake(0, 1)];

    rightSlide.shouldEnableLimits = TRUE;
    rightSlide.lowerDistanceLimit = 5;
    rightSlide.upperDistanceLimit = wheelOffsetY;


    SKPhysicsJointSpring *rightSpring = [SKPhysicsJointSpring jointWithBodyA:chassis.physicsBody bodyB:rightWheel.physicsBody
                                                                     anchorA:CGPointMake(chassis.position.x + chassis.size.width / 2, chassis.position.y)
                                                                     anchorB:rightWheel.position];
    rightSpring.damping = damping;
    rightSpring.frequency = frequency;

    SKPhysicsJointPin *rPin = [SKPhysicsJointPin jointWithBodyA:rightShockPost.physicsBody bodyB:rightWheel.physicsBody anchor:rightWheel.position];

    // Add all joints to the array.
    // Add joints to scene's physics world

    [self.scene.physicsWorld addJoint: cJoint];
    [self.scene.physicsWorld addJoint: leftSlide];
    [self.scene.physicsWorld addJoint: leftSpring];
    [self.scene.physicsWorld addJoint: lPin];
    [self.scene.physicsWorld addJoint: rightSlide];
    [self.scene.physicsWorld addJoint: rightSpring];
    [self.scene.physicsWorld addJoint: rPin];

}
@end

MyScene.m から呼び出す

_car = [[DMVehicle alloc] initWithPosition:location];
[self addChild:_car];
[_car initPhysics];

お役に立てば幸いです。

于 2014-03-28T22:24:10.220 に答える
1

だからここに私が思いついたものがあります。

これに関する私の唯一の問題は、ジョイントをクラス外の物理世界に追加する必要があるため、完全に自己完結型ではないことです.2行のコードを使用するだけで十分簡単です.

私の答えを編集しています。サスペンションは、車輪をスライド ジョイントで取り付けるのではなく、車輪をスライド ボディに取り付ける必要があります。前者を行うと、車輪が回転します。後者はそうではありません。

更新:これを回答としてマーク解除しました。その理由は、シミュレーターでは問題なく動作しますが、iPad (iOS7 を実行) で実行しようとすると、次のエラーが表示されるためです。車両クラスを削除し、その UIColor メソッドを使用する車両のコンポーネントの 1 つをメイン シーンに配置すると、エラーはスローされません。

UICachedDeviceWhiteColor addObject:]: unrecognized selector sent to instance 0x15e21360
2013-12-14 22:44:19.790 SKTestCase[1401:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UICachedDeviceWhiteColor addObject:]: unrecognized selector sent to instance 

何らかの理由で、UICashed... エラーが表示されなくなりました (はい、車両はまだクラスです)。

-[PKPhysicsJointWeld name]: unrecognized selector sent to instance 0x1464f810
2013-12-15 15:28:24.081 MTC[1747:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[PKPhysicsJointWeld name]: unrecognized selector sent to instance 0x1464f810'
*** First throw call stack:
(0x30eaff53 0x3b5186af 0x30eb38e7 0x30eb21d3 0x30e01598 0x3352837d 0x335284d5 0x33527b97 0x33525ca5 0x87385 0x335064f5 0x87ccb 0x33620fe1 0x332aa24b 0x332a5a5b 0x332d4b7d 0x3369e39b 0x3369ca03 0x3369bc53 0x3369bbdb 0x3369bb73 0x33694681 0x3362703f 0x3369b8c1 0x3369b38d 0x3362c21d 0x33629763 0x33694a55 0x33691811 0x3368bd13 0x336266a7 0x336259a9 0x3368b4fd 0x35ab270d 0x35ab22f7 0x30e7a9e7 0x30e7a983 0x30e79157 0x30de3ce7 0x30de3acb 0x3368a799 0x33685a41 0x8a52d 0x3ba20ab7)
libc++abi.dylib: terminating with uncaught exception of type NSException

Vehicle.h:

#import <SpriteKit/SpriteKit.h>

@interface Vehicle : SKNode


@property (nonatomic,assign) NSMutableArray *joints;
@property (nonatomic) SKSpriteNode *leftWheel;
@property (nonatomic) SKSpriteNode *ctop;

-(id)initWithPosition:(CGPoint)pos;

@end

Vehicle.m

#import "Vehicle.h"

@implementation Vehicle

- (SKSpriteNode*) makeWheel
{
    SKSpriteNode *wheel = [SKSpriteNode spriteNodeWithImageNamed:@"wheel.png"];
//    wheel.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:wheel.size.width/2];
    return wheel;
}

-(id)initWithPosition:(CGPoint)pos {

    if (self = [super init]) {

        _joints = [NSMutableArray array];

        int wheelOffsetY    =   60;
        CGFloat damping     =   1;
        CGFloat frequency   =   4;

        SKSpriteNode *chassis = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:CGSizeMake(120, 8)];
        chassis.position = pos;
        chassis.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:chassis.size];
        [self addChild:chassis];

        _ctop = [SKSpriteNode spriteNodeWithColor:[UIColor greenColor] size:CGSizeMake(70, 16)];
        _ctop.position = CGPointMake(chassis.position.x+20, chassis.position.y+12);
        _ctop.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_ctop.size];
        [self addChild:_ctop];

        SKPhysicsJointFixed *cJoint = [SKPhysicsJointFixed jointWithBodyA:chassis.physicsBody
                                                                    bodyB:_ctop.physicsBody
                                                                   anchor:CGPointMake(_ctop.position.x, _ctop.position.y)];


        _leftWheel = [self makeWheel];
        _leftWheel.position = CGPointMake(chassis.position.x - chassis.size.width / 2, chassis.position.y - wheelOffsetY);  //Always set position before physicsBody
        _leftWheel.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:_leftWheel.size.width/2];
        _leftWheel.physicsBody.allowsRotation = YES;
        [self addChild:_leftWheel];

        SKSpriteNode *rightWheel = [self makeWheel];
        rightWheel.position = CGPointMake(chassis.position.x + chassis.size.width / 2, chassis.position.y - wheelOffsetY);
        rightWheel.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:rightWheel.size.width/2];
        rightWheel.physicsBody.allowsRotation = YES;
        [self addChild:rightWheel];

//------------- LEFT SUSPENSION ----------------------------------------------------------------------------------------------- //

        SKSpriteNode *leftShockPost = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(7, wheelOffsetY)];
        leftShockPost.position = CGPointMake(chassis.position.x - chassis.size.width / 2, chassis.position.y - leftShockPost.size.height/2);
        leftShockPost.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:leftShockPost.size];
        [self addChild:leftShockPost];

       SKPhysicsJointSliding  *leftSlide = [SKPhysicsJointSliding jointWithBodyA:chassis.physicsBody
                                                                           bodyB:leftShockPost.physicsBody
                                                    anchor:CGPointMake(leftShockPost.position.x, leftShockPost.position.y)
                                                      axis:CGVectorMake(0, 1)];

        leftSlide.shouldEnableLimits = TRUE;
        leftSlide.lowerDistanceLimit = 5;
        leftSlide.upperDistanceLimit = wheelOffsetY;


        SKPhysicsJointSpring *leftSpring = [SKPhysicsJointSpring jointWithBodyA:chassis.physicsBody bodyB:_leftWheel.physicsBody
                                                                        anchorA:CGPointMake(chassis.position.x - chassis.size.width / 2, chassis.position.y)
                                                                        anchorB:_leftWheel.position];
        leftSpring.damping = damping;
        leftSpring.frequency = frequency;

        SKPhysicsJointPin *lPin = [SKPhysicsJointPin jointWithBodyA:leftShockPost.physicsBody bodyB:_leftWheel.physicsBody anchor:_leftWheel.position];


//------------- RIGHT SUSPENSION ----------------------------------------------------------------------------------------------- //

        SKSpriteNode *rightShockPost = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(7, wheelOffsetY)];
        rightShockPost.position = CGPointMake(chassis.position.x + chassis.size.width / 2, chassis.position.y - rightShockPost.size.height/2);
        rightShockPost.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:rightShockPost.size];
        [self addChild:rightShockPost];

        SKPhysicsJointSliding  *rightSlide = [SKPhysicsJointSliding jointWithBodyA:chassis.physicsBody
                                                                            bodyB:rightShockPost.physicsBody
                                                                           anchor:CGPointMake(rightShockPost.position.x, rightShockPost.position.y)
                                                                             axis:CGVectorMake(0, 1)];

        rightSlide.shouldEnableLimits = TRUE;
        rightSlide.lowerDistanceLimit = 5;
        rightSlide.upperDistanceLimit = wheelOffsetY;


        SKPhysicsJointSpring *rightSpring = [SKPhysicsJointSpring jointWithBodyA:chassis.physicsBody bodyB:rightWheel.physicsBody
                                                                        anchorA:CGPointMake(chassis.position.x + chassis.size.width / 2, chassis.position.y)
                                                                        anchorB:rightWheel.position];
        rightSpring.damping = damping;
        rightSpring.frequency = frequency;

        SKPhysicsJointPin *rPin = [SKPhysicsJointPin jointWithBodyA:rightShockPost.physicsBody bodyB:rightWheel.physicsBody anchor:rightWheel.position];


        // Add all joints to the array.

        [_joints addObject:cJoint];

        [_joints addObject:leftSlide];
        [_joints addObject:leftSpring];
        [_joints addObject:lPin];

        [_joints addObject:rightSlide];
        [_joints addObject:rightSpring];
        [_joints addObject:rPin];

    }

    return self;
}


@end

MyScene.m:

#import "MyScene.h"
#import "Vehicle.h"

@implementation MyScene {

    Vehicle *car;
}

-(id)initWithSize:(CGSize)size {

    if (self = [super initWithSize:size]) {
        /* Setup your scene here */

        self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(0, 0, self.size.width, self.size.height)];

    }

    return self;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */

    for (UITouch *touch in touches) {

        CGPoint location = [touch locationInNode:self];

        car = [[Vehicle alloc] initWithPosition:location];
        [self addChild:car];

        // Add joints to scene's physics world
        for (SKPhysicsJoint *j in car.joints) {
               [self.physicsWorld addJoint:j];
        }
    }

}
于 2013-12-05T02:01:59.060 に答える
0

私は同じ問題を抱えていましたが、この方法でうまくいきます:

シーンからジョイント (トラック クラスで定義) を追加しようとすると、Exc_bad_access が返されます。Truck クラスで [self.scene.physicsWorld addJoint:joint] を実行する必要があります。

ただし、[self.scene.physicsWorld addJoint:joint] をトラックの init メソッドに追加することはできません。これは、シーンでトラックの init メソッドを実行するときにトラックがシーンに追加されていないためです。

[self.scene.physicsWorld addJoint:joint] を実行するには、Truck クラスに別のメソッド (addJointsIntoScene としましょう) を記述する必要があります。トラックをシーンに追加したら、「addJointsIntoScene」メソッドを実行してジョイントを追加します。

たとえば、Truck.m -(instancetype)initWithPosition:(CGPoint) triggerPosition{ .... joint = ..... .... } //および別のメソッド -(void)addJointsIntoScene{ [self.scene.physicsWorld addJoint:ジョイント]; enter code here }

MyScene.m
Truck *truck = [[Truck alloc]initWithPosition:triggerPosition];
[self addChild:truck];
[truck addJointsIntoScene];
于 2014-05-13T11:13:34.770 に答える
0

1) ジョイントの追加: 車両の init メソッドで SKScene オブジェクトを取得しないのはなぜですか? 次に、そのメソッド内にジョイントを追加できます。それ以外の場合、_joints 配列で行ったことは機能しますが、そこに必要な追加のコードであまりきれいに見えません。

2) BAD_EXC_ACCESS: これも関節について学んでいたときに得たものです。ジョイントに参加しているノードが SKScene に追加され、他のサブノードには追加されなかったとき、それはなくなりました。私が見つけることができるApple のドキュメントで最も近い情報は、「物理ボディをシーン内の SKNode オブジェクトのペアにアタッチする」です。これが直接 SKScene を意味するのか、それとも SKScene のノード ツリー内の任意のノードを意味するのかは指定されていません。

于 2013-12-24T04:35:52.630 に答える