Added rudimentary "Bust" Animation
This commit is contained in:
@@ -33,6 +33,10 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base {
|
||||||
|
archivesName.set("OcheCompanion")
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(libs.appcompat)
|
implementation(libs.appcompat)
|
||||||
implementation(libs.material)
|
implementation(libs.material)
|
||||||
|
|||||||
@@ -123,6 +123,12 @@ public class GameActivity extends BaseActivity {
|
|||||||
*/
|
*/
|
||||||
private boolean mIsTurnOver = false;
|
private boolean mIsTurnOver = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag indicating the current turn resulted in a bust.
|
||||||
|
* Used to prevent UI from subtracting bust darts from the score display.
|
||||||
|
*/
|
||||||
|
private boolean mIsBustedTurn = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class to track dart hit details for statistics.
|
* Helper class to track dart hit details for statistics.
|
||||||
*/
|
*/
|
||||||
@@ -184,6 +190,11 @@ public class GameActivity extends BaseActivity {
|
|||||||
*/
|
*/
|
||||||
private LinearLayout layoutCheckoutSuggestion;
|
private LinearLayout layoutCheckoutSuggestion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Container for displaying the current score.
|
||||||
|
*/
|
||||||
|
private LinearLayout mScoreContainer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Button for selecting single (1×) multiplier.
|
* Button for selecting single (1×) multiplier.
|
||||||
*/
|
*/
|
||||||
@@ -199,6 +210,16 @@ public class GameActivity extends BaseActivity {
|
|||||||
*/
|
*/
|
||||||
private View btnTriple;
|
private View btnTriple;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overlay to be shown when the player busted.
|
||||||
|
*/
|
||||||
|
private View mBustOverlay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Button to submit a turn.
|
||||||
|
*/
|
||||||
|
private MaterialButton mSubmitTurnBtn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Button to open the stats view.
|
* The Button to open the stats view.
|
||||||
*/
|
*/
|
||||||
@@ -329,6 +350,7 @@ public class GameActivity extends BaseActivity {
|
|||||||
outState.putInt("startingScore", mStartingScore);
|
outState.putInt("startingScore", mStartingScore);
|
||||||
outState.putString("matchUuid", mMatchUuid);
|
outState.putString("matchUuid", mMatchUuid);
|
||||||
outState.putBoolean("isTurnOver", mIsTurnOver);
|
outState.putBoolean("isTurnOver", mIsTurnOver);
|
||||||
|
outState.putBoolean("isBustedTurn", mIsBustedTurn);
|
||||||
|
|
||||||
// Save current turn darts
|
// Save current turn darts
|
||||||
int[] dartsArray = new int[mCurrentTurnDarts.size()];
|
int[] dartsArray = new int[mCurrentTurnDarts.size()];
|
||||||
@@ -382,6 +404,7 @@ public class GameActivity extends BaseActivity {
|
|||||||
mStartingScore = savedInstanceState.getInt("startingScore", DartsConstants.DEFAULT_GAME_SCORE);
|
mStartingScore = savedInstanceState.getInt("startingScore", DartsConstants.DEFAULT_GAME_SCORE);
|
||||||
mMatchUuid = savedInstanceState.getString("matchUuid");
|
mMatchUuid = savedInstanceState.getString("matchUuid");
|
||||||
mIsTurnOver = savedInstanceState.getBoolean("isTurnOver", false);
|
mIsTurnOver = savedInstanceState.getBoolean("isTurnOver", false);
|
||||||
|
mIsBustedTurn = savedInstanceState.getBoolean("isBustedTurn", false);
|
||||||
|
|
||||||
// Restore current turn darts
|
// Restore current turn darts
|
||||||
mCurrentTurnDarts.clear();
|
mCurrentTurnDarts.clear();
|
||||||
@@ -443,6 +466,9 @@ public class GameActivity extends BaseActivity {
|
|||||||
tvDartPills[0] = findViewById(R.id.tvDart1);
|
tvDartPills[0] = findViewById(R.id.tvDart1);
|
||||||
tvDartPills[1] = findViewById(R.id.tvDart2);
|
tvDartPills[1] = findViewById(R.id.tvDart2);
|
||||||
tvDartPills[2] = findViewById(R.id.tvDart3);
|
tvDartPills[2] = findViewById(R.id.tvDart3);
|
||||||
|
mBustOverlay = findViewById(R.id.bust_pulse_overlay);
|
||||||
|
mSubmitTurnBtn = findViewById(R.id.btnSubmitTurn);
|
||||||
|
mScoreContainer = findViewById(R.id.scoreContainer);
|
||||||
|
|
||||||
glKeyboard = findViewById(R.id.glKeyboard);
|
glKeyboard = findViewById(R.id.glKeyboard);
|
||||||
|
|
||||||
@@ -458,7 +484,7 @@ public class GameActivity extends BaseActivity {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
findViewById(R.id.btnSubmitTurn).setOnClickListener(v -> submitTurn());
|
mSubmitTurnBtn.setOnClickListener(v -> submitTurn());
|
||||||
findViewById(R.id.btnUndoDart).setOnClickListener(v -> undoLastDart());
|
findViewById(R.id.btnUndoDart).setOnClickListener(v -> undoLastDart());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,10 +566,11 @@ public class GameActivity extends BaseActivity {
|
|||||||
|
|
||||||
updateTurnIndicators();
|
updateTurnIndicators();
|
||||||
mIsTurnOver = true;
|
mIsTurnOver = true;
|
||||||
|
mIsBustedTurn = true;
|
||||||
if (mIsAudioEnabled) {
|
if (mIsAudioEnabled) {
|
||||||
mSoundEngine.playBustedSound();
|
mSoundEngine.playBustedSound();
|
||||||
}
|
}
|
||||||
Toast.makeText(this, "BUST!", Toast.LENGTH_SHORT).show();
|
triggerBustSequence();
|
||||||
// In a pro interface, we usually wait for "Submit" or auto-submit after a short delay
|
// In a pro interface, we usually wait for "Submit" or auto-submit after a short delay
|
||||||
} else if (scoreAfterDart == 0 && isDouble) {
|
} else if (scoreAfterDart == 0 && isDouble) {
|
||||||
// VICTORY CONDITION
|
// VICTORY CONDITION
|
||||||
@@ -571,6 +598,39 @@ public class GameActivity extends BaseActivity {
|
|||||||
setMultiplier(DartsConstants.MULTIPLIER_SINGLE);
|
setMultiplier(DartsConstants.MULTIPLIER_SINGLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void triggerBustSequence() {
|
||||||
|
mIsTurnOver = true;
|
||||||
|
mIsBustedTurn = true;
|
||||||
|
|
||||||
|
// Visual feedback: Shake scoreboard
|
||||||
|
Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake);
|
||||||
|
mScoreContainer.startAnimation(shake);
|
||||||
|
|
||||||
|
// Change scoreboard to Red
|
||||||
|
mScoreContainer.setBackgroundColor(Color.parseColor("#33FF3B30"));
|
||||||
|
tvScorePrimary.setTextColor(ContextCompat.getColor(this, R.color.double_red));
|
||||||
|
|
||||||
|
// Pulsing red overlay on input
|
||||||
|
mBustOverlay.setVisibility(View.VISIBLE);
|
||||||
|
Animation pulse = new AlphaAnimation(0.2f, 0.5f);
|
||||||
|
pulse.setDuration(500);
|
||||||
|
pulse.setRepeatMode(Animation.REVERSE);
|
||||||
|
pulse.setRepeatCount(Animation.INFINITE);
|
||||||
|
mBustOverlay.startAnimation(pulse);
|
||||||
|
|
||||||
|
mSubmitTurnBtn.setText("NEXT PLAYER (BUST)");
|
||||||
|
updateTurnIndicators();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetVisuals() {
|
||||||
|
mScoreContainer.setBackgroundColor(ContextCompat.getColor(this, R.color.surface_primary));
|
||||||
|
tvScorePrimary.setTextColor(ContextCompat.getColor(this, R.color.volt_green));
|
||||||
|
mBustOverlay.clearAnimation();
|
||||||
|
mBustOverlay.setVisibility(View.GONE);
|
||||||
|
mSubmitTurnBtn.setText(R.string.txt_game_btn_submit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for Bull button tap. Delegates to onNumberTap with base value 25.
|
* Handler for Bull button tap. Delegates to onNumberTap with base value 25.
|
||||||
*
|
*
|
||||||
@@ -659,6 +719,7 @@ public class GameActivity extends BaseActivity {
|
|||||||
* Updates player score (unless bust), rotates to next player, resets turn state.
|
* Updates player score (unless bust), rotates to next player, resets turn state.
|
||||||
*/
|
*/
|
||||||
private void submitTurn() {
|
private void submitTurn() {
|
||||||
|
resetVisuals();
|
||||||
// Don't submit if no darts thrown
|
// Don't submit if no darts thrown
|
||||||
if (mCurrentTurnDarts.isEmpty()) return;
|
if (mCurrentTurnDarts.isEmpty()) return;
|
||||||
|
|
||||||
@@ -694,10 +755,9 @@ public class GameActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-check logic for non-double finish or score of 1
|
// Use the mIsBustedTurn flag that was set in onNumberTap when the bust was detected
|
||||||
int lastDartValue = mCurrentTurnDarts.get(mCurrentTurnDarts.size() - 1);
|
// This is more reliable than recalculating since it tracks the actual multiplier used
|
||||||
// Note: this check is redundant but safe for manual "Submit" actions
|
boolean isBust = mIsBustedTurn;
|
||||||
boolean isBust = (finalScore < 0 || finalScore == 1 || (finalScore == 0 && !isFinishDart(mCurrentTurnDarts.size() - 1)));
|
|
||||||
|
|
||||||
// Update score only if not bust
|
// Update score only if not bust
|
||||||
if (!isBust) {
|
if (!isBust) {
|
||||||
@@ -717,6 +777,7 @@ public class GameActivity extends BaseActivity {
|
|||||||
mCurrentTurnDarts.clear();
|
mCurrentTurnDarts.clear();
|
||||||
mCurrentTurnDartHits.clear();
|
mCurrentTurnDartHits.clear();
|
||||||
mIsTurnOver = false;
|
mIsTurnOver = false;
|
||||||
|
mIsBustedTurn = false;
|
||||||
|
|
||||||
// Update UI for next player
|
// Update UI for next player
|
||||||
updateUI();
|
updateUI();
|
||||||
@@ -756,10 +817,12 @@ public class GameActivity extends BaseActivity {
|
|||||||
|
|
||||||
// Allow turn to continue
|
// Allow turn to continue
|
||||||
mIsTurnOver = false;
|
mIsTurnOver = false;
|
||||||
|
mIsBustedTurn = false;
|
||||||
|
|
||||||
// Update displays
|
// Update displays
|
||||||
updateTurnIndicators();
|
updateTurnIndicators();
|
||||||
updateUI();
|
updateUI();
|
||||||
|
resetVisuals();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -782,8 +845,11 @@ public class GameActivity extends BaseActivity {
|
|||||||
tvLegAvg.setText(String.format("AVG: %.1f", avg));
|
tvLegAvg.setText(String.format("AVG: %.1f", avg));
|
||||||
|
|
||||||
// Calculate current target (remaining score minus current turn darts)
|
// Calculate current target (remaining score minus current turn darts)
|
||||||
|
// If it's a busted turn, don't subtract the bust darts from the display
|
||||||
int turnPointsSoFar = 0;
|
int turnPointsSoFar = 0;
|
||||||
for (int d : mCurrentTurnDarts) turnPointsSoFar += d;
|
if (!mIsBustedTurn) {
|
||||||
|
for (int d : mCurrentTurnDarts) turnPointsSoFar += d;
|
||||||
|
}
|
||||||
int currentTarget = active.remainingScore - turnPointsSoFar;
|
int currentTarget = active.remainingScore - turnPointsSoFar;
|
||||||
int dartsRemaining = 3 - mCurrentTurnDarts.size();
|
int dartsRemaining = 3 - mCurrentTurnDarts.size();
|
||||||
|
|
||||||
|
|||||||
@@ -157,6 +157,15 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/bust_pulse_overlay"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:background="#4DFF3B30"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/trackerBar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/dimmer"
|
android:id="@+id/dimmer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -185,6 +194,7 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/winner_text"
|
app:layout_constraintTop_toBottomOf="@id/winner_text"
|
||||||
|
android:layout_marginTop="15dp"
|
||||||
style="@style/Widget.Oche_Button_Primary"
|
style="@style/Widget.Oche_Button_Primary"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone"/>
|
||||||
|
|
||||||
@@ -198,7 +208,6 @@
|
|||||||
android:id="@+id/player_stats_view"
|
android:id="@+id/player_stats_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginTop="15dp"
|
|
||||||
android:visibility="gone"/>
|
android:visibility="gone"/>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
Reference in New Issue
Block a user