in agdk/agde/endless-tunnel/endless-tunnel/Android/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;
}
}
}
}
}