Spritekit物理:一个球击中另一个球

时间:2014-05-09 07:55:46

标签: ios sprite-kit game-physics

我是SpriteKit的新手。

我试图解决这个问题: 我的场景中有两个球,当我拖出一个球时,击中了#34;另一个球,这个球应该使用正确的物理学滚动。

在我的测试代码中我只能"移动"第二球,他没有使用" force"热门......

这是我的场景代码:

#import "HittingScene.h"

@interface HittingScene()

@property (nonatomic, strong) SKShapeNode *targetBall;
@property (nonatomic, strong) SKShapeNode *mainBall;
@property (nonatomic, weak) SKShapeNode *draggedNode;

@end

@implementation HittingScene

- (id)initWithSize:(CGSize)size
{
    if (self = [super initWithSize:size]) {
        [self addChild:[self createMainBall]];
        [self addChild:[self createTargetBall]];

        [self setPhysicsBody:[SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame]];
    }
    return self;
}

- (SKShapeNode *)createTargetBall
{
    self.targetBall = [SKShapeNode node];

    CGPathRef path = CGPathCreateWithEllipseInRect((CGRect){{-20, -20}, {40, 40}}, NULL);
    [self.targetBall setPath:path];
    CGPathRelease(path);

    [self.targetBall setPosition:CGPointMake(200, 200)];
    [self.targetBall setName:@"targetBall"];

    [self.targetBall setPhysicsBody:[SKPhysicsBody bodyWithCircleOfRadius:20.0]];
    self.targetBall.physicsBody.dynamic = YES;
    self.targetBall.physicsBody.affectedByGravity = NO;
    self.targetBall.physicsBody.restitution = 0.7;

    return self.targetBall;
}

- (SKShapeNode *)createMainBall
{
    self.mainBall = [SKShapeNode node];

    CGPathRef path = CGPathCreateWithEllipseInRect((CGRect){{-20, -20}, {40, 40}}, NULL);
    [self.mainBall setPath:path];
    CGPathRelease(path);

    [self.mainBall setPosition:CGPointMake(100, 100)];
    [self.mainBall setName:@"mainBall"];

    [self.mainBall setPhysicsBody:[SKPhysicsBody bodyWithCircleOfRadius:20.0]];
    self.mainBall.physicsBody.dynamic = YES;
    self.mainBall.physicsBody.affectedByGravity = NO;
    self.mainBall.physicsBody.restitution = 0.7;

    return self.mainBall;
}

- (void)touchesBegan:(NSSet*) touches withEvent:(UIEvent*) event
{
    self.draggedNode = (SKShapeNode *)[self nodeAtPoint:[[touches anyObject]     locationInNode:self]];
}

- (void)touchesMoved:(NSSet*) touches withEvent:(UIEvent*) event
{
    self.draggedNode.position = [[touches anyObject] locationInNode:self];
}

- (void)touchesEnded:(NSSet*) touches withEvent:(UIEvent*) event
{
    self.draggedNode = nil;
}
@end

有想法如何解决这个问题的人?

谢谢, Urkman

2 个答案:

答案 0 :(得分:1)

我认为问题在于你只是在触摸时改变球的位置。这样做只是将节点置于一个新的点并且实际上并不涉及任何力量。你需要建立一个碰撞系统,当主球与它碰撞时,对目标球施加一定的力。

SKPhysicsBody 中的 applyForce:atPoint:看起来是个好地方。

https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKPhysicsBody_Ref/Reference/Reference.html

答案 1 :(得分:0)

这是一个可能的解决方案:

#import "HittingScene.h"

@interface HittingScene() <SKPhysicsContactDelegate>

@property (nonatomic, strong) SKShapeNode *targetBall;
@property (nonatomic, strong) SKShapeNode *mainBall;
@property (nonatomic) CGPoint lastTouch;
@property (nonatomic) bool isDragging;

@end

@implementation HittingScene

static const uint32_t mainBallCategory = 0x1 << 0;
static const uint32_t targetBallCategory = 0x1 << 1;

- (id)initWithSize:(CGSize)size
{
    if (self = [super initWithSize:size]) {

        self.physicsWorld.gravity = CGVectorMake(0, 0);

        [self addChild:[self createMainBall]];
        [self addChild:[self createTargetBall]];

        [self setPhysicsBody:[SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame]];
        self.physicsWorld.contactDelegate = self;
        [self.targetBall.physicsBody applyForce:CGVectorMake(30, 30)];
    }
    return self;
}

- (SKShapeNode *)createTargetBall
{
    self.targetBall = [SKShapeNode node];

    CGPathRef path = CGPathCreateWithEllipseInRect((CGRect){{-20, -20}, {40, 40}}, NULL);
    [self.targetBall setPath:path];
    CGPathRelease(path);

    [self.targetBall setPosition:CGPointMake(200, 200)];
    [self.targetBall setName:@"targetBall"];

    [self.targetBall setPhysicsBody:[SKPhysicsBody bodyWithCircleOfRadius:20.0]];
    self.targetBall.physicsBody.dynamic = YES;
    self.targetBall.physicsBody.affectedByGravity = YES;
    self.targetBall.physicsBody.restitution = 0.7;
    self.targetBall.physicsBody.categoryBitMask = targetBallCategory;
    self.targetBall.physicsBody.contactTestBitMask = mainBallCategory;

    return self.targetBall;
}

- (SKShapeNode *)createMainBall
{
    self.mainBall = [SKShapeNode node];

    CGPathRef path = CGPathCreateWithEllipseInRect((CGRect){{-20, -20}, {40, 40}}, NULL);
    [self.mainBall setPath:path];
    CGPathRelease(path);

    [self.mainBall setPosition:CGPointMake(100, 100)];
    [self.mainBall setName:@"mainBall"];

    [self.mainBall setPhysicsBody:[SKPhysicsBody bodyWithCircleOfRadius:20.0]];
    self.mainBall.physicsBody.dynamic = NO;
    self.mainBall.physicsBody.affectedByGravity = NO;
    self.mainBall.physicsBody.restitution = 0.7;
    self.mainBall.physicsBody.categoryBitMask = mainBallCategory;

    return self.mainBall;
}    

- (void)touchesBegan:(NSSet*) touches withEvent:(UIEvent*) event
{
    if ((SKShapeNode *)[self nodeAtPoint:[[touches anyObject] locationInNode:self]] == self.mainBall) {
        self.isDragging = YES;
    }
}

- (void) didBeginContact:(SKPhysicsContact *)contact
{
    if (self.isDragging) {
        float angle = atan2f (self.lastTouch.y - self.mainBall.position.y, self.lastTouch.x - self.mainBall.position.x) ;
        float distance = hypotf(self.lastTouch.x - self.mainBall.position.x, self.lastTouch.y - self.mainBall.position.y);

        // calculate vector
        CGFloat thrust = distance;
        CGVector thrustVector = CGVectorMake(thrust*cosf(angle), thrust*sinf(angle));

        // apply force or impluse to target node

        // force is not working
        // [self.targetBall.physicsBody applyForce:thrustVector];

        // impulse is working
        [self.targetBall.physicsBody applyImpulse:thrustVector];
    }
}

- (void)touchesMoved:(NSSet*) touches withEvent:(UIEvent*) event
{
    self.lastTouch = [[touches anyObject] locationInNode:self];
    if (self.isDragging) {
        [self.mainBall runAction:[SKAction moveTo:[[touches anyObject] locationInNode:self] duration:0.01]];
    }
}

- (void)touchesEnded:(NSSet*) touches withEvent:(UIEvent*) event
{
    self.isDragging = NO;
}

@end