Tell me more ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm building a platformer in cocos2d, my first game project. I'm working on movement and collision detection. I'm using a tilemap with a "meta" layer of invisible blocks that are designated collidable.

Everything seems to work pretty well except for one minor detail: when the character jumps from above into a platform, he does not fall but clips through it. If he jumps from below, it recognizes it and resets his Y velocity accordingly. I know that it's because of how I'm detecting the collisions, and just doing a simple comparison of the origin.y's, but I'm unsure of how to refactor this code better:

- (void) update: (ccTime) dt {
    CGPoint scaledVelocity = ccpMult(leftJoystick.velocity, 35.0f);
    CGPoint newPosition = ccp(player.position.x + scaledVelocity.x * dt, player.position.y);
    CGPoint oldPosition = [player position];

    float velocityX = player.Velocity.x + scaledVelocity.x * dt;
    float velocityY = player.Velocity.y;

    BOOL isCollision = NO;
    BOOL isCollisionBelow = NO;
    BOOL isCollisionRight = NO;
    BOOL isCollisionLeft = NO;

    NSMutableArray* collisionSprites = [[NSMutableArray alloc] init];

    if (oldPosition.x > newPosition.x) {
        player.flipX = YES;
    }
    else if (oldPosition.x < newPosition.x) {
        player.flipX = NO;
    }

    for (CCSprite* sprite in gameplayLayer.collidableTiles) {
        if (CGRectIntersectsRect(player.boundingBox, sprite.boundingBox)) {
            isCollision = YES;
            [collisionSprites addObject:sprite];
        }
    }

    // Figure out which direction collision is in
    if (isCollision) {
        for (CCSprite* collisionSprite in collisionSprites) {
            if (collisionSprite.boundingBox.origin.y < player.boundingBox.origin.y) {
                isCollisionBelow = YES;
            }
            if ((collisionSprite.boundingBox.origin.x > player.boundingBox.origin.x) && (collisionSprite.boundingBox.origin.y >= player.boundingBox.origin.y)) {
                isCollisionRight = YES;
            }
            if ((collisionSprite.boundingBox.origin.x < player.boundingBox.origin.x) && (collisionSprite.boundingBox.origin.y >= player.boundingBox.origin.y)) {
                isCollisionLeft = YES;
            }
        }
    }

    if (isCollisionLeft) {
        velocityX = 0.5f;
    }
    else if (isCollisionRight) {
        velocityX = -0.5f;
    }

    if (isCollision && !isCollisionBelow && player.characterState != kStateFalling) {
        velocityY = 0;
        velocityY -= 0.8f;
        [player setCharacterState:kStateFalling];
    }
    else if (!isCollisionBelow) {
        velocityY -= 0.7f;
    }
    else if (isCollisionBelow) {
        velocityY = 0;
        [player setCharacterState:kStateIdle];
    }

    if (rightButton.active) {            
        if (player.characterState != kStateJumping) {
            velocityY += 15.0f;
            [player setCharacterState:kStateJumping];
        }
    }

    // Ground friction
    if (player.Velocity.x > 0) {
        if (player.Velocity.x < 0.5f) {
            velocityX = 0;
        }
        else {
            velocityX -= 0.5f;
        }
    }

    if (player.Velocity.x < 0) {
        velocityX += 0.5f;
    }

    [player setVelocity:ccp(velocityX, velocityY)];
    [player setPosition: ccp(player.position.x + player.Velocity.x, player.position.y + player.Velocity.y)];
    [gameplayLayer setViewpointCenter:newPosition];
    [player setOldPosition: player.position];
}

How can I refactor this code to work properly from all angles and reduce the complexity (I feel that there's too many booleans, and they all get a bit confusing).

share|improve this question
2  
I take it this code is example code from somewhere? There's already logic to detect collisions from the bottom and sides; mirror those code blocks for a new boolean isCollisionAbove, making the necessary changes to the logic. – chaosTechnician Sep 5 '11 at 4:36

1 Answer

As far as I know the Boundingbox rect has two properties origin and size. to check if some obejct is colliding from any of the sides you have to check both values: so I suggest you change your code like following :

if (CGRectMaxY(collisionSprite.boundingBox) < CGRectMinY(player.boundingBox)) {
    isCollisionBelow = YES;
}
if (CGRectMaxX(collisionSprite.boundingBox) < CGRectMinX(player.boundingBox)) {
    isCollisionRight = YES;
}
if (CGRectMinX(collisionSprite.boundingBox) > CGRectMaxX(player.boundingBox)) {
    isCollisionLeft = YES;
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.