节点不应该与其他节点发生碰撞
Node colliding with other node when it shouldn't
我有一个节点,每隔几秒生成一次,并从右侧穿过屏幕。我希望玩家每次接触该节点时分数都会增加,但我希望玩家直接穿过它而不是被它阻挡。现在,当玩家击中它时得分会上升,它会正确生成并移动,但会阻止玩家越过它。我已经尝试了多种解决方案,例如使得分线的 collisionBitmask 等于 0,但我对 objective-c 还是个新手,所以我不知道解决方案,因此我们将不胜感激。
以下是“@implementation”上面的全部代码
@interface GameScene ()
@property (nonatomic) SKSpriteNode *clouds;
@property (nonatomic) SKSpriteNode *player;
@property (nonatomic) SKTexture *pipeTexture1;
@property (nonatomic) SKTexture *pipeTexture2;
@property (nonatomic) SKAction *_moveAndRemovePipes;
@property (nonatomic) SKNode *moving;
@property (nonatomic) SKLabelNode *scoreLabelNode;
@property (nonatomic) int score;
@end
static const uint32_t playerCategory = 1;
static const uint32_t pipeCategory = 2;
static const uint32_t bottomEdgeCategory = 4;
static const uint32_t edgeCategory = 8;
static const uint32_t scoreCategory =16;
这是与分数线有关的代码。请注意,我添加分数标签的代码是我的 initWithSize 方法。
-(void) addScore:(CGSize) size{
// Initialize label and create a label which holds the score
// _score = 0;
// _scoreLabelNode = [SKLabelNode labelNodeWithFontNamed:@"MarkerFelt-Wide"];
// _scoreLabelNode.position = CGPointMake( CGRectGetMidX( self.frame ), 3 * self.frame.size.height / 4 );
// _scoreLabelNode.zPosition = 100;
// _scoreLabelNode.text = [NSString stringWithFormat:@"%d", _score];
//add score line
SKNode *contactNode = [SKNode node];
contactNode.position = CGPointMake( self.frame.size.width + _pipeTexture1.size.width - 10 , CGRectGetMidY( self.frame ) );
contactNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake( 5, self.frame.size.height )];
contactNode.physicsBody.dynamic = NO;
contactNode.physicsBody.categoryBitMask = scoreCategory;
// contactNode.physicsBody.contactTestBitMask = playerCategory;
//move score line
CGFloat distanceToMove = self.frame.size.width + 2.4 * _pipeTexture1.size.width;
SKAction *movePipes = [SKAction moveByX:-distanceToMove y:0 duration:0.01 * distanceToMove];
SKAction *removePipes = [SKAction removeFromParent];
SKAction *moveNode = [SKAction sequence:@[movePipes, removePipes]];
[contactNode runAction:moveNode];
[_moving addChild:contactNode];
// [self addChild:_scoreLabelNode];
}
下面是我的initWithSize方法,去掉了一些不重要的代码。
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
//change gravity
self.physicsWorld.gravity = CGVectorMake( 0.0, -5 );
//add physics to world
self.physicsWorld.contactDelegate = self;
//add moving node to keep track of animations
_moving = [SKNode node];
[self addChild:_moving];
// Initialize label and create a label which holds the score
_score = 0;
_scoreLabelNode = [SKLabelNode labelNodeWithFontNamed:@"MarkerFelt-Wide"];
_scoreLabelNode.position = CGPointMake( CGRectGetMidX( self.frame ), 3 * self.frame.size.height / 4 );
_scoreLabelNode.zPosition = 100;
_scoreLabelNode.text = [NSString stringWithFormat:@"%d", _score];
[self addChild:_scoreLabelNode];
SKAction* spawnScore = [SKAction performSelector:@selector(addScore:) onTarget:self];
SKAction* delayScore = [SKAction waitForDuration:2.0];
SKAction* spawnThenDelayScore = [SKAction sequence:@[delayScore,spawnScore]];
SKAction* spawnThenDelayForeverScore = [SKAction repeatActionForever:spawnThenDelayScore];
[self runAction:spawnThenDelayForeverScore];
[self addScore:size];
}
return self;
}
如果您只想检测两个 SKNode 之间的接触而不希望它们发生碰撞,请将它们的 contactTestBitMask
设置为另一个的 categoryBitMask
,并将 collissionBitMask
设置为零。
例如,在你的情况下
player.physicsBody.categoryBitMask = playerCategory
player.physicsBody.contactTestBitMask = scoreCategory | otherCategories
player.physicsBody.collisionBitMask = 0 // This can be categories other than score categories
scoreNode.physicsBody.categoryBitMask = scoreCategory
scoreNode.physicsBody.contactTestBitMask = playerCategory | otherCategories
scoreNode.physicsBody.collisionBitMask = 0
我有一个节点,每隔几秒生成一次,并从右侧穿过屏幕。我希望玩家每次接触该节点时分数都会增加,但我希望玩家直接穿过它而不是被它阻挡。现在,当玩家击中它时得分会上升,它会正确生成并移动,但会阻止玩家越过它。我已经尝试了多种解决方案,例如使得分线的 collisionBitmask 等于 0,但我对 objective-c 还是个新手,所以我不知道解决方案,因此我们将不胜感激。
以下是“@implementation”上面的全部代码
@interface GameScene ()
@property (nonatomic) SKSpriteNode *clouds;
@property (nonatomic) SKSpriteNode *player;
@property (nonatomic) SKTexture *pipeTexture1;
@property (nonatomic) SKTexture *pipeTexture2;
@property (nonatomic) SKAction *_moveAndRemovePipes;
@property (nonatomic) SKNode *moving;
@property (nonatomic) SKLabelNode *scoreLabelNode;
@property (nonatomic) int score;
@end
static const uint32_t playerCategory = 1;
static const uint32_t pipeCategory = 2;
static const uint32_t bottomEdgeCategory = 4;
static const uint32_t edgeCategory = 8;
static const uint32_t scoreCategory =16;
这是与分数线有关的代码。请注意,我添加分数标签的代码是我的 initWithSize 方法。
-(void) addScore:(CGSize) size{
// Initialize label and create a label which holds the score
// _score = 0;
// _scoreLabelNode = [SKLabelNode labelNodeWithFontNamed:@"MarkerFelt-Wide"];
// _scoreLabelNode.position = CGPointMake( CGRectGetMidX( self.frame ), 3 * self.frame.size.height / 4 );
// _scoreLabelNode.zPosition = 100;
// _scoreLabelNode.text = [NSString stringWithFormat:@"%d", _score];
//add score line
SKNode *contactNode = [SKNode node];
contactNode.position = CGPointMake( self.frame.size.width + _pipeTexture1.size.width - 10 , CGRectGetMidY( self.frame ) );
contactNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake( 5, self.frame.size.height )];
contactNode.physicsBody.dynamic = NO;
contactNode.physicsBody.categoryBitMask = scoreCategory;
// contactNode.physicsBody.contactTestBitMask = playerCategory;
//move score line
CGFloat distanceToMove = self.frame.size.width + 2.4 * _pipeTexture1.size.width;
SKAction *movePipes = [SKAction moveByX:-distanceToMove y:0 duration:0.01 * distanceToMove];
SKAction *removePipes = [SKAction removeFromParent];
SKAction *moveNode = [SKAction sequence:@[movePipes, removePipes]];
[contactNode runAction:moveNode];
[_moving addChild:contactNode];
// [self addChild:_scoreLabelNode];
}
下面是我的initWithSize方法,去掉了一些不重要的代码。
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
//change gravity
self.physicsWorld.gravity = CGVectorMake( 0.0, -5 );
//add physics to world
self.physicsWorld.contactDelegate = self;
//add moving node to keep track of animations
_moving = [SKNode node];
[self addChild:_moving];
// Initialize label and create a label which holds the score
_score = 0;
_scoreLabelNode = [SKLabelNode labelNodeWithFontNamed:@"MarkerFelt-Wide"];
_scoreLabelNode.position = CGPointMake( CGRectGetMidX( self.frame ), 3 * self.frame.size.height / 4 );
_scoreLabelNode.zPosition = 100;
_scoreLabelNode.text = [NSString stringWithFormat:@"%d", _score];
[self addChild:_scoreLabelNode];
SKAction* spawnScore = [SKAction performSelector:@selector(addScore:) onTarget:self];
SKAction* delayScore = [SKAction waitForDuration:2.0];
SKAction* spawnThenDelayScore = [SKAction sequence:@[delayScore,spawnScore]];
SKAction* spawnThenDelayForeverScore = [SKAction repeatActionForever:spawnThenDelayScore];
[self runAction:spawnThenDelayForeverScore];
[self addScore:size];
}
return self;
}
如果您只想检测两个 SKNode 之间的接触而不希望它们发生碰撞,请将它们的 contactTestBitMask
设置为另一个的 categoryBitMask
,并将 collissionBitMask
设置为零。
例如,在你的情况下
player.physicsBody.categoryBitMask = playerCategory
player.physicsBody.contactTestBitMask = scoreCategory | otherCategories
player.physicsBody.collisionBitMask = 0 // This can be categories other than score categories
scoreNode.physicsBody.categoryBitMask = scoreCategory
scoreNode.physicsBody.contactTestBitMask = playerCategory | otherCategories
scoreNode.physicsBody.collisionBitMask = 0