【问题标题】:Make an elastic band type slingshot in spritekit在 spritekit 中制作松紧带式弹弓
【发布时间】:2014-05-03 06:16:10
【问题描述】:

我正在开发一款游戏,我在屏幕底部有一条线,我用它来将东西发射到空中。它的行为应该像橡皮筋或弹弓。我已经将一些可行的方法组合在一起,但这是一个糟糕的解决方案,我希望有人可以提出另一种方法。我的方法基本上涉及通过在 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;
}

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

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

【问题讨论】:

    标签: ios sprite-kit physics


    【解决方案1】:

    我不确定您是否关心如何在屏幕上绘制令人信服的松紧带,或者如何模拟松紧带的物理特性。如果是前者,我帮不了你太多,但如果是后者,你可以试试这样的东西!您应该能够将其复制并粘贴到现有的 sprite kit 应用程序中进行操作,只需对其进行初始化并调用 SKViewpresentScene: 即可。

    (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) 将其启动并正确启动。不过,使用弹簧接头会给您一些加速。

    【讨论】:

    • 啊,这真的很好,可能会让我朝着正确的方向前进。我没有指定物体需要降落在电线上,您可以再次启动它。想象一根穿过场景底部的电线,你可以用它来将东西发射到空中。当他们回来时,他们降落在电线上,你可以再次发射它们。但我认为如果我使用两个锚点并设置碰撞位掩码,这种方法可能会起作用。感谢您为我编写了一整段代码!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-16
    • 1970-01-01
    相关资源
    最近更新 更多