void PlayScene::DetectCollisions()

in endless-tunnel/app/src/main/cpp/play_scene.cpp [669:751]


void PlayScene::DetectCollisions(float previousY) {
    Obstacle *o = GetObstacleAt(0);
    float obsCenter = GetSectionCenterY(mFirstSection);
    float obsMin = obsCenter - OBS_BOX_SIZE;
    float curY = mPlayerPos.y;

    if (!o || !(previousY < obsMin && curY >= obsMin)) {
        // no collision
        return;
    }

    // what row/column is the player on?
    int col = o->GetColAt(mPlayerPos.x);
    int row = o->GetRowAt(mPlayerPos.z);

    if (o->grid[col][row]) {
        // crashed against obstacle
        mLives--;
        if (mLives > 0) {
            ShowSign(S_OUCH, SIGN_DURATION);
            SfxMan::GetInstance()->PlayTone(TONE_CRASHED);
        } else {
            // say "Game Over"
            ShowSign(S_GAME_OVER, SIGN_DURATION_GAME_OVER);
            SfxMan::GetInstance()->PlayTone(TONE_GAME_OVER);
            mGameOverExpire = Clock() + GAME_OVER_EXPIRE;
        }
        mPlayerPos.y = obsMin - PLAYER_RECEDE_AFTER_COLLISION;
        mPlayerSpeed = PLAYER_SPEED_AFTER_COLLISION;
        mBlinkingHeart = true;
        mBlinkingHeartExpire = Clock() + BLINKING_HEART_DURATION;

        mLastCrashSection = mFirstSection;

    } else if (row == o->bonusRow && col == o->bonusCol) {
        ShowSign(S_GOT_BONUS, SIGN_DURATION_BONUS);
        o->DeleteBonus();
        AddScore(BONUS_POINTS);
        mBonusInARow++;

        if (mBonusInARow >= 10) {
            mBonusInARow = 0;
        }

        // update difficulty level, if applicable
        int score = GetScore();
        if (mDifficulty < score / SCORE_PER_LEVEL) {
            mDifficulty = score / SCORE_PER_LEVEL;
            ShowLevelSign();
            mObstacleGen.SetDifficulty(mDifficulty);
            SfxMan::GetInstance()->PlayTone(TONE_LEVEL_UP);

            // save progress, if needed
            SaveProgress();
        } else {
            int tone = (score % SCORE_PER_LEVEL) / BONUS_POINTS - 1;
            tone = tone < 0 ? 0 :
                   tone >= static_cast<int>(sizeof(TONE_BONUS)/sizeof(char*)) ?
                   static_cast<int>(sizeof(TONE_BONUS)/sizeof(char*) - 1) : tone;
            SfxMan::GetInstance()->PlayTone(TONE_BONUS[tone]);
        }

    } else if (o->HasBonus()) {
        // player missed bonus!
        mBonusInARow = 0;
    }

    // was it a close call?
    if (!o->grid[col][row]) {
        bool isCloseCall = false;
        for (int i = -1; i <= 1 && !isCloseCall; i++) {
            for (int j = -1; j <= 1; j++) {
                int other_row = o->GetColAt(mPlayerPos.x + i * CLOSE_CALL_CALC_DELTA);
                int other_col = o->GetRowAt(mPlayerPos.z + j * CLOSE_CALL_CALC_DELTA);
                if (o->grid[other_col][other_row]) {
                    isCloseCall = true;
                    break;
                }
            }
        }

    }
}