在spritekit中制作一个弹性带式弹弓

时间:2014-05-03 06:16:11

标签: ios sprite-kit physics

我正在制作一个游戏,我在屏幕底部有一条线,用于向空中发射。它应该像橡皮筋或弹弓。我已经将一些有效的东西一起攻击,但这是一个糟糕的解决方案,我希望有人可以提出另一种方法。我的方法基本上涉及通过在touchesMoved方法期间重复调用draw方法来重绘可变路径。再一次,我知道这是一个糟糕的做法,对于可怕的代码感到抱歉。

-(void)drawLine:(CGPoint)location
{
[_powerLine removeFromParent];

CGPoint pointTL = CGPointMake(19, 131);
CGPoint pointTR = CGPointMake(308, 131);
CGPoint pointBL = CGPointMake(location.x-10, location.y);
CGPoint pointBR = CGPointMake(location.x+10, location.y);

UIBezierPath *lineShape = [UIBezierPath bezierPath];
[lineShape moveToPoint:pointTL];
[lineShape addLineToPoint:pointBL];
[lineShape addLineToPoint:pointBR];
[lineShape addLineToPoint:pointTR];

_powerLine = [SKShapeNode node];
_powerLine.path = lineShape.CGPath;
_powerLine.lineWidth = 2.0;
_powerLine.strokeColor = [SKColor colorWithRed:0.0 green:0 blue:0 alpha:1];

[self addChild:_powerLine];

CGMutablePathRef powerLinePath = CGPathCreateMutable();
CGPathMoveToPoint(powerLinePath, nil, pointTL.x, pointTL.y);
CGPathAddLineToPoint(powerLinePath, nil, pointBL.x, pointBL.y);
CGPathAddLineToPoint(powerLinePath, nil, pointBR.x, pointBR.y);
CGPathAddLineToPoint(powerLinePath, nil, pointTR.x, pointTR.y);
_powerLine.physicsBody = [SKPhysicsBody bodyWithEdgeChainFromPath:powerLinePath];
_powerLine.physicsBody.categoryBitMask = WFPhysicsCategoryPowerline;
_lastBR = pointBR;
_lastBL = pointBL;
}

我希望有更好的方法可以做到这一点,除了不断重新绘制它,当人们向下拉线以将物体射向空中时。我看着弹簧关节,但无法说服他们工作。我对弹簧接头的另一个问题是如何使图像拉伸以匹配线应该在哪里。这种方法通过简单地消除图像来解决尝试拉伸图像的问题。使用弹簧会很好,这样我就可以避免手工编写物理代码。

有人想过如何做到这一点吗?

1 个答案:

答案 0 :(得分:1)

我不确定你是否关心如何在屏幕上画出令人信服的弹性乐队,或者如何模仿一个人的物理特性。如果它是前者我无法帮助你,但如果它是后者你可以尝试这样的东西!您应该可以将其复制并粘贴到现有的精灵工具包应用中,然后对其进行初始化,然后使用它来调用SKView presentScene:

(header file)
#import <SpriteKit/SpriteKit.h>

@interface SlingScene : SKScene

@end

(implementation file)
#import "SlingScene.h"

@interface SlingScene ()

@property (nonatomic, strong) SKAction *slingAction;

@end

@implementation SlingScene

- (instancetype)initWithSize:(CGSize)size {
    self = [super initWithSize:size];
    if (self) {
        CGPoint center = CGPointMake(self.size.width/2.0, self.size.height/2.0);

        self.slingAction = [SKAction sequence:
                            @[[SKAction waitForDuration:0.1],
                              [SKAction runBlock:
                               ^{  
                                   [self.physicsWorld removeAllJoints];
                               }   
                               ]]];

        // Create a square, which will be slung by the spring
        SKSpriteNode *square =
            [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor]
                                         size:CGSizeMake(60.0, 60.0)];
        square.position = CGPointMake(center.x, center.y - 2*square.size.height);
        square.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:square.size];
        square.physicsBody.collisionBitMask = 0;
        square.name = @"square";

        // Create a post to anchor the square to
        SKShapeNode *post = [SKShapeNode node];
        post.path = CGPathCreateWithEllipseInRect(
                CGRectMake(0.0, 0.0, 60.0, 60.0), NULL);
        post.fillColor = [SKColor brownColor];
        post.strokeColor = [SKColor brownColor];
        post.position = CGPointMake(center.x-30.0, center.y-30.0);
        post.physicsBody =
            [SKPhysicsBody bodyWithCircleOfRadius:60.0 center:center];

        // Give the post a near-infinite mass so the square won't tug at it
        // and move it around
        post.physicsBody.mass = 1000000;
        post.physicsBody.affectedByGravity = NO; 

        // Set their collision bit masks to the same value to allow them to pass
        // through each other
        post.physicsBody.collisionBitMask = 0;
        square.physicsBody.collisionBitMask = 0;

        // Add them to the scene
        [self addChild:post];
        [self addChild:square];

        // Connect them via a spring
        SKPhysicsJointSpring *spring =
            [SKPhysicsJointSpring jointWithBodyA:post.physicsBody
                                           bodyB:square.physicsBody
                                         anchorA:center
                                         anchorB:square.position];
        spring.damping = 0.4;
        spring.frequency = 1.0;
        [self.physicsWorld addJoint:spring];

        // Lower gravity from the default {0.0, -9.8} to allow the
        // square to be slung farther
        self.physicsWorld.gravity = CGVectorMake(0.0, -4.0);
    }
    return self;
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    // Move the square to the touch position
    SKSpriteNode *square = (SKSpriteNode *)[self childNodeWithName:@"square"];
    CGPoint location = [[touches anyObject] locationInNode:self];
    [square runAction:[SKAction moveTo:location duration:0.1]];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    // Sling the square by
    //   1. allowing the spring to accelerate it, and
    //   2. removing the spring altogether
    [self runAction:self.slingAction];
}

@end

另一种方法可能是计算相对于特定点的x和y位置,并在相反方向上施加脉冲。例如,如果您找到dx = -100.0dy = -100.0,则可以使用applyImpulse:CGVectorMake(-dx, -dy)向上和向右启动它。但是,使用弹簧接头会为您提供一些加速度。