当对象逆时针而不是顺时针方向时,intersectsNode失败

时间:2015-08-16 23:48:16

标签: objective-c sprite-kit intersection

我正在创造一个非常简单的轮盘游戏。没有物理参与。表盘绕着彩色的方向盘旋转,必须使表盘停在正确的颜色上。如果它们停在正确的颜色上,则表盘会以相反的方向旋转一个新颜色,以便它们匹配。我正在使用" intersectsNode"在边界线上检测表盘何时进入车轮的象限并检查其颜色是否正确等。当表盘逆时针旋转时,表盘在接触时正确地与边界线相交。然而,当表盘顺时针旋转时,intersectsNode在它连接之前会被触发三分之一。

相同的代码用于检测逆时针和顺时针以及创建边界线,所以我很困惑为什么它会以一种方式与另一种方式失败。有没有人有任何想法?也许是我不知道的一个错误?我的设置一个明显的问题?

UIFontDescriptor

@implementation GameScene {

    Sound *sound;
    GameModel *gameModel;

    SKSpriteNode  *wheel, *pin;
    float duration;

    Direction currentDirection;
    int colorCount;
    Color currentColor, startingColor, enteringColor;
    SKLabelNode *scoreLabel;
}

- (void)didMoveToView:(SKView *)view {

    gameModel = [GameModel sharedManager];

    self.anchorPoint = CGPointMake(0.5, 0.5);
    self.backgroundColor = [SKColor colorWithWhite:0.9 alpha:1.0];

    wheel = [SKSpriteNode spriteNodeWithImageNamed:@"wheel"];
    [self addChild:wheel];
    //wheel.zRotation = SK_DEGREES_TO_RADIANS(-45);

    SKSpriteNode *hub = [SKSpriteNode spriteNodeWithImageNamed:@"hub"];
    [wheel addChild:hub];

    pin = [SKSpriteNode spriteNodeWithImageNamed:@"blue_pin"];
    pin.anchorPoint = CGPointMake(0.5, 0);
    pin.size = pin.texture.size;
    //pin.zRotation = SK_DEGREES_TO_RADIANS(45);
    [self addChild:pin];

    [self createBoundaryLines];

    PushButton *hubButton = [[PushButton alloc] initWithUpImage:@"blank_button" andDownImage:@"blank_button"];
    [hubButton setTouchUpInsideTarget:self action:@selector(switchDirection) parent:self];
    hubButton.zPosition = 50;
    [wheel addChild:hubButton];

    [self createScoreLabel];

    [self createResetButton];

    [self resetGame];
}

- (void)setScore:(int)score {

    _score = score;

    scoreLabel.text = [NSString stringWithFormat:@"%d", _score];
}

- (void)createBoundaryLines {

    //counterclockwise lines
    [wheel addChild:[self createLine:@"counterLine" color:[SKColor blueColor] position:CGPointMake(0, wheel.size.height / 2) size:CGSizeMake(1, 150) value:0]];
    [wheel addChild:[self createLine:@"counterLine" color:[SKColor yellowColor] position:CGPointMake(wheel.size.width / 2, 0) size:CGSizeMake(150, 1) value:1]];
    [wheel addChild:[self createLine:@"counterLine" color:[SKColor greenColor] position:CGPointMake(0, -wheel.size.height / 2) size:CGSizeMake(1, 150) value:2]];
    [wheel addChild:[self createLine:@"counterLine" color:[SKColor redColor] position:CGPointMake(-wheel.size.width / 2, 0) size:CGSizeMake(150, 1) value:3]];

    //clockwise lines
    [wheel addChild:[self createLine:@"clockwiseLine" color:[SKColor yellowColor] position:CGPointMake(1, wheel.size.height / 2) size:CGSizeMake(1, 150) value:1]];
    [wheel addChild:[self createLine:@"clockwiseLine" color:[SKColor greenColor] position:CGPointMake(wheel.size.width / 2, 1) size:CGSizeMake(150, 1) value:2]];
    [wheel addChild:[self createLine:@"clockwiseLine" color:[SKColor orangeColor] position:CGPointMake(1, -wheel.size.height / 2) size:CGSizeMake(1, 150) value:3]];
    [wheel addChild:[self createLine:@"clockwiseLine" color:[SKColor blueColor] position:CGPointMake(-wheel.size.width / 2, 1) size:CGSizeMake(150, 1) value:0]];
}

- (SKSpriteNode *)createLine:(NSString *)name color:(SKColor *)color position:(CGPoint)position size:(CGSize)size value:(int)value {

    SKSpriteNode *line = [SKSpriteNode spriteNodeWithColor:color size:size];
    line.position = position;
    line.name = name;
    line.userData = [[NSMutableDictionary alloc] init];
    [line.userData setValue:[NSNumber numberWithInt:value] forKey:@"color"];
    line.zPosition = 500;

    return line;
}

#pragma mark - game methods

- (Color)getRandomColorButNotThisColor:(Color)color {

    //recursive method to find unique color other than one currently assigned
    Color randomColor = (int)arc4random_uniform(colorCount);

    if (randomColor == color)
        //same color so try again
        return [self getRandomColorButNotThisColor:color];

    return randomColor;
}

- (void)switchDirection {

    [pin removeAllActions];

    //if they are stopping the pin then it is either going to be correct or game over
    if (enteringColor != currentColor) {

        RLog(@"game over");
        return;
    }

    self.score += 1;

    //find a new color for them to match
    startingColor = currentColor;
    currentColor = [self getRandomColorButNotThisColor:currentColor];
    [self changePinToColor:currentColor];

    //change direction of the spinning pin
    currentDirection = (currentDirection == COUNTERCLOCKWISE) ? CLOCKWISE : COUNTERCLOCKWISE;
    [pin runAction:[SKAction rotateByAngle:2 * M_PI * currentDirection duration:duration]];
}

- (void)resetGame {

    [pin removeAllActions];

    pin.zRotation = 0;

    //reset all variables
    currentColor = startingColor = BLUE;
    [self changePinToColor:currentColor];

    self.score = 0;
    colorCount = 4;
    duration = 5.0;
    currentDirection = COUNTERCLOCKWISE;
    //pin.zRotation = SK_DEGREES_TO_RADIANS(45);
}

- (void)changePinToColor:(Color)color {

    //change the pin color based on the color that they need to match
    SKTexture *pinTexture;

    switch (color) {

        case BLUE:
            pinTexture = [SKTexture textureWithImageNamed:@"blue_pin"];
            break;

        case YELLOW:
            pinTexture = [SKTexture textureWithImageNamed:@"yellow_pin"];
            break;

        case GREEN:
            pinTexture = [SKTexture textureWithImageNamed:@"green_pin"];
            break;

        case RED:
            pinTexture = [SKTexture textureWithImageNamed:@"orange_pin"];
            break;

        default:
            break;
    }

    pin.texture = pinTexture;
}

#pragma mark - game loop methods

- (void)update:(CFTimeInterval)currentTime {

    [self checkForCollisions];
}

- (void)checkForCollisions{

    if (currentDirection == COUNTERCLOCKWISE) {

        [wheel enumerateChildNodesWithName:@"counterLine" usingBlock:^(SKNode *line, BOOL *stop) {

            if ([pin intersectsNode:line]) {

                int amount = [line.userData[@"color"] intValue];

                [line runAction:[gameModel flashRedAction]];

                if (amount != enteringColor) {

                    enteringColor = amount;

                    RLog(@"entered %@", amount == 0 ? @"blue" : amount == 1 ? @"yellow" : amount == 2 ? @"green" : @"red" );

                    if (amount == currentColor - 1 || ((currentColor == 0) && amount == colorCount - 1))
                        RLog(@"game over!");

                    *stop = YES;
                }
            }
        }];
    }
    else {

        [wheel enumerateChildNodesWithName:@"clockwiseLine" usingBlock:^(SKNode *line, BOOL *stop) {

            if ([pin intersectsNode:line]) {

                int amount = [line.userData[@"color"] intValue];

                [line runAction:[gameModel flashRedAction]];

                if (amount != enteringColor) {

                    enteringColor = amount;

                    RLog(@"entered %@", amount == 0 ? @"blue" : amount == 1 ? @"yellow" : amount == 2 ? @"green" : @"red" );

                    if (amount == currentColor + 1 || ((currentColor == colorCount - 1) && amount == 0))
                        RLog(@"game over!");

                    *stop = YES;
                }
            }
        }];
    }
}

enter image description here

1 个答案:

答案 0 :(得分:1)

来自intersectsNode文档,

  如果两个节点的帧相交,则认为它们相交。

节点的帧(即边界框)是

  

父级坐标系中包含节点内容的矩形...

通过观察引脚旋转时产生的边界框(见视频剪辑),很明显为什么使用intersectsNode不是确定引脚在方向盘内位置的可靠方法。

enter image description here

或者,您可以通过

直接从zRotation属性确定引脚的位置
// Make sure angle in [-2pi, 2pi]. It can be a very large number
CGFloat angle = fmod(sprite.zRotation+M_PI_2, 2*M_PI);
// Make sure angle is positive and in [0, 2pi]
angle = angle < 0 ? angle + M_PI*2 : angle;
// Determine which quadrant the pin is in. An integer in [0, 3]
int quadrant =  (int)floor(angle/M_PI_2);

此时,“象限”表示引脚的颜色位置,其中0 =黄色,1 =蓝色,2 =橙色,3 =绿色。