3

有没有人(本机)想出如何将 SKNode 子类化以包括通过关节连接的多个主体 - 例如,汽车?

似乎没有办法将子类的关节添加到父场景的physicsWorld 属性。

此外,当尝试编译和运行下面的对象时,即使没有关节,我也会收到 BAD_EXC_ACCESS 错误。

感谢@Smick 提供此处发布的初始车辆代码:Sprite Kit 销接头似乎有不正确的锚点

卡车类:

#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]

这是我对您已经拥有的内容的改进:

车辆.h

@interface Vehicle : SKNode

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

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

@end

车辆.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

所以这就是我想出的。

我唯一的问题是它不是完全独立的,因为关节必须添加到类之外的物理世界中 - 很简单,你会看到使用两行代码。

编辑我的答案。与通过滑动接头连接车轮相比,悬架需要将车轮连接到滑动体上。做前者可以让轮子旋转。后者没有。

更新:我没有将此标记为答案。原因是,虽然它在模拟器上运行良好,但当我尝试在我的 iPad(运行 iOS7)上运行它时收到以下错误。当我删除我的车辆类并将使用该 UIColor 方法的车辆组件之一放入我的主场景时,不会引发错误。

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

车辆.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

车辆.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

我的场景.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] 添加到 Truck 的 init 方法中,因为在您的场景中运行 Truck 的 init 方法时,尚未将 Truck 添加到您的场景中。

您必须在 Truck 类中编写另一个方法(比如 addJointsIntoScene)来运行 [self.scene.physicsWorld addJoint:joint]。将卡车添加到场景后,运行“addJointsIntoScene”方法来添加关节。

例如 Truck.m -(instancetype)initWithPosition:(CGPoint) triggerPosition{ ....joint = ..... .... } //还有另一个方法 -(void)addJointsIntoScene{ [self.scene.physicsWorld添加联合:联合]; 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 回答