对于我的程序,我需要使用触摸移动和 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/