如何使用SKShapeNode绘制一条线并使其成为一个物理体(启用碰撞)?

时间:2014-04-13 22:30:35

标签: ios cocoa-touch draw sprite-kit

对于我的程序,我需要使用移动的触摸和SKShapeNode绘制一条线并为其提供碰撞属性。

我看了一下这个帖子:draw a line in sprite kit in touchesmoved画了一条线,但我很难把它变成一个物理体。

我想要完成的是通过用户绘制的道路从上方和下方驾驶汽车。因此,我试图让汽车接触线并沿着它移动......从技术上讲,汽车不会移动,因为只有背景移动。

我将如何做到这一点?

以下是我的代码的重要部分:

我已经制作了3个类(GameHelper,StartGame和GameOver),但它们与我的问题无关。这里是我声明了一个名为pathToDraw的CGMutablePathRef和一个名为lineNode的SKShapeNode。

#import "MyScene.h"
#import "MyScene.h"
#import "StartGameLayer.h"
#import "GameOverLayer.h"

#define TIME 1.5
#define MINIMUM_ROCK_HEIGHT 200.0f
#define GAP_BETWEEN_TOP_AND_BOTTOM_ROCK 50.0f

#define BACKGROUND_Z_POSITION    100
#define START_GAME_LAYER_Z_POSITION     150
#define GAME_OVER_LAYER_Z_POSITION      200

static const uint32_t rockCategory            =  0x1 << 0;
static const uint32_t mineCartCategory        =  0x1 << 1;
static const uint32_t lineCategory            =  0x1 << 1;



static const float BG_VELOCITY = (TIME * 60);

static inline CGPoint CGPointAdd(const CGPoint a, const CGPoint b)
{
    return CGPointMake(a.x + b.x, a.y + b.y);
}

static inline CGPoint CGPointMultiplyScalar(const CGPoint a, const CGFloat b)
{
    return CGPointMake(a.x * b, a.y * b);
}


@interface MyScene() <SKPhysicsContactDelegate, StartGameLayerDelegate, GameOverLayerDelegate>
{
    NSTimeInterval _dt;
    float bottomScrollerHeight;

    BOOL _gameStarted;
    BOOL _gameOver;

    CGMutablePathRef pathToDraw;
    SKShapeNode *lineNode;

    StartGameLayer* _startGameLayer;
    GameOverLayer* _gameOverLayer;

    int _score;
}
@property (nonatomic) SKSpriteNode* backgroundImageNode;
@property (nonatomic) SKSpriteNode* mineCart;
@property (nonatomic) NSTimeInterval lastSpawnTimeInterval;
@property (nonatomic) NSTimeInterval lastUpdateTimeInterval;

@property (nonatomic) NSArray* mineCartFrames;
@end

然后这是我的代码画线:

#pragma mark - Touches

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch* touch = [touches anyObject];
    CGPoint positionInScene = [touch locationInNode:self];

    pathToDraw = CGPathCreateMutable();
    CGPathMoveToPoint(pathToDraw, NULL, positionInScene.x, positionInScene.y);
    lineNode = [SKShapeNode node];
    lineNode.path = pathToDraw;
    lineNode.strokeColor = [SKColor redColor];
    lineNode.zPosition = 125;
    lineNode.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:lineNode.path];
    lineNode.physicsBody.categoryBitMask = lineCategory;
    lineNode.physicsBody.contactTestBitMask = mineCartCategory;
    lineNode.physicsBody.collisionBitMask = 0;
    lineNode.physicsBody.affectedByGravity = NO;
    [self addChild:lineNode];
}

- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
    UITouch* touch = [touches anyObject];
    CGPoint positionInScene = [touch locationInNode:self];
    CGPathAddLineToPoint(pathToDraw, NULL, positionInScene.x, positionInScene.y);
    lineNode.path = pathToDraw;
}

这里我试图让lineNode成为一个物理实体,但是当我运行它时,碰撞并不起作用。 (它运行没有错误)

下面是碰撞代码:

- (void)didBeginContact:(SKPhysicsContact *)contact
{
    SKPhysicsBody *firstBody, *secondBody;

    if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
    {
        firstBody = contact.bodyA;
        secondBody = contact.bodyB;
    }
    else
    {
        firstBody = contact.bodyB;
        secondBody = contact.bodyA;
    }

    if ((firstBody.categoryBitMask & rockCategory) != 0 &&
        (secondBody.categoryBitMask & mineCartCategory) != 0)
    {
        [self rock:(SKSpriteNode *) firstBody.node didCollideWithCart:(SKSpriteNode *) secondBody.node];
    }
    else if ((firstBody.categoryBitMask & lineCategory) != 0 &&
             (secondBody.categoryBitMask & mineCartCategory) != 0)
    {
        [self line:(SKSpriteNode *) firstBody.node didCollideWithCart:(SKSpriteNode *) secondBody.node];
    }
}

2 个答案:

答案 0 :(得分:0)

尝试制作具有一定宽度的闭合路径,例如:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    ...
    pathToDraw = CGPathCreateMutable();
    CGPathMoveToPoint(pathToDraw, NULL, 0, 0);
    CGPathAddLineToPoint(pathToDraw, NULL, 1, 0);
    ...
}

- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
    ...
    CGPathAddLineToPoint(pathToDraw, NULL, positionInScene.x, positionInScene.y);
    CGPathAddLineToPoint(pathToDraw, NULL, 0, 0);
    lineNode.path = pathToDraw;
}

答案 1 :(得分:0)

你应该在

之后添加物理体
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{

你做的是在用户触摸的第一点开始添加一个物理体,这不是你想要的。