GameBoard5.java :  » Game » pattern-puzzler » com » games » rm » patternpuzzler » Android Open Source

Android Open Source » Game » pattern puzzler 
pattern puzzler » com » games » rm » patternpuzzler » GameBoard5.java
/*
 * Copyright (C) 2010 Ryan Morton
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.games.rm.patternpuzzler;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class GameBoard5 extends Activity implements OnClickListener,OnTouchListener, CountdownTimerFinishedListener
{
private final float LEFT_VOLUME = GameBoard4.LEFT_VOLUME, RIGHT_VOLUME = GameBoard4.RIGHT_VOLUME;
  
  //main layouts**********/
  private RelativeLayout redButtonLayout;
  private RelativeLayout yellowButtonLayout;
  private RelativeLayout blueButtonLayout;
  private RelativeLayout greenButtonLayout;
  private RelativeLayout orangeButtonLayout;
  private LinearLayout statusbarLayout;
  private LinearLayout pauseMenuLayout;
  private LinearLayout successLayout;
  private LinearLayout failLayout;
  private TextView countdownTimerText;
  
  //buttons*************/
  private ImageView redButtonTop;
  private ImageView redButtonLight;
  private ImageView yellowButtonTop;
  private ImageView yellowButtonLight;
  private ImageView blueButtonTop;
  private ImageView blueButtonLight;
  private ImageView greenButtonTop;
  private ImageView greenButtonLight;
  private ImageView orangeButtonTop;
  private ImageView orangeButtonLight;
  private ImageView forwardButton;
  private ImageView replayButton;
  private ImageView pauseButton;
  private TextView resumeButton;
  private RadioGroup fxRadioGroup;
  private RadioButton fxOnRadioButton;
  private RadioButton fxOffRadioButton;
  
  //other things***********/
  private TextView levelTextBox;
  private boolean buttonsActive;
  private boolean statusbarActive;
  private boolean showingPattern;
  private boolean isGameOver;
  private boolean replayResetUsed;
  private boolean soundFxOn;
  private Animation[] animationCache;
  private CountdownTimer myCountdownTimer;
  private HashMap<Integer, ImageView> lightedButtonMap;
  private ArrayList<Integer> myPattern;
  private int currentPatternIndex; //this stores the current index of the pattern ... to check against user input
  private Random randomGen;
  private PatternPlayer myPatternPlayer;
  private Savegame mySaveGame;
  private HashMap<ImageView,MediaPlayer> soundCache;
  HashMap<ImageView, MediaPlayer> patternPlayerSoundCache;
  
  @Override
  protected void onCreate(Bundle savedInstanceState)
  {
    //System.out.println("onCreate");
    super.onCreate(savedInstanceState);
    //set up the window properties
        Utilities.setupActivityWindow(this);
        
        //inflate the main layout
        this.setContentView(R.layout.game_board_5);
        
        //run the init();
        this.init();
        
        //go to onResume for what happens next
  }
  
  /***
     * initialize the variables
     */
  private void init()
  {
    //init animation cache
    animationCache = new Animation[2];
    animationCache[0] = AnimationUtils.loadAnimation(this, R.anim.fade_in_buttons);
    animationCache[1] = AnimationUtils.loadAnimation(this, R.anim.fade_in_200);
    
    //init layouts************/
    redButtonLayout = (RelativeLayout)this.findViewById(R.id.GameBoard_5_Red_Button_Layout);
    yellowButtonLayout = (RelativeLayout)this.findViewById(R.id.GameBoard_5_Yellow_Button_Layout);
    blueButtonLayout = (RelativeLayout)this.findViewById(R.id.GameBoard_5_Blue_Button_Layout);
    greenButtonLayout = (RelativeLayout)this.findViewById(R.id.GameBoard_5_Green_Button_Layout);
    orangeButtonLayout = (RelativeLayout)this.findViewById(R.id.GameBoard_5_Orange_Button_Layout);
    statusbarLayout = (LinearLayout)this.findViewById(R.id.GameBoard_5_StatusBar_Layout);
    pauseMenuLayout = (LinearLayout)this.findViewById(R.id.GameBoard_5_Pause_Menu_Layout);
    successLayout = (LinearLayout)this.findViewById(R.id.GameBoard_5_Success_Layout);
    failLayout = (LinearLayout)this.findViewById(R.id.GameBoard_5_Fail_Layout);
    countdownTimerText = (TextView)this.findViewById(R.id.GameBoard_5_Countdown);
    
    //init buttons**************/
    redButtonTop = (ImageView)redButtonLayout.findViewById(R.id.GameBoard_5_Red_Button);
    redButtonLight = (ImageView)redButtonLayout.findViewById(R.id.GameBoard_5_Red_Button_On);
    yellowButtonTop = (ImageView)yellowButtonLayout.findViewById(R.id.GameBoard_5_Yellow_Button);
    yellowButtonLight = (ImageView)yellowButtonLayout.findViewById(R.id.GameBoard_5_Yellow_Button_On);
    blueButtonTop = (ImageView)blueButtonLayout.findViewById(R.id.GameBoard_5_Blue_Button);
    blueButtonLight = (ImageView)blueButtonLayout.findViewById(R.id.GameBoard_5_Blue_Button_On);
    greenButtonTop = (ImageView)greenButtonLayout.findViewById(R.id.GameBoard_5_Green_Button);
    greenButtonLight = (ImageView)greenButtonLayout.findViewById(R.id.GameBoard_5_Green_Button_On);
    orangeButtonTop = (ImageView) orangeButtonLayout.findViewById(R.id.GameBoard_5_Orange_Button);
    orangeButtonLight = (ImageView) orangeButtonLayout.findViewById(R.id.GameBoard_5_Orange_Button_On);
    forwardButton = (ImageView)statusbarLayout.findViewById(R.id.GameBoard_5_StatusBar_Forward_Button);
    replayButton = (ImageView)statusbarLayout.findViewById(R.id.GameBoard_5_StatusBar_Replay_Button);
    pauseButton = (ImageView)statusbarLayout.findViewById(R.id.GameBoard_5_StatusBar_Pause_Button);
    resumeButton = (TextView)pauseMenuLayout.findViewById(R.id.GameBoard_5_Pause_Menu_Resume_Game_Button);
    fxRadioGroup = (RadioGroup)this.findViewById(R.id.GameBoard_5_Pause_Menu_FxGroup);
    fxOffRadioButton = (RadioButton)fxRadioGroup.findViewById(R.id.GameBoard_5_Pause_Menu_Fx_Off);
    fxOnRadioButton = (RadioButton)fxRadioGroup.findViewById(R.id.GameBoard_5_Pause_Menu_Fx_On);
    /*according to the Android JAVA Doc, the code below increases performance:
    "Setting a solid background color for the drawing cache's bitmaps will improve performance and memory usage.
    Note, though that this should only be used if this view will always be drawn on top of a solid color."
    */
    redButtonLight.setDrawingCacheBackgroundColor(Color.BLACK);
    yellowButtonLight.setDrawingCacheBackgroundColor(Color.BLACK);
    blueButtonLight.setDrawingCacheBackgroundColor(Color.BLACK);
    greenButtonLight.setDrawingCacheBackgroundColor(Color.BLACK);
    //set onTouch/onClick listeners
    redButtonTop.setOnTouchListener(this);
    yellowButtonTop.setOnTouchListener(this);
    blueButtonTop.setOnTouchListener(this);
    greenButtonTop.setOnTouchListener(this);
    orangeButtonTop.setOnTouchListener(this);
    forwardButton.setOnClickListener(this);
    replayButton.setOnClickListener(this);
    pauseButton.setOnClickListener(this);
    resumeButton.setOnClickListener(this);
    fxOffRadioButton.setOnClickListener(this);
    fxOnRadioButton.setOnClickListener(this);
    
    //init other things****************/
    levelTextBox = (TextView)statusbarLayout.findViewById(R.id.GameBoard_5_StatusBar_Level_Text);
    buttonsActive = false;
    statusbarActive = false;
    showingPattern = false;
    isGameOver = false;
    replayResetUsed = false;
    soundFxOn = Utilities.loadSettings(this).isSoundOn();
    randomGen = new Random(System.currentTimeMillis());
    lightedButtonMap = new HashMap<Integer, ImageView>(5);
    lightedButtonMap.put(1, redButtonLight);
    lightedButtonMap.put(2, yellowButtonLight);
    lightedButtonMap.put(3, blueButtonLight);
    lightedButtonMap.put(4, greenButtonLight);
    lightedButtonMap.put(5, orangeButtonLight);
    //create gameboard sound caches... one for this, and one for the pattern player
    soundCache = new HashMap<ImageView, MediaPlayer>(5);
    patternPlayerSoundCache = new HashMap<ImageView, MediaPlayer>(5);
    MediaPlayer currentMP = MediaPlayer.create(this, R.raw.fx_430);
    currentMP.setLooping(true);
    currentMP.setVolume(LEFT_VOLUME,RIGHT_VOLUME);
    soundCache.put(redButtonTop, currentMP);
    patternPlayerSoundCache.put(redButtonLight, currentMP);
    currentMP = MediaPlayer.create(this, R.raw.fx_530);
    currentMP.setLooping(true);
    currentMP.setVolume(LEFT_VOLUME,RIGHT_VOLUME);
    soundCache.put(yellowButtonTop, currentMP);
    patternPlayerSoundCache.put(yellowButtonLight, currentMP);
    currentMP = MediaPlayer.create(this, R.raw.fx_630);
    currentMP.setLooping(true);
    currentMP.setVolume(LEFT_VOLUME,RIGHT_VOLUME);
    soundCache.put(blueButtonTop, currentMP);
    patternPlayerSoundCache.put(blueButtonLight, currentMP);
    currentMP = MediaPlayer.create(this, R.raw.fx_730);
    currentMP.setLooping(true);
    currentMP.setVolume(LEFT_VOLUME,RIGHT_VOLUME);
    soundCache.put(greenButtonTop, currentMP);
    patternPlayerSoundCache.put(greenButtonLight, currentMP);
    currentMP = MediaPlayer.create(this, R.raw.fx_830);
    currentMP.setLooping(true);
    currentMP.setVolume(LEFT_VOLUME,RIGHT_VOLUME);
    soundCache.put(orangeButtonTop, currentMP);
    patternPlayerSoundCache.put(orangeButtonLight, currentMP);
    myCountdownTimer = new CountdownTimer(countdownTimerText, new Handler());
    //buttonLighter = new Handler();
    myPatternPlayer = new PatternPlayer(Utilities.loadSettings(this).shouldSpeedIncrease(),
        lightedButtonMap,patternPlayerSoundCache, this, new Handler());
    myPattern = myPatternPlayer.getPattern();
    myCountdownTimer.setTimerListener(this);
  }
  /***
   * this is only called when the activity is first initialized/created
   */
  private void startFirstRun()
  {
    //start button animations
    redButtonLayout.startAnimation(animationCache[0]);
    yellowButtonLayout.startAnimation(animationCache[0]);
    blueButtonLayout.startAnimation(animationCache[0]);
    greenButtonLayout.startAnimation(animationCache[0]);
    orangeButtonLayout.startAnimation(animationCache[0]);
    
    //start the countdown timer... delay execution for 1 sec.
    new Handler().postDelayed(new Runnable() {
      
      @Override
      public void run()
      {
        GameBoard5.this.countdownTimerText.setVisibility(View.VISIBLE);
        GameBoard5.this.myCountdownTimer.start();
      }
    }, 1000);
  }
  
  /***
   * this starts the game after a savegame is loaded
   */
  private void startFromSavedGame(boolean wasLevelCompleted)
  {
    //disable buttons
    buttonsActive = false;
    statusbarActive = false;
    
    levelTextBox.setText(String.format("%03d",myPattern.size()));
    
    if(wasLevelCompleted)
    {
      this.beginNewLevel();
      return;
    }
    
    //restart the countdown timer... delay execution for 1 sec.
    new Handler().postDelayed(new Runnable() {
      
      @Override
      public void run()
      {
        GameBoard5.this.countdownTimerText.setVisibility(View.VISIBLE);
        GameBoard5.this.myCountdownTimer.restart();
      }
    }, 1000);
  }
  
  /***
   * this starts the countdown timer at the beginning of levels != 1
   */
  private void beginNewLevel()
  {
    //disable buttons
    buttonsActive = false;
    statusbarActive = false;
    
    //increase the level number
    final int currentLevel = Integer.parseInt(levelTextBox.getText().toString());
    levelTextBox.setText(String.format("%03d",(currentLevel+1)));
    
    //restart the countdown timer... delay execution for 1 sec.
    new Handler().postDelayed(new Runnable() {
      
      @Override
      public void run()
      {
        GameBoard5.this.countdownTimerText.setVisibility(View.VISIBLE);
        GameBoard5.this.myCountdownTimer.restart();
      }
    }, 1000);
  }

  @Override
  public void onCountdownFinished()
  {
    countdownTimerText.setVisibility(View.GONE);
    
    //start showing the pattern... delay for 500 ms
    new Handler().postDelayed(new Runnable() {
      
      @Override
      public void run()
      {
        GameBoard5.this.showThePattern();
      }
    }, 500);
  }
  
  /***
   * Starts the display of the lighted button sequence. When finished, the user
   * is allowed to try and repeat the pattern. 
   */
  private void showThePattern()
  {
    showingPattern = true;
    if(mySaveGame!=null)
    {
      if(!mySaveGame.getIsLevelComplete())
      {
        //just show the pattern
        myPatternPlayer.playPattern(false);
        mySaveGame = null;//important... so this code block isn't called again
        return;
      }
    }
    
    //add new button to the pattern
    final int nextButton = this.getNextRandomNumber(1, 5);
    //System.out.println(""+nextButton);
    myPatternPlayer.add(nextButton);
    myPatternPlayer.playPattern(false);
  }
  
  /***
   * starts the portion of the game that allows for user input of the pattern guess
   */
  public void startGame()
  {
    //make the replayButton visible every 5 turns if it isn't already
    if(Integer.parseInt(levelTextBox.getText().toString())%5 == 1 && replayButton.getVisibility()==View.INVISIBLE && !replayResetUsed)
    {
      replayButton.setVisibility(View.VISIBLE);
      replayResetUsed = true;
    }
    currentPatternIndex = 0;
    //set the buttons active for user input
    buttonsActive = true;
    statusbarActive = true;
    showingPattern = false;
  }
  
  /**
   * ends the current game and allows the use to go back to the main menu
   */
  private void gameOver()
  {
    Utilities.deleteSavegame(this);
    Utilities.addHighScore(this, Utilities.GAME_TYPE_5_BUTTON, Integer.parseInt(levelTextBox.getText().toString()));
    buttonsActive = false;
    isGameOver = true;
    failLayout.setVisibility(View.VISIBLE);
    forwardButton.setVisibility(View.VISIBLE);
  }
  
  public boolean isSoundOn()
  {
    return soundFxOn;
  }
  
  /**
   * Checks the if the user has entered the entire pattern
   * @return true if the currentPatternIndex == the myPattern.size()... false otherwise
   */
  private boolean isLevelComplete()
  {
    return (currentPatternIndex == myPattern.size());
  }
  
  /***
   * The user has completed a level. This shows the appropriate message and sets conditions for the next level.
   * The program will now wait for the user to touch the => icon to continue.
   */
  private void levelUp()
  {
    System.gc();//good time to free up resources
    buttonsActive = false;
    successLayout.setVisibility(View.VISIBLE);
    forwardButton.setVisibility(View.VISIBLE);
  }
  
  /***
   * Returns a random number in the passed integer range
   * @param min
   * @param max
   * @return an int between [min, max] (inclusive)
   */
  private int getNextRandomNumber(int min, int max)
  {
    return (min + (int)(randomGen.nextDouble() * ((max - min) + 1)));
  }
  
  /***************Section Below Handles Touch/Click/Keypress Events (User Input)*******************/
  @Override
  public boolean onTouch(View v, MotionEvent e)
  {    
    if(e.getAction() == MotionEvent.ACTION_DOWN && buttonsActive)
    {
      //play tones
      if(soundFxOn && (v==redButtonTop || v==yellowButtonTop || v==blueButtonTop || v==greenButtonTop || v==orangeButtonTop))
      {
        soundCache.get(v).start();
      }
      
      if(v == redButtonTop)
      {
        redButtonLight.setVisibility(View.VISIBLE);
      }
      else if(v == yellowButtonTop)
      {
        yellowButtonLight.setVisibility(View.VISIBLE);
      }
      else if(v == blueButtonTop)
      {
        blueButtonLight.setVisibility(View.VISIBLE);
      }
      else if(v == greenButtonTop)
      {
        greenButtonLight.setVisibility(View.VISIBLE);
      }
      else if(v == orangeButtonTop)
      {
        orangeButtonLight.setVisibility(View.VISIBLE);
      }
      return true;
    }
    else if(e.getAction() == MotionEvent.ACTION_UP && buttonsActive)
    {
      //stop the tone
      if(soundFxOn && (v==redButtonTop || v==yellowButtonTop || v==blueButtonTop || v==greenButtonTop || v==orangeButtonTop))
      {
        soundCache.get(v).pause();
      }
      
      if(v == redButtonTop)
      {
        redButtonLight.setVisibility(View.INVISIBLE);
        //check against the pattern
        if(this.validateInput(1))
        {
          //check for level end
          if(this.isLevelComplete())
          {
            //level up
            this.levelUp();
          }
        }
        else
        {
          //end the game
          this.gameOver();
        }
      }
      else if(v == yellowButtonTop)
      {
        yellowButtonLight.setVisibility(View.INVISIBLE);
        //check against the pattern
        if(this.validateInput(2))
        {
          //check for level end
          if(this.isLevelComplete())
          {
            //level up
            this.levelUp();
          }
        }
        else
        {
          //end the game
          this.gameOver();
        }
      }
      else if(v == blueButtonTop)
      {
        blueButtonLight.setVisibility(View.INVISIBLE);
        //check against the pattern
        if(this.validateInput(3))
        {
          //check for level end
          if(this.isLevelComplete())
          {
            //level up
            this.levelUp();
          }
        }
        else
        {
          //end the game
          this.gameOver();
        }
      }
      else if(v == greenButtonTop)
      {
        greenButtonLight.setVisibility(View.INVISIBLE);
        //check against the pattern
        if(this.validateInput(4))
        {
          //check for level end
          if(this.isLevelComplete())
          {
            //level up
            this.levelUp();
          }
        }
        else
        {
          //end the game
          this.gameOver();
        }
      }
      else if(v == orangeButtonTop)
      {
        orangeButtonLight.setVisibility(View.INVISIBLE);
        //check against the pattern
        if(this.validateInput(5))
        {
          //check for level end
          if(this.isLevelComplete())
          {
            //level up
            this.levelUp();
          }
        }
        else
        {
          //end the game
          this.gameOver();
        }
      }
      return true;
    }
    
    return false;
  }
  
  /***
   * Validates the button press against the stored pattern
   * @param buttonPressed
   * @return
   */
  private boolean validateInput(int buttonPressed)
  {
    
    final int buttonExpected = myPattern.get(currentPatternIndex);
    //System.out.println("Expected: "+buttonExpected+"   Entered: "+buttonPressed);
    if(buttonExpected == buttonPressed)
    {
      currentPatternIndex++;
      return true;
    }
    //else
    return false;
  }
    
  @Override
  public void onClick(View v)
  {
    //check for clicks
    //can use == instead of .equals(...)
    if(v == resumeButton)
    {
      buttonsActive = true;
      statusbarActive = true;
      pauseMenuLayout.setVisibility(View.GONE);
    }
    else if(v==fxOffRadioButton)
    {
      if(fxOffRadioButton.isChecked())
      {
        soundFxOn = false;
      }
    }
    else if(v==fxOnRadioButton)
    {
      if(fxOnRadioButton.isChecked())
      {
        soundFxOn = true;
      }
    }
    else if(forwardButton == v && statusbarActive)
    {
      if(!isGameOver)
      {
        forwardButton.setVisibility(View.INVISIBLE);
        successLayout.setVisibility(View.GONE);
        this.beginNewLevel();
      }
      else
      {        
        //return to the main menu
        Intent myIntent = new Intent(this, Main.class);
        //this.startActivityForResult(myIntent, 1);
        this.startActivity(myIntent);
        this.finish();
      }
    }
    else if(v == replayButton && statusbarActive && !showingPattern && 
        this.successLayout.getVisibility()!=View.VISIBLE && this.failLayout.getVisibility()!=View.VISIBLE)
    {
      statusbarActive = false;
      buttonsActive = false;
      myPatternPlayer.playPattern(true);//repeat, so don't decrease delay/display times
      replayButton.setVisibility(View.INVISIBLE);
    }
    else if(v == pauseButton && statusbarActive)
    {
      buttonsActive = false;
      statusbarActive = false;
      pauseMenuLayout.startAnimation(animationCache[1]);
      if(soundFxOn)
      {
        fxOnRadioButton.setChecked(true);
      }
      else
      {
        fxOffRadioButton.setChecked(true);
      }
      pauseMenuLayout.setVisibility(View.VISIBLE);
    }
  }
  
  //intercept the back and menu key presses
  @Override
  public boolean onKeyDown(int keyCode, KeyEvent event)
  {
    if(keyCode == KeyEvent.KEYCODE_BACK)
    {
      if(pauseMenuLayout.getVisibility() == View.VISIBLE)
      {
        resumeButton.performClick();
        return true;
      }
    }
    else if(keyCode == KeyEvent.KEYCODE_MENU && buttonsActive)
    {
      pauseButton.performClick();
      return true;
    }
    //else
    return super.onKeyDown(keyCode, event);
  }
  /********************************************************************************************/
  
  @Override
  protected void onPause()
  {
    //System.out.println("onPause");
    if(!this.isGameOver)
    {
      Utilities.saveCurrentGame(this, Utilities.GAME_TYPE_5_BUTTON, myPattern, this.isLevelComplete());
    }
    
    //stop any playing sounds in the patternplayer
    myPatternPlayer.cancelPlayback();
    
    //release resources for the mediaplayers
    try
    {
      for(MediaPlayer mp : soundCache.values())
      {
        if(mp.isPlaying())
        {
          mp.stop();
        }
        
        mp.release();
      }
    }
    catch (Exception e)
    {
      //nothing
    }
    
    super.onPause();
    
    //close the app
    this.finish();
  }
  
  @Override
  protected void onResume()
  {
    //System.out.println("onResume");
    mySaveGame = Utilities.loadSavegame(this);
    
    //check the savegame
        if(mySaveGame!=null)
    {
      myPatternPlayer.setPattern(mySaveGame.getPattern());
      myPattern = myPatternPlayer.getPattern();
      
      this.startFromSavedGame(mySaveGame.getIsLevelComplete());
      
    }
        else
        {
          //run the 1st-run components
            this.startFirstRun();
        }
        
    super.onResume();
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.