com.SwedishSignAlphabet.Game.java Source code

Java tutorial

Introduction

Here is the source code for com.SwedishSignAlphabet.Game.java

Source

package com.SwedishSignAlphabet;

import com.SwedishSignAlphabet.R;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

/**
 *     Copyright 2012, Grupp02
 * 
 *     This file is part of Handalfabetet.
 *
 *   Handalfabetet is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   Handalfabetet is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with Handalfabetet.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * The Game Activity houses all GUI for the main game.
 * 
 * @author : Grupp02
 * @version : 2012-10-21, v1.0
 */
public class Game extends Activity {

    // Audio Focus helper
    private AudioFocusHelper focusHelper;

    // GameLogic object
    GameLogic gameLogic;

    // Instance Variables
    private ImageView image1;
    private ImageView image2;
    private ImageView image3;
    private ImageButton nextButton;
    private Button firstOptionButton;
    private Button secondOptionButton;
    private Button thirdOptionButton;
    private TextView totalPoint;
    private TextView roundPoint;
    private ProgressBar timerBar;
    private int difficulty;
    private int numLetters;

    private TextView userName;
    private TextView userStatus;

    private Bitmap img;
    private ImageView userImg;
    private int answerID = 0;

    private final int maxProgress = 100;
    private final int difficultyOne = 1;
    private final int oneLetter = 1;
    private final int twoLetters = 2;
    private final int threeLetters = 3;
    private final int firstButton = 1;
    private final int secondButton = 2;
    private final int thirdButton = 3;
    private final int zero = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.game);

        // Make sure we're running on Honeycomb or higher to use ActionBar APIs
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            // getActionBar().setDisplayHomeAsUpEnabled( true );
        }

        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
            focusHelper = new AudioFocusHelper(this);
        } else {
            focusHelper = null;
        }

        // The text prompt view
        TextView questionView = (TextView) findViewById(R.id.question_view);

        // GUI variables
        timerBar = (ProgressBar) findViewById(R.id.timer_bar);

        image1 = (ImageView) findViewById(R.id.image_view1);
        image2 = (ImageView) findViewById(R.id.image_view2);
        image3 = (ImageView) findViewById(R.id.image_view3);
        nextButton = (ImageButton) findViewById(R.id.next_button);
        String pic_blank = "blank";

        // User Image
        userImg = (ImageView) findViewById(R.id.userpic);
        userStatus = (TextView) findViewById(R.id.textView1);
        // Displays the username
        userName = (TextView) findViewById(R.id.textView2);

        // Initialize the layout
        setButtonsAndTextView();

        // Check whether we're recreating a previously destroyed instance
        if (savedInstanceState != null) {

            //basic settings
            difficulty = savedInstanceState.getInt("difficulty");
            numLetters = savedInstanceState.getInt("letters");

            // The game logic object
            gameLogic = new GameLogic(difficulty, numLetters, this);

            //score
            int round = savedInstanceState.getInt("roundScore");
            int total = savedInstanceState.getInt("totalScore");

            gameLogic.setRoundScore(round);
            roundPoint.setText(Integer.toString(round));
            gameLogic.setTotalScore(round);
            totalPoint.setText(Integer.toString(total));

            // Restore name, user status, and user picture
            userName.setText(savedInstanceState.getString("Name"));
            userStatus.setText(savedInstanceState.getString("status"));
            img = savedInstanceState.getParcelable("picture");
            userImg.setImageBitmap(img);

            //statistics
            gameLogic.setTotalTime(savedInstanceState.getInt("totalTime"));
            gameLogic.setNumCorrect(savedInstanceState.getInt("numCorrect"));

            //Buttons and correct sign
            String firstButtonString = savedInstanceState.getString("firstButtonString");
            gameLogic.setFirstButtonString(firstButtonString);
            firstOptionButton.setText(firstButtonString);
            String secondButtonString = savedInstanceState.getString("secondButtonString");
            gameLogic.setSecondButtonString(secondButtonString);
            secondOptionButton.setText(secondButtonString);
            String thirdButtonString = savedInstanceState.getString("thirdButtonString");
            gameLogic.setThirdButtonString(thirdButtonString);
            thirdOptionButton.setText(thirdButtonString);
            gameLogic.setCorrectChoice(savedInstanceState.getString("correctSign"));

            //Pictures
            String firstPicture = savedInstanceState.getString("firstPicture");
            gameLogic.setFirstPicture(firstPicture);
            image1.setImageResource(picSetter(firstPicture));
            String secondPicture = savedInstanceState.getString("secondPicture");
            gameLogic.setSecondPicture(secondPicture);
            image2.setImageResource(picSetter(secondPicture));
            String thirdPicture = savedInstanceState.getString("thirdPicture");
            gameLogic.setThirdPicture(thirdPicture);
            image3.setImageResource(picSetter(thirdPicture));
        } else {
            // game difficulty, default level 1
            difficulty = getIntent().getIntExtra("Difficulty", difficultyOne);
            numLetters = getIntent().getIntExtra("Letters", oneLetter);

            // User Image
            img = (Bitmap) (getIntent().getExtras().getParcelable("userImg"));
            userImg.setImageBitmap(img);
            userStatus.setText(R.string.logged_in);
            // Displays the username
            userName.setText(getIntent().getStringExtra("Name"));

            // The game logic object
            gameLogic = new GameLogic(difficulty, numLetters, this);

            // Changes the picture and button text
            deployTextButtons();

            // Start the ticking noise
            playTicking();
        }

        // Sets up the next button
        nextRound();

        // Depending on one letter, or several letter words, alter the
        // question view text and the button appearance
        if (numLetters > oneLetter) {
            questionView.setText(R.string.word_view);
            nextButton.setBackgroundResource(R.drawable.next_word);
        } else {
            questionView.setText(R.string.letter_view);
            nextButton.setBackgroundResource(R.drawable.next_letter);
        }

        // Have certain pictures blank depending on difficulty level
        if (numLetters == 2) {
            image3.setImageResource(picSetter(pic_blank));
        } else if (numLetters == 1) {
            image2.setImageResource(picSetter(pic_blank));
            image3.setImageResource(picSetter(pic_blank));
        }
    }

    @Override
    /**
     * onResume is overriden in order to utterly abandon sound focus if
     * sound has been turned off, or resume sound if on.
     * 
     */
    public void onResume() {
        super.onResume();

        if (SoundPlayer.getSoundEnabled() == false) {
            if (focusHelper != null) {
                focusHelper.abandonFocus();
            }
            SoundPlayer.stop();
        } else {
            SoundPlayer.resume();
        }

        gameLogic.restartTimer();

        // Sadly this is going to give FULL time again. Have to try to fix this
        // restarts the count down timer
        // gameLogic.getCountDownTimer().start();
    }

    @Override
    public void onPause() {
        super.onPause(); // Always call the superclass method first

        // Pause sound when paused
        if (SoundPlayer.getSoundEnabled()) {
            SoundPlayer.pause();
        }

        // cancels the count down timer, this runs on startup though, so not
        // good
        // gameLogic.getCountDownTimer().cancel();
    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        // Save name, user status, and user picture
        savedInstanceState.putString("Name", userName.getText().toString());
        savedInstanceState.putString("status", userStatus.getText().toString());
        savedInstanceState.putParcelable("picture", img);
        //basic settings
        savedInstanceState.putInt("difficulty", difficulty);
        savedInstanceState.putInt("letters", numLetters);
        //score
        savedInstanceState.putInt("roundScore", gameLogic.getRoundScore());
        savedInstanceState.putInt("totalScore", gameLogic.getTotalScore());
        //time
        savedInstanceState.putInt("timeCount", gameLogic.getTimeCount());
        savedInstanceState.putInt("timeLimit", gameLogic.getTimeLimit());
        //Buttons and correct sign
        savedInstanceState.putString("firstButtonString", gameLogic.getFirstButtonString());
        savedInstanceState.putString("secondButtonString", gameLogic.getSecondButtonString());
        savedInstanceState.putString("thirdButtonString", gameLogic.getThirdButtonString());
        savedInstanceState.putString("correctSign", gameLogic.getCorrectChoice());
        //Pictures
        savedInstanceState.putString("firstPicture", gameLogic.getFirstPicture());
        savedInstanceState.putString("secondPicture", gameLogic.getSecondPicture());
        savedInstanceState.putString("thirdPicture", gameLogic.getThirdPicture());
        //Answer ID
        savedInstanceState.putInt("answer", answerID);
        //statistics
        savedInstanceState.putInt("totalTime", gameLogic.getTotalTime());
        savedInstanceState.putInt("numCorrect", gameLogic.getNumCorrect());

        // Always call the superclass so it can save the view hierarchy state
        super.onSaveInstanceState(savedInstanceState);
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        // Always call the superclass so it can restore the view hierarchy
        super.onRestoreInstanceState(savedInstanceState);

        //If the save is a valid one, restore the game
        if (getValidInstance()) {
            //time
            int timeCount = savedInstanceState.getInt("timeCount");
            gameLogic.setTimeCount(timeCount);
            int tickTime = 1000;

            //Answer ID
            answerID = savedInstanceState.getInt("answer");

            //If the timer was on it's way down and an answer wasn't given,
            //the timer should start where it left off
            if (timeCount < 10 && timeCount > 0 && answerID == 0) {
                int timeLimit = savedInstanceState.getInt("timeLimit");
                gameLogic.setTimeLimit(timeLimit - (timeCount * tickTime));
                gameLogic.restartTimer();

                // Start the ticking noise
                //playTicking();                
            }
            //If an answer was given, restore that state
            else if (answerID != 0) {
                gameLogic.getCountDownTimer().cancel();

                firstOptionButton.setEnabled(false);
                secondOptionButton.setEnabled(false);
                thirdOptionButton.setEnabled(false);

                switch (answerID) {

                case R.id.first_opt_button:

                    if (gameLogic.getCorrectButton() == firstButton) {
                        firstOptionButton.setBackgroundColor(android.graphics.Color.GREEN);
                    } else {
                        firstOptionButton.setBackgroundColor(android.graphics.Color.RED);
                    }
                    break;

                case R.id.second_opt_button:

                    if (gameLogic.getCorrectButton() == secondButton) {
                        secondOptionButton.setBackgroundColor(android.graphics.Color.GREEN);
                    } else {
                        secondOptionButton.setBackgroundColor(android.graphics.Color.RED);
                    }
                    break;

                case R.id.third_opt_button:

                    if (gameLogic.getCorrectButton() == thirdButton) {
                        thirdOptionButton.setBackgroundColor(android.graphics.Color.GREEN);
                    } else {
                        thirdOptionButton.setBackgroundColor(android.graphics.Color.RED);
                    }
                    break;
                }

                // Enable the next letter/word button
                nextButton.setEnabled(true);
            }
            //If time stopped make sure the countdown timer has stopped
            else if (timeCount <= 0) {
                gameLogic.getCountDownTimer().cancel();
            }

            timerBar.setProgress(timeCount * tickTime);
        }
        //Otherwise create a new game round
        else {
            // game difficulty, default level 1
            difficulty = getIntent().getIntExtra("Difficulty", difficultyOne);
            numLetters = getIntent().getIntExtra("Letters", oneLetter);

            gameLogic.setDiffLevel(difficulty);
            gameLogic.setNumLetters(numLetters);

            // User Image
            img = (Bitmap) (getIntent().getExtras().getParcelable("userImg"));
            userImg.setImageBitmap(img);
            userStatus.setText(R.string.logged_in);
            // Displays the username
            userName.setText(getIntent().getStringExtra("Name"));

            // Changes the picture and button text
            deployTextButtons();

            // Start the ticking noise
            playTicking();
        }
    }

    /**
     * getValidInstance
     */
    private boolean getValidInstance() {

        if (firstOptionButton.getText().toString() != null && firstOptionButton.getText().toString() != ""
                && secondOptionButton.getText().toString() != null && secondOptionButton.getText().toString() != ""
                && thirdOptionButton.getText().toString() != null && thirdOptionButton.getText().toString() != ""
                && image1.getDrawable() != null) {

            if (difficulty == 3) {
                if (image3.getDrawable() != null && image2.getDrawable() != null
                        && firstOptionButton.getText().toString().length() == 3) {
                    return true;
                }
            } else if (difficulty == 2) {
                if (image2.getDrawable() != null && firstOptionButton.getText().toString().length() == 2) {
                    return true;
                }
            } else { //difficulty 1
                if (firstOptionButton.getText().toString().length() == 1) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * getTimerBar
     * 
     * @return : returns the ProgressBar object timerBar
     */
    public ProgressBar getTimerBar() {
        return timerBar;
    }

    /**
     * Initiate buttons and textViews
     */
    private void setButtonsAndTextView() {

        firstOptionButton = (Button) findViewById(R.id.first_opt_button);
        secondOptionButton = (Button) findViewById(R.id.second_opt_button);
        thirdOptionButton = (Button) findViewById(R.id.third_opt_button);

        totalPoint = (TextView) findViewById(R.id.show_total_points);
        roundPoint = (TextView) findViewById(R.id.show_round_points);
    }

    /**
     * Displays the score on the screen
     */
    private void scoreCounter() {
        gameLogic.scoreCounter();
        totalPoint.setText(Integer.toString(gameLogic.getTotalScore()));
        roundPoint.setText(Integer.toString(gameLogic.getRoundScore()));
    }

    /**
     * Sets the green color on the button the player clicked for correct answer
     * and red for wrong answer
     * 
     * @param v
     *            Clicked answer button
     */
    public void markButtonsAfterClicked(View v) {

        // stop the clock ticking sound, and play the button sound
        SoundPlayer.stop();
        playButton();

        // cancels the count down timer
        gameLogic.getCountDownTimer().cancel();

        int button_id = v.getId();
        answerID = button_id;

        //Set the answer and activate the next button
        setAnswer(button_id);
    }

    /**
     * setAnswer sets the answer and activate the next button
     */
    private void setAnswer(int button_id) {

        firstOptionButton.setEnabled(false);
        secondOptionButton.setEnabled(false);
        thirdOptionButton.setEnabled(false);

        switch (button_id) {

        case R.id.first_opt_button:

            if (gameLogic.getCorrectButton() == firstButton) {
                firstOptionButton.setBackgroundColor(android.graphics.Color.GREEN);
                scoreCounter();
                playRightChoice();
            } else {
                firstOptionButton.setBackgroundColor(android.graphics.Color.RED);
                playWrongChoice();
            }
            break;

        case R.id.second_opt_button:

            if (gameLogic.getCorrectButton() == secondButton) {
                secondOptionButton.setBackgroundColor(android.graphics.Color.GREEN);
                scoreCounter();
                playRightChoice();
            } else {
                secondOptionButton.setBackgroundColor(android.graphics.Color.RED);
                playWrongChoice();
            }
            break;

        case R.id.third_opt_button:

            if (gameLogic.getCorrectButton() == thirdButton) {
                thirdOptionButton.setBackgroundColor(android.graphics.Color.GREEN);
                scoreCounter();
                playRightChoice();
            } else {
                thirdOptionButton.setBackgroundColor(android.graphics.Color.RED);
                playWrongChoice();
            }
            break;
        }

        // Enable the next letter/word button
        nextButton.setEnabled(true);
    }

    /**
     * playRightChoice
     * 
     * Unlike playButton, this also plays a vibration, so it is called as long
     * as sound or vibrations are enabled.
     */
    public void playRightChoice() {
        if (SoundPlayer.getSoundEnabled() || SoundPlayer.getVibrationEnabled()) {
            if (focusHelper != null) {
                if (getAudioFocus()) {
                    focusHelper.playRightChoice();
                }
            } else {
                SoundPlayer.playRightChoice(this);
            }
        }
    }

    /**
     * playWrongChoice
     * 
     * Unlike playButton, this also plays a vibration, so it is called as long
     * as sound or vibrations are enabled.
     */
    public void playWrongChoice() {
        if (SoundPlayer.getSoundEnabled() || SoundPlayer.getVibrationEnabled()) {
            if (focusHelper != null) {
                if (getAudioFocus()) {
                    focusHelper.playWrongChoice();
                }
            } else {
                SoundPlayer.playWrongChoice(this);
            }
        }
    }

    /**
     * Changes the sign image when nextButton is clicked
     */
    private void nextRound() {

        // Disable the next letter/word button
        nextButton.setEnabled(false);

        nextButton.setOnClickListener(new OnClickListener() {
            public void onClick(View arg0) {
                //Reset the answer variable
                answerID = 0;
                // play the button sound
                playButton();

                // If all game rounds have completed, bring up the end screen
                if (gameLogic.countDownRounds()) {
                    // kills current activity
                    finish();

                    Intent endIntent = new Intent("android.intent.action.GAMEEND");
                    endIntent.putExtra("NumCorrect", gameLogic.getNumCorrect());
                    endIntent.putExtra("TotalScore", gameLogic.getTotalScore());
                    endIntent.putExtra("AverageTime", gameLogic.getAverageTime());
                    endIntent.putExtra("Difficulty", difficulty);
                    endIntent.putExtra("Letters", numLetters);
                    endIntent.putExtra("name", getIntent().getStringExtra("Name"));
                    endIntent.putExtra("userImg", img);
                    startActivity(endIntent);
                } else {
                    // start clock ticking
                    playTicking();

                    // Reset round points to 0
                    roundPoint.setText(Integer.toString(zero));

                    // Reset answer button backgrounds
                    firstOptionButton.setBackgroundColor(android.graphics.Color.LTGRAY);
                    secondOptionButton.setBackgroundColor(android.graphics.Color.LTGRAY);
                    thirdOptionButton.setBackgroundColor(android.graphics.Color.LTGRAY);

                    // Enable answer buttons
                    firstOptionButton.setEnabled(true);
                    secondOptionButton.setEnabled(true);
                    thirdOptionButton.setEnabled(true);

                    // Get text for buttons and disable next button
                    deployTextButtons();
                    nextButton.setEnabled(false);

                    // Reset the timer
                    timerBar.setProgress(maxProgress);
                    gameLogic.resetTimeCount();
                    // (re)starts the count down timer
                    //gameLogic.getCountDownTimer().start();
                }
            }
        });
    }

    /**
     * Sets random letters to the buttons and the correct letter for the shown
     * sign.
     */
    private void deployTextButtons() {
        // Determine sign picture and button text
        gameLogic.determineChoices();

        // Set the picture
        image1.setImageResource(picSetter(gameLogic.getFirstPicture()));

        if (numLetters >= twoLetters) {
            image2.setImageResource(picSetter(gameLogic.getSecondPicture()));
        }
        if (numLetters == threeLetters) {
            image3.setImageResource(picSetter(gameLogic.getThirdPicture()));
        }

        // Set the button text
        firstOptionButton.setText(gameLogic.getFirstButtonString());
        secondOptionButton.setText(gameLogic.getSecondButtonString());
        thirdOptionButton.setText(gameLogic.getThirdButtonString());
    }

    /**
     * Gets the id for the sign image letter/word
     * 
     * @param word
     * @return the id number
     */
    private int picSetter(String word) {
        int resource;

        if (word.equals(Character.toString(''))) {
            resource = getResources().getIdentifier("ae", "drawable", "com.SwedishSignAlphabet");
        } else if (word.equals(Character.toString(''))) {
            resource = getResources().getIdentifier("ao", "drawable", "com.SwedishSignAlphabet");
        } else if (word.equals(Character.toString(''))) {
            resource = getResources().getIdentifier("oe", "drawable", "com.SwedishSignAlphabet");
        } else {
            resource = getResources().getIdentifier(word, "drawable", "com.SwedishSignAlphabet");
        }

        return resource;
    }

    /**
     * The getAudioFocus method attempts to gain focus for playing audio. If
     * full access can't be gained, transitive access at a quiet volume is
     * attempted. If that can't be granted, false is returned.
     * 
     * @return : true if focus in some form is granted, otherwise false
     */
    private boolean getAudioFocus() {

        if (focusHelper != null) {
            if (!focusHelper.requestFocus()) {
                if (!focusHelper.requestQuietFocus()) {
                    return false;
                } else {
                    return true;
                }
            } else {
                return true;
            }
        }

        return false;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_game, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            NavUtils.navigateUpFromSameTask(this);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * playButton plays the button sound
     * 
     * If there is an AudioFocusHelper (api >= 8) use it, otherwise default to
     * SoundPlayer
     */
    public void playButton() {
        if (SoundPlayer.getSoundEnabled()) {
            if (focusHelper != null) {
                if (getAudioFocus()) {
                    focusHelper.playButton();
                }
            } else {
                SoundPlayer.playButton(this);
            }
        }
    }

    /**
     * playTicking plays the ticking sound
     * 
     * If there is an AudioFocusHelper (api >= 8) use it, otherwise default to
     * SoundPlayer
     */
    public void playTicking() {
        if (SoundPlayer.getSoundEnabled()) {
            if (focusHelper != null) {
                if (getAudioFocus()) {
                    focusHelper.playTicking();
                }
            } else {
                SoundPlayer.playTicking(this);
            }
        }
    }

    /**
     * onStop is called when the activity is shut down, usually before being
     * destroyed. We need to stop the timer and media players to properly free
     * up memory. The focus helper should lose focus anyway, but no reason not
     * to tie up loose ends.
     */
    @Override
    public void onStop() {
        // cancels the count down timer
        gameLogic.getCountDownTimer().cancel();

        // call the super method
        super.onStop();
    }

    /**
     * onKeyDown overrides onKeyDown and allows code to be executed when the
     * back button is pushed in the simulator / on the mobile phone Since
     * pushing "back" won't necessarily call the destroy method as far as I
     * understand it.
     * 
     * @param keyCode
     *            : code of the key pressed
     * @param event
     *            : the event for the key pressed
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == zero) {

            //This code cannot be in onStop in Game because
            //it also kills the applause noise as GameEnd begins      
            // cancel any noises and abandon focus
            SoundPlayer.stop();
            if (focusHelper != null) {
                focusHelper.abandonFocus();
            }

            // continue backwards (kills current activity)
            finish();

            return true;
        }

        return super.onKeyDown(keyCode, event);
    }
}