package com.novoda.simonsays.game; import android.content.Intent; import android.hardware.usb.UsbManager; import android.os.Bundle; import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.view.KeyEvent; import android.view.View; import android.widget.TextView; import com.novoda.notils.caster.Views; import com.novoda.notils.logger.toast.ToastDisplayer; import com.novoda.notils.logger.toast.ToastDisplayers; import com.novoda.notils.meta.AndroidUtils; import com.novoda.simonsays.BuildConfig; import com.novoda.simonsays.R; import com.novoda.simonsays.highscores.HighscoresActivity; import java.util.ArrayList; import java.util.List; public class GameActivity extends AppCompatActivity { public static final String EXTRA_ROUND_NUMBER = BuildConfig.APPLICATION_ID + "/RoundNumber"; private final List<Integer> playerInput = new ArrayList<>(); enum State { PAUSED, PLAYING_SEQUENCE, AWAITING_PLAYER; } private ToastDisplayer toastDisplayer; private Handler gameHandler; private SequenceShower sequenceShower; private Round currentRound; private State state; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.game_activity); toastDisplayer = ToastDisplayers.noPendingToastsToastDisplayer(this); TextView scoreWidget = Views.findById(this, R.id.game_label_score); View gameButtonA = Views.findById(this, R.id.game_button_a); View gameButtonB = Views.findById(this, R.id.game_button_b); View gameButtonC = Views.findById(this, R.id.game_button_c); View gameButtonD = Views.findById(this, R.id.game_button_d); final List<View> views = new ArrayList<>(); views.add(gameButtonA); views.add(gameButtonB); views.add(gameButtonC); views.add(gameButtonD); int roundNumber = getIntent().getIntExtra(EXTRA_ROUND_NUMBER, 1); RoundCreator roundCreator = new RoundCreator(views); if (savedInstanceState == null) { currentRound = roundCreator.createRound(roundNumber); } else { currentRound = roundCreator.resumeRound(roundNumber); } state = State.PAUSED; gameHandler = new Handler(getMainLooper()); sequenceShower = new SequenceShower( gameHandler, currentRound.getViewSequence(), currentRound.getSpeed() ); gameHandler.postDelayed(sequenceShower, 500); scoreWidget.setText(getString(R.string.score_x, currentRound.getScore())); } private class SequenceShower implements Runnable { private final Handler gameHandler; private final Round.ViewSequence viewSequence; private final long roundSpeed; private SequenceShower(Handler gameHandler, Round.ViewSequence viewSequence, long roundSpeed) { this.gameHandler = gameHandler; this.viewSequence = viewSequence; this.roundSpeed = roundSpeed; } @Override public void run() { Views.findById(GameActivity.this, R.id.game_label_instructions).setVisibility(View.INVISIBLE); state = State.PLAYING_SEQUENCE; if (viewSequence.isComplete()) { state = State.AWAITING_PLAYER; playerInput.clear(); promptForInput(); return; } final View view = viewSequence.next(); final long animationSpeed = roundSpeed / 2; view.animate().alpha(1).setDuration(animationSpeed).setStartDelay(0).withEndAction(new Runnable() { @Override public void run() { view.animate().alpha(0.33f).setDuration(animationSpeed / 2).setStartDelay(animationSpeed / 2).start(); } }).start(); gameHandler.postDelayed(this, roundSpeed); } } private void promptForInput() { UsbManager systemService = (UsbManager) getSystemService(USB_SERVICE); if (systemService.getDeviceList().isEmpty()) { AndroidUtils.toggleKeyboard(GameActivity.this); } else { toastDisplayer.display("Simon Says!"); } } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { return super.onKeyUp(keyCode, event); } if (state != State.AWAITING_PLAYER) { return true; } highlightKeyPressed(keyCode); playerInput.add(keyCode); checkForSequence(); return true; } private void highlightKeyPressed(int keyCode) { if (currentRound.getKeySequence().contains(keyCode)) { int index = currentRound.getKeySequence().indexOf(keyCode); final View sequenceCurrentView = currentRound.getViewSequence().get(index); sequenceCurrentView.animate().alpha(1).setDuration(20).setStartDelay(0).withEndAction(new Runnable() { @Override public void run() { sequenceCurrentView.animate().alpha(0.33f).setDuration(50).setStartDelay(10).start(); } }).start(); } } private void checkForSequence() { Round.KeySequence currentRoundKeySequence = currentRound.getKeySequence(); for (int i = 0; i < currentRoundKeySequence.size(); i++) { if (playerInput.size() <= i) { return; } int expectedKey = currentRoundKeySequence.get(i); int inputtedKey = playerInput.get(i); if (expectedKey == inputtedKey) { // input so far is correct toastDisplayer.display(getString(R.string.aw_yes, KeyEvent.keyCodeToString(inputtedKey))); if (playerInput.size() == currentRoundKeySequence.size()) { // whole sequence is correct state = State.PAUSED; toastDisplayer.display(getString(R.string.moving_to_next_level)); continueToNextLevel(); return; } } else { state = State.PAUSED; // Game over toastDisplayer.displayLong(getString(R.string.incorrect_key, KeyEvent.keyCodeToString(inputtedKey))); continueToHighscores(); return; } } } private void continueToNextLevel() { Intent intent = new Intent(this, GameActivity.class); intent.putExtra(EXTRA_ROUND_NUMBER, currentRound.getNextLevel()); gameHandler.removeCallbacks(sequenceShower); startActivity(intent); finish(); overridePendingTransition(0, 0); } private void continueToHighscores() { Intent intent = new Intent(this, HighscoresActivity.class); intent.putExtra(HighscoresActivity.EXTRA_SCORE, currentRound.getScore()); gameHandler.removeCallbacks(sequenceShower); startActivity(intent); finish(); } @Override protected void onStop() { super.onStop(); gameHandler.removeCallbacks(sequenceShower); } @Override protected void onPause() { super.onPause(); gameHandler.removeCallbacks(sequenceShower); } }