Android Open Source - BlockBreaker Block Breaker Activity






From Project

Back to project page BlockBreaker.

License

The source code is released under:

GNU General Public License

If you think the Android project BlockBreaker listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package de.hotware.blockbreaker.android;
/*from   w w  w  .  j  a v  a 2 s. c o m*/
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Random;

import org.andengine.engine.camera.Camera;
import org.andengine.engine.camera.hud.HUD;
import org.andengine.engine.handler.timer.ITimerCallback;
import org.andengine.engine.handler.timer.TimerHandler;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.SpriteBackground;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.text.Text;
import org.andengine.entity.text.Text.TextOptions;
import org.andengine.entity.util.FPSCounter;
import org.andengine.entity.util.FPSLogger;
import org.andengine.opengl.font.Font;
import org.andengine.opengl.font.FontFactory;
import org.andengine.opengl.font.FontManager;
import org.andengine.opengl.texture.TextureManager;
import org.andengine.opengl.texture.TextureOptions;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.region.TextureRegion;
import org.andengine.opengl.texture.region.TiledTextureRegion;
import org.andengine.opengl.vbo.VertexBufferObjectManager;
import org.andengine.input.sensor.orientation.IOrientationListener;
import org.andengine.input.sensor.orientation.OrientationData;
import org.andengine.ui.activity.BaseGameActivity;
import org.andengine.util.HorizontalAlign;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.graphics.Color;
import android.preference.PreferenceManager;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.FrameLayout;
import de.hotware.blockbreaker.android.view.LevelSceneHandler;
import de.hotware.blockbreaker.android.view.UIConstants;
import de.hotware.blockbreaker.model.generator.LevelGenerator;
import de.hotware.blockbreaker.model.listeners.IGameEndListener;
import de.hotware.blockbreaker.model.listeners.IGameEndListener.GameEndEvent.GameEndType;
import de.hotware.blockbreaker.model.Level;
import de.hotware.blockbreaker.util.misc.StreamUtil;

/**
 * (c) 2011-2012 Martin Braun
 * TODO: change behaviours via different GameEndListener, Do we need Timed Mode?
 * TODO: save levels (Preferences checkbox if dialog should appear)
 * TODO: maybe use factory methods instead of new instances for GameTypeHandlers in extra
 *      class with methods. Cache instances!
 * @author Martin Braun
 * @since Dec 2011
 */
public class BlockBreakerActivity extends BaseGameActivity implements IOrientationListener {
  ////////////////////////////////////////////////////////////////////
  ////              Constants            ////
  ////////////////////////////////////////////////////////////////////
  static final String DEFAULT_LEVEL_PATH = "levels/default.lev";
  static final boolean USE_MENU_WORKAROUND = Integer.valueOf(android.os.Build.VERSION.SDK) < 7;

  static final String HIGHSCORE_NUM_KEY = "high_score_num_key";
  static final String HIGHSCORE_PLAYER_KEY = "high_score_player_key";

  ////////////////////////////////////////////////////////////////////
  ////              Fields              ////
  ////////////////////////////////////////////////////////////////////
  static final Random sRandomSeedObject = new Random();

  boolean mUseOrientSensor = false;
  boolean mTimeAttackMode = false;
  int mNumberOfTurns = 16;
  int mWinCount = 10;

  BitmapTextureAtlas mBlockBitmapTextureAtlas;
  TiledTextureRegion mBlockTiledTextureRegion;
  BitmapTextureAtlas mArrowBitmapTextureAtlas;
  TiledTextureRegion mArrowTiledTextureRegion;
  BitmapTextureAtlas mSceneBackgroundBitmapTextureAtlas;
  TextureRegion mSceneBackgroundTextureRegion;

  Properties mStringProperties;

  Camera mCamera;  
  Scene mLevelScene;
  Font mMiscFont;
  Font mSceneUIFont;

  Text mSeedText;

  LevelSceneHandler mLevelSceneHandler;
  Level mBackupLevel;
  Level mLevel;

  boolean mIgnoreInput = false;

  //currently not used
  String mLevelPath = DEFAULT_LEVEL_PATH;
  boolean mIsAsset = true;
  //not used end

  private BaseGameTypeHandler mGameTypeHandler;

  ////////////////////////////////////////////////////////////////////
  ////          Overridden Methods            ////
  ////////////////////////////////////////////////////////////////////

  @Override
  public void onResume() {
    super.onResume();
    boolean oldTimeAttackMode = this.mTimeAttackMode;
    int oldNumberOfTurns = this.mNumberOfTurns;
    this.getPrefs();
    if(oldTimeAttackMode ^ this.mTimeAttackMode || this.mGameTypeHandler == null) {
      if(this.mGameTypeHandler != null) {
        this.mGameTypeHandler.cleanUp();
      }
      this.mGameTypeHandler = this.mTimeAttackMode ? new TimeAttackGameHandler() : new DefaultGameHandler();
      //no level has yet been created nor a LevelSceneHandler which is needed in some GameTypeHandlers
      if(this.mLevel != null) {
        this.mLevel.setGameEndListener(this.mGameTypeHandler);
        this.mGameTypeHandler.init();
      }
    } else if(oldNumberOfTurns != this.mNumberOfTurns) {
      this.mGameTypeHandler.onNumberOfTurnsPropertyChanged();
    }
    if(this.mLevel != null) {
      //call on enter focus, if the game has already started once (outside of the andengine lifecycle!!!)
      this.mGameTypeHandler.onEnterFocus();
    }
  }

  @Override
  public void onPause() {
    super.onPause();
    //this has to be done here outside of the andengine lifecycle
    this.mGameTypeHandler.onLeaveFocus();
  }

  /**
   * sets the EngineOptions to the needs of the game
   */
  @Override
  public EngineOptions onCreateEngineOptions() {
    this.mCamera = new Camera(0, 0, UIConstants.LEVEL_WIDTH, UIConstants.LEVEL_HEIGHT);
    EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(UIConstants.LEVEL_WIDTH, UIConstants.LEVEL_HEIGHT), this.mCamera);
    return engineOptions;
  }

  /**
   * Load all the textures we need
   */
  @Override
  public void onCreateResources(OnCreateResourcesCallback pCallback) {

    BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

    //TODO: Language choosing
    this.mStringProperties = new Properties();
    AssetManager assetManager = this.getResources().getAssets();
    InputStream is = null;
    boolean fail = false;
    try {
      is = assetManager.open(UIConstants.DEFAULT_PROPERTIES_PATH);
      this.mStringProperties.load(is);
    } catch (IOException e) {
      fail = true;
      this.showFailDialog(e.getMessage());
    } finally {
      StreamUtil.closeQuietly(is);
    }

    if(fail) {
      this.finish();
    }

    TextureManager textureManager = this.mEngine.getTextureManager();

    //loading block textures
    this.mBlockBitmapTextureAtlas = new BitmapTextureAtlas(textureManager, 276, 46, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
    this.mBlockTiledTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mBlockBitmapTextureAtlas, this, "blocks_tiled.png", 0,0, 6,1);
    this.mEngine.getTextureManager().loadTexture(this.mBlockBitmapTextureAtlas);

    //loading arrow sprites
    this.mArrowBitmapTextureAtlas = new BitmapTextureAtlas(textureManager, 512, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
    this.mArrowTiledTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mArrowBitmapTextureAtlas, this, "arrow_tiled.png", 0,0, 4,1);
    this.mEngine.getTextureManager().loadTexture(this.mArrowBitmapTextureAtlas);

    //Loading Background
    this.mSceneBackgroundBitmapTextureAtlas = new BitmapTextureAtlas(textureManager, 960, 640, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
    this.mSceneBackgroundTextureRegion = (TextureRegion) BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mSceneBackgroundBitmapTextureAtlas, this, "background.png", 0, 0);   
    this.mEngine.getTextureManager().loadTexture(this.mSceneBackgroundBitmapTextureAtlas);

    FontManager fontManager = this.mEngine.getFontManager();

    //loading fps font
    BitmapTextureAtlas fpsFontTexture = new BitmapTextureAtlas(textureManager, 256, 256, TextureOptions.BILINEAR);
    this.mEngine.getTextureManager().loadTexture(fpsFontTexture);
    FontFactory.setAssetBasePath("font/");
    this.mMiscFont = FontFactory.createFromAsset(fontManager, fpsFontTexture, assetManager, "Droid.ttf", 12, true, Color.BLACK);     
    this.mEngine.getFontManager().loadFont(this.mMiscFont);

    //loading scene font
    BitmapTextureAtlas sceneFontTexture = new BitmapTextureAtlas(textureManager, 256, 256, TextureOptions.BILINEAR);
    this.mEngine.getTextureManager().loadTexture(sceneFontTexture);
    this.mSceneUIFont = FontFactory.createFromAsset(fontManager, sceneFontTexture, assetManager, "Plok.ttf", 18, true, Color.BLACK);
    this.mEngine.getFontManager().loadFont(this.mSceneUIFont);

    pCallback.onCreateResourcesFinished();
  }

  /**
   * initialization of the Activity is done here.
   */
  @Override
  public void onCreateScene(OnCreateSceneCallback pCallback) {
    this.mEngine.registerUpdateHandler(new FPSLogger());    
    pCallback.onCreateSceneFinished(new Scene());
  }

  @Override
  public void onPopulateScene(Scene pScene, OnPopulateSceneCallback pCallback) {
    this.loadFirstLevel();
    this.initLevel();
    this.mCamera.getHUD().attachChild(this.mSeedText);
    //TODO: setting scene only for testing purposes!!!
    this.mEngine.setScene(this.mLevelScene);
    pCallback.onPopulateSceneFinished();
    this.mGameTypeHandler.init();
    this.mGameTypeHandler.onEnterFocus();
  }

  @Override
  public void onResumeGame() {
    super.onResumeGame();
    if(this.mUseOrientSensor) {
      this.enableOrientationSensor(this);
    } else {
      this.disableOrientationSensor();
    }
  }

  @Override
  public void onPauseGame() {
    super.onPauseGame();
    this.disableOrientationSensor();
  }

  /**
   * Listener method for Changes of the devices Orientation.
   * sets the Levels Gravity to the overwhelming Gravity
   */
  @Override
  public void onOrientationChanged(OrientationData pOrientData) {
    if(this.mUseOrientSensor) {
      if(this.mLevel != null) {
        float pitch = pOrientData.getPitch();
        float roll = pOrientData.getRoll();
        if(roll == 0 && pitch == 0) {
          this.mLevel.setGravity(Level.Gravity.NORTH);
        } else if(Math.max(Math.abs(pitch), Math.abs(roll)) == Math.abs(pitch)) {
          if(-pitch < 0) {
            this.mLevel.setGravity(Level.Gravity.SOUTH);
          } else {
            this.mLevel.setGravity(Level.Gravity.NORTH);
          }
        } else {
          if(roll < 0) {
            this.mLevel.setGravity(Level.Gravity.EAST);
          } else {
            this.mLevel.setGravity(Level.Gravity.WEST);
          }
        }
      }
    }
  }

  /**
   * creates the menu defined in the corresponding xml file
   */
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    if(this.mStringProperties != null) {
      menu.add(Menu.NONE,
          UIConstants.MENU_MENU_ID,
          Menu.NONE,
          this.mStringProperties.getProperty(UIConstants.MENU_PROPERTY_KEY));
      menu.add(Menu.NONE,
          UIConstants.FROM_SEED_MENU_ID,
          Menu.NONE,
          this.mStringProperties.getProperty(UIConstants.FROM_SEED_PROPERTY_KEY));
      menu.add(Menu.NONE,
          UIConstants.RESTART_MENU_ID,
          Menu.NONE,
          this.mStringProperties.getProperty(UIConstants.RESTART_PROPERTY_KEY));
      menu.add(Menu.NONE, 
          UIConstants.NEXT_MENU_ID, 
          Menu.NONE, 
          this.mStringProperties.getProperty(UIConstants.NEXT_PROPERTY_KEY));
      return true;
    }
    return false;
  }

  /**
   * shows the Activities Menu
   */
  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    //TODO use AndEngines Menu System!
    switch(item.getItemId()) {
      case UIConstants.MENU_MENU_ID: {
        if(this.mGameTypeHandler.requestLeaveToMenu()) {
          Intent settingsActivity = new Intent(getBaseContext(),
              BlockBreakerPreferencesActivity.class);
          this.startActivity(settingsActivity);
        }
        return true;
      }
      case UIConstants.FROM_SEED_MENU_ID: {
        this.mGameTypeHandler.requestSeedInput();
        return true;
      }
      case UIConstants.RESTART_MENU_ID: {
        this.mGameTypeHandler.requestRestart();
        return true;
      }
      case UIConstants.NEXT_MENU_ID:  {
        this.mGameTypeHandler.requestNextLevel();
        return true;
      }
      default: {
        return super.onOptionsItemSelected(item);
      }
    }
  }

  /**
   * Fix for older SDK versions which don't have onBackPressed()  
   */
  @Override
  public boolean onKeyDown(int pKeyCode, KeyEvent pEvent) {
    if(USE_MENU_WORKAROUND && 
        pKeyCode == KeyEvent.KEYCODE_BACK && 
        pEvent.getRepeatCount() == 0) {
      this.onBackPressed();
    }
    return super.onKeyDown(pKeyCode, pEvent);
  }

  /**
   * If the user presses the back button he is asked if he wants to quit
   */
  @Override
  public void onBackPressed() {
    this.showCancelDialog();
  }

  @Override
  public void onOrientationAccuracyChanged(OrientationData pOrientationData) {

  }

  ////////////////////////////////////////////////////////////////////
  ////          Private/Package Methods          ////
  ////////////////////////////////////////////////////////////////////

  void updateLevel(String pLevelPath, boolean pIsAsset) throws Exception {
    this.mSeedText.setText("");
    this.mLevelPath = pLevelPath;
    this.mIsAsset = pIsAsset;
    this.loadLevelFromAsset();
    this.mLevel = this.mBackupLevel.copy();
    this.mLevel.start();
    this.mLevel.setGameEndListener(this.mGameTypeHandler);
    this.mLevelSceneHandler.updateLevel(this.mLevel);
  }

  void loadLevelFromAsset() throws Exception {
    throw new Exception("not Implemented!");
  }

  /**
   * restarts the Level by creating a deep copy of the backup level
   * and making it the current level. it also sets the GameEndListener
   * correctly and updates the LevelSceneHandlers Level
   */
  void restartLevel() {
    this.mLevel = this.mBackupLevel.copy();
    this.mLevel.start();
    this.mLevel.setGameEndListener(this.mGameTypeHandler);
    this.mLevelSceneHandler.updateLevel(this.mLevel);
  }

  /**
   * changes the current Level to a completely
   * randomly generated Level
   */
  void randomLevel() {
    long seed = sRandomSeedObject.nextLong();
    this.randomLevelFromSeed(seed);
  }

  /**
   * changes the current Level to a Level from seed
   * @param pSeed
   */
  void randomLevelFromSeed(long pSeed) {
    this.mSeedText.setText("Seed: " + Long.toString(pSeed));
    this.mBackupLevel = LevelGenerator.createRandomLevelFromSeed(pSeed, 
        this.mNumberOfTurns, 
        this.mWinCount);
    this.mLevel = this.mBackupLevel.copy();
    this.mLevel.start();
    this.mLevel.setGameEndListener(this.mGameTypeHandler);
    this.mLevelSceneHandler.updateLevel(this.mLevel);
  }

  /**
   * initializes the first Level, only to be called on first startup!
   */
  private void initLevel() {
    final Scene scene = new Scene();
    this.mLevelScene = scene;

    this.mLevel = this.mBackupLevel.copy();
    this.mLevel.start();

    this.mLevel.setGameEndListener(this.mGameTypeHandler);

    VertexBufferObjectManager vboManager = this.mEngine.getVertexBufferObjectManager();

    this.mLevelSceneHandler = new LevelSceneHandler(scene, vboManager);

    //ignore input, gamehandlers will have to handle starting on their own
    this.mLevelSceneHandler.setIgnoreInput(true);

    this.mLevelSceneHandler.initLevelScene(BlockBreakerActivity.this.mLevel, 
        this.mSceneUIFont,
        this.mBlockTiledTextureRegion,
        this.mArrowTiledTextureRegion,
        this.mStringProperties);

    final HUD hud = new HUD();
    final FPSCounter counter = new FPSCounter();
    this.mEngine.registerUpdateHandler(counter);
    final int maxLength = "FPS: XXXXXXX".length();
    final Text fps = new Text(1, 
        1, 
        this.mMiscFont, 
        "FPS:", 
        maxLength, 
        vboManager);
    hud.attachChild(fps);

    this.mCamera.setHUD(hud);

    scene.registerUpdateHandler(new TimerHandler(1/20F, true, 
        new ITimerCallback() {
      
          @Override
          public void onTimePassed(TimerHandler arg0) {
            String fpsString = Float.toString(counter.getFPS());
            int length = fpsString.length();
            fps.setText("FPS: " + fpsString.substring(0, length >= 5 ? 5 : length));
          }  
          
    }));
    scene.setBackground(new SpriteBackground(new Sprite(0,0,UIConstants.LEVEL_WIDTH, 
        UIConstants.LEVEL_HEIGHT, 
        BlockBreakerActivity.this.mSceneBackgroundTextureRegion,
        vboManager)));
  }

  void showCancelDialog() {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage(this.mStringProperties.getProperty(UIConstants.EXIT_GAME_QUESTION_PROPERTY_KEY))
    .setCancelable(true)
    .setPositiveButton(this.mStringProperties.getProperty(UIConstants.YES_PROPERTY_KEY),
        new DialogInterface.OnClickListener() {
      
          @Override
          public void onClick(DialogInterface pDialog, int pId) {
            pDialog.dismiss();
            BlockBreakerActivity.this.finish();
          }
      
    })
    .setNegativeButton(this.mStringProperties.getProperty(UIConstants.NO_PROPERTY_KEY), 
        new DialogInterface.OnClickListener() {
      
          @Override
          public void onClick(DialogInterface pDialog, int pId) {
            pDialog.dismiss();
          }
          
    });
    builder.create().show();
  }

  void showFailDialog(String pMessage) {
    //Don't use Properties here because this is used for failures in property loading as well
    AlertDialog.Builder builder = new AlertDialog.Builder(BlockBreakerActivity.this);
    builder.setMessage(pMessage + "\nQuitting!")
    .setCancelable(false)
    .setPositiveButton("OK", new DialogInterface.OnClickListener() {
      
      @Override
      public void onClick(DialogInterface pDialog, int pId) {
        pDialog.dismiss();
        BlockBreakerActivity.this.finish();
      }
      
    });
    builder.create().show();
  }

  void showInputSeedDialog() {
    this.showInputSeedDialog(
        this.mStringProperties.getProperty(UIConstants.INPUT_SEED_QUESTION_PROPERTY_KEY));
  }

  void showInputSeedDialog(String pText) {  
    FrameLayout fl = new FrameLayout(this);
    final EditText input = new EditText(this);
    input.setGravity(Gravity.CENTER);
    fl.addView(input, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT, 
        FrameLayout.LayoutParams.WRAP_CONTENT));

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage(pText)
    .setView(fl)
    .setCancelable(true)
    .setPositiveButton(this.mStringProperties.getProperty(UIConstants.OK_PROPERTY_KEY), 
        new DialogInterface.OnClickListener() {
      
          @Override
          public void onClick(DialogInterface pDialog, int pId) {
            try { 
              pDialog.dismiss();
              long seed = Long.parseLong(input.getText().toString());
              BlockBreakerActivity.this.randomLevelFromSeed(seed);  
            } catch (NumberFormatException e) {
              BlockBreakerActivity.this.showInputSeedDialog(
                  BlockBreakerActivity.this.mStringProperties.getProperty(
                      UIConstants.WRONG_SEED_INPUT_PROPERTY_KEY));          
            }
          }
          
    })
    .setNegativeButton(this.mStringProperties.getProperty(UIConstants.CANCEL_PROPERTY_KEY),
        new DialogInterface.OnClickListener() {  
      
          @Override
          public void onClick(DialogInterface pDialog, int pId) {
            pDialog.dismiss();
          }
          
    });
    builder.create().show();
  }

  /**
   * loads the first randomly generated Level and initializes the SeedText
   */
  private void loadFirstLevel() {
    long seed = sRandomSeedObject.nextLong();
    this.mBackupLevel = LevelGenerator.createRandomLevelFromSeed(seed, this.mNumberOfTurns, this.mWinCount);
    int maxLength = "Seed: ".length() + Long.toString(Long.MAX_VALUE).length() + 1;
    this.mSeedText = new Text(1,
        UIConstants.LEVEL_HEIGHT - 15,
        this.mMiscFont,
        "Seed: " + seed,
        maxLength,
        this.mEngine.getVertexBufferObjectManager());
  }

  /**
   * gets the shared preferences and changes some boolean variables according to that
   */
  private void getPrefs() {
    // Get the xml/preferences.xml preferences
    // Don't save this in a constant, because it will only be used in code here
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
    this.mUseOrientSensor = prefs.getBoolean("orient_sens_pref", false);
    this.mTimeAttackMode = prefs.getBoolean("time_attack_pref", false);
    this.mNumberOfTurns = Integer.parseInt(prefs.getString("number_of_turns_pref", "16"));
  }

  ////////////////////////////////////////////////////////////////////
  ////          Inner Classes & Interfaces        ////
  ////////////////////////////////////////////////////////////////////

  public abstract class BaseGameTypeHandler implements IGameEndListener {

    /**
     * called if Activity loses Focus
     */
    public void onLeaveFocus() {
      BlockBreakerActivity.this.mLevelSceneHandler.setIgnoreInput(true);
    }

    public void requestSeedInput() { }

    /**
     * called if Activity gains Focus
     */
    public void onEnterFocus() {
      BlockBreakerActivity.this.mLevelSceneHandler.setIgnoreInput(false);
    }

    /**
     * called if the user requests the next Level, which is the same as losing in TimeAttack
     */
    public void requestNextLevel(){}

    /**
     * called if the user requests to leave to the menu Activity
     * @return true if menu will be shown, false otherwise
     * @return default version returns true
     */
    public boolean requestLeaveToMenu(){return true;}

    /**
     * called if the user requests a restart of the game
     */
    public void requestRestart(){}

    /**
     * called upon first start of the game
     */
    public void init(){}

    /**
     * called when before the GameHandler is changed
     */
    public void cleanUp(){}

    /**
     * called if the number of turns property has changed, only used for notifying, no information
     */
    public void onNumberOfTurnsPropertyChanged(){}

  }

  private class DefaultGameHandler extends BaseGameTypeHandler {

    @Override
    public void onGameEnd(final GameEndEvent pEvt) {
      BlockBreakerActivity.this.runOnUiThread(new Runnable() {
        public void run() {
          DefaultGameHandler.this.showEndDialog(pEvt.getType());
        }
      });
    }

    @Override
    public void requestRestart() {
      BlockBreakerActivity.this.restartLevel();
    }

    @Override
    public void requestNextLevel() {
      BlockBreakerActivity.this.randomLevel();
    }

    @Override
    public void cleanUp() {
      BlockBreakerActivity.this.randomLevel();
    }

    private void showEndDialog(final GameEndType pResult) {
      String resString;

      switch(pResult) {
        case WIN: {
          resString = BlockBreakerActivity.this.mStringProperties.
              getProperty(UIConstants.WIN_GAME_PROPERTY_KEY);
          break;
        }
        case LOSE: {
          resString = BlockBreakerActivity.this.mStringProperties.
              getProperty(UIConstants.LOSE_GAME_PROPERTY_KEY);
          break;
        }
        default: {
          resString = "WTF?";
          break;
        }
      }

      AlertDialog.Builder builder = new AlertDialog.Builder(BlockBreakerActivity.this);
      builder.setMessage(resString + " " + BlockBreakerActivity.this.mStringProperties.
          getProperty(UIConstants.RESTART_QUESTION_PROPERTY_KEY))
          .setCancelable(true)
          .setPositiveButton(BlockBreakerActivity.
              this.mStringProperties.getProperty(UIConstants.YES_PROPERTY_KEY),
              new DialogInterface.OnClickListener() {
                
                @Override
                public void onClick(DialogInterface pDialog, int pId) {
                  pDialog.dismiss();
                  BlockBreakerActivity.this.restartLevel();
                }
                
          })
          .setNegativeButton(BlockBreakerActivity.this.mStringProperties.
              getProperty(UIConstants.NO_PROPERTY_KEY), new DialogInterface.OnClickListener() {
                
                @Override
                public void onClick(DialogInterface pDialog, int pId) {
                  pDialog.dismiss();
                  //TODO: Testing purposes!
                  BlockBreakerActivity.this.randomLevel();
                }
                
          });
      builder.create().show();
    }

    @Override
    public void requestSeedInput() {
      BlockBreakerActivity.this.showInputSeedDialog();
    }

  }

  private class TimeAttackGameHandler extends BaseGameTypeHandler {

    private static final int DEFAULT_DURATION_IN_SECONDS = 120;
    private static final int DEFAULT_NUMBER_OF_ALLOWED_LOSES = 2;
    private static final int GAME_WIN_BONUS = 100;
    private static final int BLOCK_LEFT_BONUS = 10;
    private static final int GAME_LOSE_BONUS = -50;

    int mDurationInSeconds;
    int mNumberOfAllowedLoses;
    int mGamesLost;
    int mGamesWon;
    TimerHandler mTimeMainHandler;
    TimerHandler mTimeUpdateHandler;
    Text mStatusText;
    Text mTimeText;
    Text mTimeLeftText;
    int mScore;

    public TimeAttackGameHandler() {
      this(DEFAULT_DURATION_IN_SECONDS, DEFAULT_NUMBER_OF_ALLOWED_LOSES);
    }

    public TimeAttackGameHandler(int pDurationInSeconds, int pNumberOfAllowedLoses) {
      this.mDurationInSeconds = pDurationInSeconds;
      this.mNumberOfAllowedLoses = pNumberOfAllowedLoses;
      this.mGamesWon = 0;
      this.mGamesLost = 0;
      this.mScore = 0;
      this.mTimeMainHandler = new TimerHandler(this.mDurationInSeconds, 
          new ITimerCallback() {

            @Override
            public void onTimePassed(TimerHandler pTimerHandler) {
              TimeAttackGameHandler.this.onTimeAttackEnd();
            }

      });
      this.mTimeUpdateHandler = new TimerHandler(1.0F, true, new ITimerCallback() {

        @Override
        public void onTimePassed(TimerHandler pTimerHandler) {
          if(!TimeAttackGameHandler.this.mTimeMainHandler.isTimerCallbackTriggered()) {
            TimeAttackGameHandler.this.mTimeLeftText.setText(
                Integer.toString((int)Math.round(
                    TimeAttackGameHandler.this.mDurationInSeconds - 
                    TimeAttackGameHandler.this.mTimeMainHandler.getTimerSecondsElapsed())));
          } else {
            TimeAttackGameHandler.this.mTimeLeftText.setText(Integer.toString(0));
            pTimerHandler.setAutoReset(false);
          }
        }

      });
    }

    @Override
    public void onGameEnd(GameEndEvent pEvt) {
      switch(pEvt.getType()) {
        case WIN: {
          this.mScore = this.mScore + GAME_WIN_BONUS + 
              BlockBreakerActivity.this.mLevel.getBlocksLeft() * BLOCK_LEFT_BONUS;
          ++this.mGamesWon;
          BlockBreakerActivity.this.randomLevel();
          this.updateStatusText();
          break;
        }
        case LOSE: {
          this.requestNextLevel();
          break;
        }
      }
    }

    @Override
    public void onEnterFocus() {
      if(this.mTimeMainHandler.getTimerSecondsElapsed() < this.mDurationInSeconds
          && this.mGamesLost < this.mNumberOfAllowedLoses) {
        BlockBreakerActivity.this.runOnUiThread(new Runnable() {

          @Override
          public void run() {
            AlertDialog.Builder builder = new AlertDialog.Builder(BlockBreakerActivity.this);
            builder.setMessage(BlockBreakerActivity.this.mStringProperties.getProperty(UIConstants.TIME_ATTACK_START_TEXT_PROPERTY_KEY))
            .setCancelable(false)
            .setPositiveButton(BlockBreakerActivity.this.mStringProperties.getProperty(UIConstants.START_PROPERTY_KEY), 
                new DialogInterface.OnClickListener() {
                  @Override
                  public void onClick(DialogInterface pDialog, int pId) {
                    pDialog.dismiss();
                    BlockBreakerActivity.this.mLevelSceneHandler.setIgnoreInput(false);
                    BlockBreakerActivity.this.mEngine.registerUpdateHandler(TimeAttackGameHandler.this.mTimeMainHandler);
                    BlockBreakerActivity.this.mEngine.registerUpdateHandler(TimeAttackGameHandler.this.mTimeUpdateHandler);
                    pDialog.dismiss();
                  }
            }
                );
            builder.create().show();
          }

        });
      } else {
        this.showTimeAttackEndDialog();
      }
    }

    @Override
    public void onLeaveFocus() {
      BlockBreakerActivity.this.mLevelSceneHandler.setIgnoreInput(true);
      BlockBreakerActivity.this.mEngine.unregisterUpdateHandler(this.mTimeMainHandler);
      BlockBreakerActivity.this.mEngine.unregisterUpdateHandler(this.mTimeUpdateHandler);
    }

    @Override
    public boolean requestLeaveToMenu() {
      return true;
    }

    @Override
    public void requestRestart() {
      //make sure everything is set back to normal
      BlockBreakerActivity.this.mEngine.unregisterUpdateHandler(TimeAttackGameHandler.this.mTimeMainHandler);
      BlockBreakerActivity.this.mEngine.unregisterUpdateHandler(TimeAttackGameHandler.this.mTimeUpdateHandler);
      this.reset();
      BlockBreakerActivity.this.randomLevel();
      //ready, set go!
      BlockBreakerActivity.this.mEngine.registerUpdateHandler(TimeAttackGameHandler.this.mTimeMainHandler);
      BlockBreakerActivity.this.mEngine.registerUpdateHandler(TimeAttackGameHandler.this.mTimeUpdateHandler);
    }

    @Override
    public void requestNextLevel() {
      this.mScore = this.mScore + GAME_LOSE_BONUS;
      this.updateStatusText();
      ++this.mGamesLost;
      if(this.mGamesLost <= this.mNumberOfAllowedLoses) {
        BlockBreakerActivity.this.randomLevel();
      } else {
        this.showTimeAttackEndDialog();
      }
    }

    @Override
    public void init() {
      this.mTimeLeftText = BlockBreakerActivity.this.mLevelSceneHandler.getTimeLeftText();
      this.mTimeLeftText.setVisible(true);
      this.mTimeLeftText.setText(Integer.toString(this.mDurationInSeconds));
      this.mTimeText = BlockBreakerActivity.this.mLevelSceneHandler.getTimeText();
      this.mTimeText.setVisible(true);
      VertexBufferObjectManager vbo = BlockBreakerActivity.this.mEngine.getVertexBufferObjectManager();
      this.mStatusText = new Text(UIConstants.LEVEL_WIDTH - 100,
          5,
          BlockBreakerActivity.this.mMiscFont,
          "",
          15,
          new TextOptions(HorizontalAlign.RIGHT),
          vbo);
      this.updateStatusText();
      BlockBreakerActivity.this.mCamera.getHUD().attachChild(this.mStatusText);
    }

    @Override
    public void cleanUp() {
      BlockBreakerActivity.this.mEngine.unregisterUpdateHandler(this.mTimeMainHandler);
      BlockBreakerActivity.this.mEngine.unregisterUpdateHandler(this.mTimeUpdateHandler);
      BlockBreakerActivity.this.mLevelSceneHandler.setIgnoreInput(false);
      BlockBreakerActivity.this.randomLevel();
      this.mTimeLeftText.setVisible(false);
      this.mTimeLeftText.setText("");
      this.mTimeText.setVisible(false);
      this.mStatusText.detachSelf();
    }

    @Override
    public void onNumberOfTurnsPropertyChanged() {
      this.reset();
    }

    public void onTimeAttackEnd() {
      BlockBreakerActivity.this.mLevelSceneHandler.setIgnoreInput(true);
      this.showTimeAttackEndDialog();
    }

    private void showTimeAttackEndDialog() {
      BlockBreakerActivity.this.runOnUiThread(new Runnable() {

        @Override
        public void run() {
          AlertDialog.Builder builder = new AlertDialog.Builder(BlockBreakerActivity.this);
          builder.setMessage(
              BlockBreakerActivity.this.mStringProperties.getProperty(UIConstants.GAME_OVER_TEXT_PROPERTY_KEY)
              + "\n" + BlockBreakerActivity.this.mStringProperties.getProperty(UIConstants.SCORE_TEXT_PROPERTY_KEY)
              + ":\n" + TimeAttackGameHandler.this.mScore
              + "\n" + BlockBreakerActivity.this.mStringProperties.getProperty(UIConstants.COMPLETED_LEVELS_PROPERTY_KEY)
              + ":\n" + TimeAttackGameHandler.this.mGamesWon
              + "\n" + BlockBreakerActivity.this.mStringProperties.getProperty(UIConstants.LOST_LEVELS_TEXT_PROPERTY_KEY)
              + ":\n" + TimeAttackGameHandler.this.mGamesLost)
<<<<<<< HEAD
          .setCancelable(true)
          .setPositiveButton(BlockBreakerActivity.this.mStringProperties.getProperty(UIConstants.RESTART_PROPERTY_KEY), 
              new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface pDialog, int pId) {
                  pDialog.dismiss();
                  TimeAttackGameHandler.this.requestRestart();
                }
=======
              .setCancelable(true)
              .setPositiveButton(BlockBreakerActivity.this.mStringProperties.getProperty(UIConstants.RESTART_PROPERTY_KEY), 
                  new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface pDialog, int pId) {
                      //a restart has been requested
                      TimeAttackGameHandler.this.requestRestart();
                      pDialog.dismiss();
                    }
>>>>>>> unstable
              }
                  );
          builder.create().show();
        }

      });
    }

    private void reset() {
      this.mScore = 0;
      this.mGamesWon = 0;
      this.mGamesLost = 0;
      this.mTimeMainHandler.reset();
      this.mTimeUpdateHandler.reset();
      BlockBreakerActivity.this.mLevelSceneHandler.setIgnoreInput(false);
      this.updateStatusText();
    }

    private void updateStatusText() {
      this.mStatusText.setText("Score: " + this.mScore);
    }

  }

}




Java Source Code List

de.hotware.blockbreaker.android.BlockBreakerActivity.java
de.hotware.blockbreaker.android.BlockBreakerLogoSplashScreenActivity.java
de.hotware.blockbreaker.android.BlockBreakerPreferencesActivity.java
de.hotware.blockbreaker.android.highscore.HighscoreSQLManager.java
de.hotware.blockbreaker.android.util.activities.BaseSplashScreenActivity.java
de.hotware.blockbreaker.android.view.BasicBlockPositionListener.java
de.hotware.blockbreaker.android.view.BlockSpritePool.java
de.hotware.blockbreaker.android.view.BlockSprite.java
de.hotware.blockbreaker.android.view.LevelSceneHandler.java
de.hotware.blockbreaker.android.view.UIConstants.java
de.hotware.blockbreaker.android.view.listeners.IBlockSpriteTouchListener.java