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

标签 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 设为一个 physicsBody,但是当我运行它时,碰撞不起作用。 (它运行没有错误)

下面是碰撞代码:

- (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];
    }
}

最佳答案

尝试做一个有一定宽度的封闭路径,例如:

- (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;
}

关于ios - 如何使用 SKShapeNode 绘制一条线并使其成为物理体(启用碰撞)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23049260/

相关文章:

iphone - 如何将并排放置的两个图像一起缩放?

iphone - 如何在 UITableViewCell 中模糊(ios7 风格)图像的一部分?

ios - 以编程方式调整大小/对齐加载 View

qt - 在 QDockWidget 中停靠的小部件顶部绘画/绘图

qt - 在 QML 中绘制弧/圆扇区?

ios - 保存分段 Controller 位置

iOS应用程序退出并重新加载后黑屏

ios - 在已失效的 session 中创建的任务

ios - otest 崩溃与 -[id<NSURLAuthenticationChallengeSender> userCredential :]

ios - UIView如何绘制相机选择器