Home | History | Annotate | Download | only in replicaisland
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.replica.replicaisland;
     18 
     19 import java.lang.reflect.InvocationTargetException;
     20 import java.lang.reflect.Method;
     21 
     22 import android.app.Activity;
     23 import android.app.AlertDialog;
     24 import android.app.Dialog;
     25 import android.content.DialogInterface;
     26 import android.content.Intent;
     27 import android.content.SharedPreferences;
     28 import android.hardware.Sensor;
     29 import android.hardware.SensorEvent;
     30 import android.hardware.SensorEventListener;
     31 import android.hardware.SensorManager;
     32 import android.media.AudioManager;
     33 import android.os.Bundle;
     34 import android.os.Debug;
     35 import android.util.DisplayMetrics;
     36 import android.view.KeyEvent;
     37 import android.view.Menu;
     38 import android.view.MenuItem;
     39 import android.view.MotionEvent;
     40 import android.view.View;
     41 import android.view.animation.Animation;
     42 import android.view.animation.AnimationUtils;
     43 import android.widget.TextView;
     44 
     45 /**
     46  * Core activity for the game.  Sets up a surface view for OpenGL, bootstraps
     47  * the game engine, and manages UI events.  Also manages game progression,
     48  * transitioning to other activites, save game, and input events.
     49  */
     50 public class AndouKun extends Activity implements SensorEventListener {
     51     private static final int ACTIVITY_CHANGE_LEVELS = 0;
     52     private static final int ACTIVITY_CONVERSATION = 1;
     53     private static final int ACTIVITY_DIARY = 2;
     54     private static final int ACTIVITY_ANIMATION_PLAYER = 3;
     55 
     56     private static final int CHANGE_LEVEL_ID = Menu.FIRST;
     57     private static final int TEST_ANIMATION_ID = CHANGE_LEVEL_ID + 1;
     58     private static final int TEST_DIARY_ID = CHANGE_LEVEL_ID + 2;
     59     private static final int METHOD_TRACING_ID = CHANGE_LEVEL_ID + 3;
     60 
     61     private static final int ROLL_TO_FACE_BUTTON_DELAY = 400;
     62 
     63     public static final int QUIT_GAME_DIALOG = 0;
     64 
     65     // If the version is a negative number, debug features (logging and a debug menu)
     66     // are enabled.
     67     public static final int VERSION = 14;
     68 
     69     private GLSurfaceView mGLSurfaceView;
     70     private Game mGame;
     71     private boolean mMethodTracing;
     72     private int mLevelRow;
     73     private int mLevelIndex;
     74     private float mTotalGameTime;
     75     private int mRobotsDestroyed;
     76     private int mPearlsCollected;
     77     private int mPearlsTotal;
     78     private int mLastEnding = -1;
     79     private int mLinearMode = 0;
     80     private int mDifficulty = 1;
     81     private boolean mExtrasUnlocked;
     82     private SensorManager mSensorManager;
     83     private SharedPreferences.Editor mPrefsEditor;
     84     private long mLastTouchTime = 0L;
     85     private long mLastRollTime = 0L;
     86     private View mPauseMessage = null;
     87     private View mWaitMessage = null;
     88     private View mLevelNameBox = null;
     89     private TextView mLevelName = null;
     90     private Animation mWaitFadeAnimation = null;
     91 
     92     private EventReporter mEventReporter;
     93     private Thread mEventReporterThread;
     94 
     95     private long mSessionId = 0L;
     96 
     97     /** Called when the activity is first created. */
     98     @Override
     99     protected void onCreate(Bundle savedInstanceState) {
    100         super.onCreate(savedInstanceState);
    101 
    102         SharedPreferences prefs = getSharedPreferences(PreferenceConstants.PREFERENCE_NAME, MODE_PRIVATE);
    103         final boolean debugLogs = prefs.getBoolean(PreferenceConstants.PREFERENCE_ENABLE_DEBUG, false);
    104 
    105         if (VERSION < 0 || debugLogs) {
    106         	DebugLog.setDebugLogging(true);
    107         } else {
    108         	DebugLog.setDebugLogging(false);
    109         }
    110 
    111         DebugLog.d("AndouKun", "onCreate");
    112 
    113 
    114         setContentView(R.layout.main);
    115         mGLSurfaceView = (GLSurfaceView) findViewById(R.id.glsurfaceview);
    116         mPauseMessage = findViewById(R.id.pausedMessage);
    117         mWaitMessage = findViewById(R.id.pleaseWaitMessage);
    118         mLevelNameBox = findViewById(R.id.levelNameBox);
    119         mLevelName = (TextView)findViewById(R.id.levelName);
    120         mWaitFadeAnimation = AnimationUtils.loadAnimation(this, R.anim.wait_message_fade);
    121 
    122 
    123         //mGLSurfaceView.setGLWrapper(new GLErrorLogger());
    124         mGLSurfaceView.setEGLConfigChooser(false); // 16 bit, no z-buffer
    125         //mGLSurfaceView.setDebugFlags(GLSurfaceView.DEBUG_CHECK_GL_ERROR | GLSurfaceView.DEBUG_LOG_GL_CALLS);
    126         mGame = new Game();
    127         mGame.setSurfaceView(mGLSurfaceView);
    128         DisplayMetrics dm = new DisplayMetrics();
    129         getWindowManager().getDefaultDisplay().getMetrics(dm);
    130 
    131         int defaultWidth = 480;
    132         int defaultHeight = 320;
    133         if (dm.widthPixels != defaultWidth) {
    134         	float ratio =((float)dm.widthPixels) / dm.heightPixels;
    135         	defaultWidth = (int)(defaultHeight * ratio);
    136         }
    137 
    138 
    139         mLevelRow = 0;
    140         mLevelIndex = 0;
    141 
    142 
    143         mPrefsEditor = prefs.edit();
    144         // Make sure that old game information is cleared when we start a new game.
    145         // CTS: clear settings to force start from beginning
    146         mPrefsEditor.remove(PreferenceConstants.PREFERENCE_LEVEL_ROW);
    147         mPrefsEditor.remove(PreferenceConstants.PREFERENCE_LEVEL_INDEX);
    148         mPrefsEditor.remove(PreferenceConstants.PREFERENCE_LEVEL_COMPLETED);
    149         mPrefsEditor.remove(PreferenceConstants.PREFERENCE_LINEAR_MODE);
    150         mPrefsEditor.remove(PreferenceConstants.PREFERENCE_TOTAL_GAME_TIME);
    151         mPrefsEditor.remove(PreferenceConstants.PREFERENCE_PEARLS_COLLECTED);
    152         mPrefsEditor.remove(PreferenceConstants.PREFERENCE_PEARLS_TOTAL);
    153         mPrefsEditor.remove(PreferenceConstants.PREFERENCE_ROBOTS_DESTROYED);
    154         mPrefsEditor.remove(PreferenceConstants.PREFERENCE_DIFFICULTY);
    155         mPrefsEditor.commit();
    156 
    157 
    158         mLevelRow = prefs.getInt(PreferenceConstants.PREFERENCE_LEVEL_ROW, 0);
    159         mLevelIndex = prefs.getInt(PreferenceConstants.PREFERENCE_LEVEL_INDEX, 0);
    160         int completed = prefs.getInt(PreferenceConstants.PREFERENCE_LEVEL_COMPLETED, 0);
    161         mTotalGameTime = prefs.getFloat(PreferenceConstants.PREFERENCE_TOTAL_GAME_TIME, 0.0f);
    162         mRobotsDestroyed = prefs.getInt(PreferenceConstants.PREFERENCE_ROBOTS_DESTROYED, 0);
    163         mPearlsCollected = prefs.getInt(PreferenceConstants.PREFERENCE_PEARLS_COLLECTED, 0);
    164         mPearlsTotal = prefs.getInt(PreferenceConstants.PREFERENCE_PEARLS_TOTAL, 0);
    165         mLinearMode = prefs.getInt(PreferenceConstants.PREFERENCE_LINEAR_MODE,
    166         		getIntent().getBooleanExtra("linearMode", false) ? 1 : 0);
    167         mExtrasUnlocked = prefs.getBoolean(PreferenceConstants.PREFERENCE_EXTRAS_UNLOCKED, false);
    168         mDifficulty = prefs.getInt(PreferenceConstants.PREFERENCE_DIFFICULTY, getIntent().getIntExtra("difficulty", 1));
    169 
    170         mGame.bootstrap(this, dm.widthPixels, dm.heightPixels, defaultWidth, defaultHeight, mDifficulty);
    171         mGLSurfaceView.setRenderer(mGame.getRenderer());
    172 
    173 
    174         int levelTreeResource = R.xml.level_tree;
    175 	    if (mLinearMode != 0) {
    176 	    	levelTreeResource = R.xml.linear_level_tree;
    177 	    }
    178 
    179 
    180         // Android activity lifecycle rules make it possible for this activity to be created
    181         // and come to the foreground without the MainMenu Activity ever running, so in that
    182         // case we need to make sure that this static data is valid.
    183         if (!LevelTree.isLoaded(levelTreeResource)) {
    184         	LevelTree.loadLevelTree(levelTreeResource, this);
    185         	LevelTree.loadAllDialog(this);
    186         }
    187 
    188         if (getIntent().getBooleanExtra("startAtLevelSelect", false)) {
    189         	Intent i = new Intent(this, LevelSelectActivity.class);
    190         	i.putExtra("unlockAll", true);
    191             startActivityForResult(i, ACTIVITY_CHANGE_LEVELS);
    192         } else {
    193 	        if (!LevelTree.levelIsValid(mLevelRow, mLevelIndex)) {
    194 	        	// bad data?  Let's try to recover.
    195 
    196 	        	// is the row valid?
    197 	        	if (LevelTree.rowIsValid(mLevelRow)) {
    198 	        		// In that case, just start the row over.
    199 	        		mLevelIndex = 0;
    200 	        		completed = 0;
    201 	        	} else if (LevelTree.rowIsValid(mLevelRow - 1)) {
    202 	        		// If not, try to back up a row.
    203 	        		mLevelRow--;
    204 	        		mLevelIndex = 0;
    205 	        		completed = 0;
    206 	        	}
    207 
    208 
    209 	        	if (!LevelTree.levelIsValid(mLevelRow, mLevelIndex)) {
    210 		        	// if all else fails, start the game over.
    211 		        	mLevelRow = 0;
    212 		        	mLevelIndex = 0;
    213 		        	completed = 0;
    214 	        	}
    215 	        }
    216 
    217 	        LevelTree.updateCompletedState(mLevelRow, completed);
    218 
    219 	        mGame.setPendingLevel(LevelTree.get(mLevelRow, mLevelIndex));
    220 	        if (LevelTree.get(mLevelRow, mLevelIndex).showWaitMessage) {
    221 	    		showWaitMessage();
    222 	        } else {
    223 	    		hideWaitMessage();
    224 	        }
    225         }
    226         mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    227 
    228         // This activity uses the media stream.
    229         setVolumeControlStream(AudioManager.STREAM_MUSIC);
    230 
    231 
    232         mSessionId = prefs.getLong(PreferenceConstants.PREFERENCE_SESSION_ID, System.currentTimeMillis());
    233 
    234 
    235         mEventReporter = null;
    236         mEventReporterThread = null;
    237         final boolean statsEnabled = prefs.getBoolean(PreferenceConstants.PREFERENCE_STATS_ENABLED, true);
    238         if (statsEnabled) {
    239 	        mEventReporter = new EventReporter();
    240 	        mEventReporterThread = new Thread(mEventReporter);
    241 	        mEventReporterThread.setName("EventReporter");
    242 	        mEventReporterThread.start();
    243         }
    244     }
    245 
    246 
    247     @Override
    248     protected void onDestroy() {
    249         DebugLog.d("AndouKun", "onDestroy()");
    250         mGame.stop();
    251         if (mEventReporterThread != null) {
    252 	        mEventReporter.stop();
    253 	        try {
    254 				mEventReporterThread.join();
    255 			} catch (InterruptedException e) {
    256 				mEventReporterThread.interrupt();
    257 			}
    258         }
    259         super.onDestroy();
    260 
    261     }
    262 
    263 
    264     @Override
    265     protected void onPause() {
    266         super.onPause();
    267         DebugLog.d("AndouKun", "onPause");
    268 
    269         hidePauseMessage();
    270 
    271         mGame.onPause();
    272         mGLSurfaceView.onPause();
    273         mGame.getRenderer().onPause();	// hack!
    274 
    275         if (mMethodTracing) {
    276             Debug.stopMethodTracing();
    277             mMethodTracing = false;
    278         }
    279         if (mSensorManager != null) {
    280             mSensorManager.unregisterListener(this);
    281         }
    282     }
    283 
    284     @Override
    285     protected void onResume() {
    286         super.onResume();
    287 
    288         // Preferences may have changed while we were paused.
    289         SharedPreferences prefs = getSharedPreferences(PreferenceConstants.PREFERENCE_NAME, MODE_PRIVATE);
    290         final boolean debugLogs = prefs.getBoolean(PreferenceConstants.PREFERENCE_ENABLE_DEBUG, false);
    291 
    292         if (VERSION < 0 || debugLogs) {
    293         	DebugLog.setDebugLogging(true);
    294         } else {
    295         	DebugLog.setDebugLogging(false);
    296         }
    297 
    298         DebugLog.d("AndouKun", "onResume");
    299         mGLSurfaceView.onResume();
    300         mGame.onResume(this, false);
    301 
    302 
    303         final boolean soundEnabled = prefs.getBoolean(PreferenceConstants.PREFERENCE_SOUND_ENABLED, true);
    304         final boolean safeMode = prefs.getBoolean(PreferenceConstants.PREFERENCE_SAFE_MODE, false);
    305         final boolean clickAttack = prefs.getBoolean(PreferenceConstants.PREFERENCE_CLICK_ATTACK, true);
    306         final boolean tiltControls = prefs.getBoolean(PreferenceConstants.PREFERENCE_TILT_CONTROLS, false);
    307         final int tiltSensitivity = prefs.getInt(PreferenceConstants.PREFERENCE_TILT_SENSITIVITY, 50);
    308         final int movementSensitivity = prefs.getInt(PreferenceConstants.PREFERENCE_MOVEMENT_SENSITIVITY, 100);
    309         final boolean onScreenControls = prefs.getBoolean(PreferenceConstants.PREFERENCE_SCREEN_CONTROLS, false);
    310 
    311         final int leftKey = prefs.getInt(PreferenceConstants.PREFERENCE_LEFT_KEY, KeyEvent.KEYCODE_DPAD_LEFT);
    312         final int rightKey = prefs.getInt(PreferenceConstants.PREFERENCE_RIGHT_KEY, KeyEvent.KEYCODE_DPAD_RIGHT);
    313         final int jumpKey = prefs.getInt(PreferenceConstants.PREFERENCE_JUMP_KEY, KeyEvent.KEYCODE_SPACE);
    314         final int attackKey = prefs.getInt(PreferenceConstants.PREFERENCE_ATTACK_KEY, KeyEvent.KEYCODE_SHIFT_LEFT);
    315 
    316         mGame.setSoundEnabled(soundEnabled);
    317         mGame.setControlOptions(clickAttack, tiltControls, tiltSensitivity, movementSensitivity, onScreenControls);
    318         mGame.setKeyConfig(leftKey, rightKey, jumpKey, attackKey);
    319         mGame.setSafeMode(safeMode);
    320 
    321         if (mSensorManager != null) {
    322             Sensor orientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
    323             if (orientation != null) {
    324                 mSensorManager.registerListener(this,
    325                     orientation,
    326                     SensorManager.SENSOR_DELAY_GAME,
    327                     null);
    328             }
    329         }
    330     }
    331 
    332     @Override
    333     public boolean onTrackballEvent(MotionEvent event) {
    334     	if (!mGame.isPaused()) {
    335 	        mGame.onTrackballEvent(event);
    336 	        final long time = System.currentTimeMillis();
    337 	        mLastRollTime = time;
    338     	}
    339         return true;
    340     }
    341 
    342     @Override
    343     public boolean onTouchEvent(MotionEvent event) {
    344     	if (!mGame.isPaused()) {
    345     		mGame.onTouchEvent(event);
    346 
    347 	        final long time = System.currentTimeMillis();
    348 	        if (event.getAction() == MotionEvent.ACTION_MOVE && time - mLastTouchTime < 32) {
    349 		        // Sleep so that the main thread doesn't get flooded with UI events.
    350 		        try {
    351 		            Thread.sleep(32);
    352 		        } catch (InterruptedException e) {
    353 		            // No big deal if this sleep is interrupted.
    354 		        }
    355 		        mGame.getRenderer().waitDrawingComplete();
    356 	        }
    357 	        mLastTouchTime = time;
    358     	}
    359         return true;
    360     }
    361 
    362     @Override
    363     public boolean onKeyDown(int keyCode, KeyEvent event) {
    364     	boolean result = true;
    365     	if (keyCode == KeyEvent.KEYCODE_BACK) {
    366 			final long time = System.currentTimeMillis();
    367     		if (time - mLastRollTime > ROLL_TO_FACE_BUTTON_DELAY &&
    368     				time - mLastTouchTime > ROLL_TO_FACE_BUTTON_DELAY) {
    369     			showDialog(QUIT_GAME_DIALOG);
    370     			result = true;
    371     		}
    372     	} else if (keyCode == KeyEvent.KEYCODE_MENU) {
    373     		result = true;
    374     		if (mGame.isPaused()) {
    375     			hidePauseMessage();
    376     			mGame.onResume(this, true);
    377     		} else {
    378     			final long time = System.currentTimeMillis();
    379     	        if (time - mLastRollTime > ROLL_TO_FACE_BUTTON_DELAY &&
    380     	        		time - mLastTouchTime > ROLL_TO_FACE_BUTTON_DELAY) {
    381     	        	showPauseMessage();
    382     	        	mGame.onPause();
    383     	        }
    384     	        if (VERSION < 0) {
    385     	        	result = false;	// Allow the debug menu to come up in debug mode.
    386     	        }
    387     		}
    388     	} else {
    389 		    result = mGame.onKeyDownEvent(keyCode);
    390 		    // Sleep so that the main thread doesn't get flooded with UI events.
    391 		    try {
    392 		        Thread.sleep(4);
    393 		    } catch (InterruptedException e) {
    394 		        // No big deal if this sleep is interrupted.
    395 		    }
    396     	}
    397         return result;
    398     }
    399 
    400     @Override
    401     public boolean onKeyUp(int keyCode, KeyEvent event) {
    402     	boolean result = false;
    403     	if (keyCode == KeyEvent.KEYCODE_BACK) {
    404     		result = true;
    405     	} else if (keyCode == KeyEvent.KEYCODE_MENU){
    406 	        if (VERSION < 0) {
    407 	        	result = false;	// Allow the debug menu to come up in debug mode.
    408 	        }
    409     	} else {
    410     		result = mGame.onKeyUpEvent(keyCode);
    411 	        // Sleep so that the main thread doesn't get flooded with UI events.
    412 	        try {
    413 	            Thread.sleep(4);
    414 	        } catch (InterruptedException e) {
    415 	            // No big deal if this sleep is interrupted.
    416 	        }
    417     	}
    418         return result;
    419     }
    420 
    421     @Override
    422     public boolean onCreateOptionsMenu(Menu menu) {
    423         super.onCreateOptionsMenu(menu);
    424         boolean handled = false;
    425         // Only allow the debug menu in development versions.
    426         if (VERSION < 0) {
    427 	        menu.add(0, CHANGE_LEVEL_ID, 0, R.string.change_level);
    428 	        menu.add(0, TEST_ANIMATION_ID, 0, R.string.test_animation);
    429 	        menu.add(0, TEST_DIARY_ID, 0, R.string.test_diary);
    430 
    431 	        menu.add(0, METHOD_TRACING_ID, 0, R.string.method_tracing);
    432 	        handled = true;
    433         }
    434 
    435         return handled;
    436     }
    437 
    438     @Override
    439     public boolean onMenuItemSelected(int featureId, MenuItem item) {
    440         Intent i;
    441         switch(item.getItemId()) {
    442         case CHANGE_LEVEL_ID:
    443             i = new Intent(this, LevelSelectActivity.class);
    444             startActivityForResult(i, ACTIVITY_CHANGE_LEVELS);
    445             return true;
    446         case TEST_ANIMATION_ID:
    447             i = new Intent(this, AnimationPlayerActivity.class);
    448             i.putExtra("animation", AnimationPlayerActivity.ROKUDOU_ENDING);
    449             startActivity(i);
    450             return true;
    451         case TEST_DIARY_ID:
    452             i = new Intent(this, DiaryActivity.class);
    453             i.putExtra("text", R.string.Diary10);
    454             startActivity(i);
    455             return true;
    456         case METHOD_TRACING_ID:
    457             if (mMethodTracing) {
    458                 Debug.stopMethodTracing();
    459             } else {
    460                 Debug.startMethodTracing("andou");
    461             }
    462             mMethodTracing = !mMethodTracing;
    463             return true;
    464         }
    465 
    466         return super.onMenuItemSelected(featureId, item);
    467     }
    468 
    469     @Override
    470     protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    471         super.onActivityResult(requestCode, resultCode, intent);
    472 
    473         if (requestCode == ACTIVITY_CHANGE_LEVELS) {
    474 	        if (resultCode == RESULT_OK) {
    475 	            mLevelRow = intent.getExtras().getInt("row");
    476 	            mLevelIndex = intent.getExtras().getInt("index");
    477 		        LevelTree.updateCompletedState(mLevelRow, 0);
    478 
    479 	            saveGame();
    480 
    481 	            mGame.setPendingLevel(LevelTree.get(mLevelRow, mLevelIndex));
    482 	            if (LevelTree.get(mLevelRow, mLevelIndex).showWaitMessage) {
    483             		showWaitMessage();
    484 	            } else {
    485             		hideWaitMessage();
    486 	            }
    487 
    488 	        }
    489         } else if (requestCode == ACTIVITY_ANIMATION_PLAYER) {
    490         	int lastAnimation = intent.getIntExtra("animation", -1);
    491         	// record ending events.
    492         	if (lastAnimation > -1) {
    493         		mGame.setLastEnding(lastAnimation);
    494         	}
    495         	// on finishing animation playback, force a level change.
    496         	onGameFlowEvent(GameFlowEvent.EVENT_GO_TO_NEXT_LEVEL, 0);
    497         }
    498     }
    499 
    500     /*
    501      *  When the game thread needs to stop its own execution (to go to a new level, or restart the
    502      *  current level), it registers a runnable on the main thread which orders the action via this
    503      *  function.
    504      */
    505     public void onGameFlowEvent(int eventCode, int index) {
    506        switch (eventCode) {
    507            case GameFlowEvent.EVENT_END_GAME:
    508                mGame.stop();
    509                finish();
    510                break;
    511            case GameFlowEvent.EVENT_RESTART_LEVEL:
    512         	   if (LevelTree.get(mLevelRow, mLevelIndex).restartable) {
    513         		   if (mEventReporter != null) {
    514 	        		   mEventReporter.addEvent(EventReporter.EVENT_DEATH,
    515 	        				   mGame.getLastDeathPosition().x,
    516 	        				   mGame.getLastDeathPosition().y,
    517 	        				   mGame.getGameTime(),
    518 	        				   LevelTree.get(mLevelRow, mLevelIndex).name,
    519 	        				   VERSION,
    520 	        				   mSessionId);
    521         		   }
    522         		   mGame.restartLevel();
    523         		   break;
    524         	   }
    525         	   // else, fall through and go to the next level.
    526            case GameFlowEvent.EVENT_GO_TO_NEXT_LEVEL:
    527                LevelTree.get(mLevelRow, mLevelIndex).completed = true;
    528                final LevelTree.LevelGroup currentGroup = LevelTree.levels.get(mLevelRow);
    529                final int count = currentGroup.levels.size();
    530                boolean groupCompleted = true;
    531                if (mEventReporter != null) {
    532 	               mEventReporter.addEvent(EventReporter.EVENT_BEAT_LEVEL,
    533 	    				   0,
    534 	    				   0,
    535 	    				   mGame.getGameTime(),
    536 	    				   LevelTree.get(mLevelRow, mLevelIndex).name,
    537 	    				   VERSION,
    538 	    				   mSessionId);
    539                }
    540                for (int x = 0; x < count; x++) {
    541             	   if (currentGroup.levels.get(x).completed == false) {
    542             		   // We haven't completed the group yet.
    543             		   mLevelIndex = x;
    544             		   groupCompleted = false;
    545             		   break;
    546             	   }
    547                }
    548 
    549                if (groupCompleted) {
    550                    mLevelIndex = 0;
    551                    mLevelRow++;
    552                }
    553 
    554     		   mTotalGameTime += mGame.getGameTime();
    555     		   mRobotsDestroyed += mGame.getRobotsDestroyed();
    556     		   mPearlsCollected += mGame.getPearlsCollected();
    557     		   mPearlsTotal += mGame.getPearlsTotal();
    558 
    559                if (mLevelRow < LevelTree.levels.size()) {
    560             	   final LevelTree.Level currentLevel = LevelTree.get(mLevelRow, mLevelIndex);
    561             	   if (currentLevel.inThePast || LevelTree.levels.get(mLevelRow).levels.size() > 1) {
    562             		   // go to the level select.
    563             		   Intent i = new Intent(this, LevelSelectActivity.class);
    564                        startActivityForResult(i, ACTIVITY_CHANGE_LEVELS);
    565                        if (UIConstants.mOverridePendingTransition != null) {
    566         	 		       try {
    567         	 		    	  UIConstants.mOverridePendingTransition.invoke(AndouKun.this, R.anim.activity_fade_in, R.anim.activity_fade_out);
    568         	 		       } catch (InvocationTargetException ite) {
    569         	 		           DebugLog.d("Activity Transition", "Invocation Target Exception");
    570         	 		       } catch (IllegalAccessException ie) {
    571         	 		    	   DebugLog.d("Activity Transition", "Illegal Access Exception");
    572         	 		       }
    573         	            }
    574             	   } else {
    575             		   // go directly to the next level
    576 	                   mGame.setPendingLevel(currentLevel);
    577 	                   if (currentLevel.showWaitMessage) {
    578 	                	   showWaitMessage();
    579 	                   } else {
    580 	                	   hideWaitMessage();
    581 	                   }
    582 	                   mGame.requestNewLevel();
    583             	   }
    584             	   saveGame();
    585 
    586                } else {
    587             	   if (mEventReporter != null) {
    588 	            	   mEventReporter.addEvent(EventReporter.EVENT_BEAT_GAME,
    589 	        				   0,
    590 	        				   0,
    591 	        				   mGame.getGameTime(),
    592 	        				   "end",
    593 	        				   VERSION,
    594 	        				   mSessionId);
    595             	   }
    596                    // We beat the game!
    597             	   mLevelRow = 0;
    598             	   mLevelIndex = 0;
    599             	   mLastEnding = mGame.getLastEnding();
    600             	   mExtrasUnlocked = true;
    601             	   saveGame();
    602                    mGame.stop();
    603                    Intent i = new Intent(this, GameOverActivity.class);
    604                    startActivity(i);
    605                    if (UIConstants.mOverridePendingTransition != null) {
    606     	 		       try {
    607     	 		    	  UIConstants.mOverridePendingTransition.invoke(AndouKun.this, R.anim.activity_fade_in, R.anim.activity_fade_out);
    608     	 		       } catch (InvocationTargetException ite) {
    609     	 		           DebugLog.d("Activity Transition", "Invocation Target Exception");
    610     	 		       } catch (IllegalAccessException ie) {
    611     	 		    	   DebugLog.d("Activity Transition", "Illegal Access Exception");
    612     	 		       }
    613     	            }
    614                    finish();
    615 
    616                }
    617                break;
    618            case GameFlowEvent.EVENT_SHOW_DIARY:
    619                Intent i = new Intent(this, DiaryActivity.class);
    620                LevelTree.Level level = LevelTree.get(mLevelRow, mLevelIndex);
    621                level.diaryCollected = true;
    622                i.putExtra("text", level.dialogResources.diaryEntry);
    623                startActivity(i);
    624                if (UIConstants.mOverridePendingTransition != null) {
    625  	 		       try {
    626  	 		    	  UIConstants.mOverridePendingTransition.invoke(AndouKun.this, R.anim.activity_fade_in, R.anim.activity_fade_out);
    627  	 		       } catch (InvocationTargetException ite) {
    628  	 		           DebugLog.d("Activity Transition", "Invocation Target Exception");
    629  	 		       } catch (IllegalAccessException ie) {
    630  	 		    	   DebugLog.d("Activity Transition", "Illegal Access Exception");
    631  	 		       }
    632  	            }
    633                break;
    634 
    635            case GameFlowEvent.EVENT_SHOW_DIALOG_CHARACTER1:
    636         	   i = new Intent(this, ConversationDialogActivity.class);
    637                i.putExtra("levelRow", mLevelRow);
    638                i.putExtra("levelIndex", mLevelIndex);
    639                i.putExtra("index", index);
    640                i.putExtra("character", 1);
    641                startActivity(i);
    642                break;
    643 
    644            case GameFlowEvent.EVENT_SHOW_DIALOG_CHARACTER2:
    645         	   i = new Intent(this, ConversationDialogActivity.class);
    646                i.putExtra("levelRow", mLevelRow);
    647                i.putExtra("levelIndex", mLevelIndex);
    648                i.putExtra("index", index);
    649                i.putExtra("character", 2);
    650                startActivity(i);
    651                break;
    652            case GameFlowEvent.EVENT_SHOW_ANIMATION:
    653         	   i = new Intent(this, AnimationPlayerActivity.class);
    654                i.putExtra("animation", index);
    655                startActivityForResult(i, ACTIVITY_ANIMATION_PLAYER);
    656                if (UIConstants.mOverridePendingTransition != null) {
    657 	 		       try {
    658 	 		    	  UIConstants.mOverridePendingTransition.invoke(AndouKun.this, R.anim.activity_fade_in, R.anim.activity_fade_out);
    659 	 		       } catch (InvocationTargetException ite) {
    660 	 		           DebugLog.d("Activity Transition", "Invocation Target Exception");
    661 	 		       } catch (IllegalAccessException ie) {
    662 	 		    	   DebugLog.d("Activity Transition", "Illegal Access Exception");
    663 	 		       }
    664 	            }
    665                break;
    666 
    667        }
    668     }
    669 
    670     protected void saveGame() {
    671     	if (mPrefsEditor != null) {
    672     		final int completed = LevelTree.packCompletedLevels(mLevelRow);
    673     		mPrefsEditor.putInt(PreferenceConstants.PREFERENCE_LEVEL_ROW, mLevelRow);
    674     		mPrefsEditor.putInt(PreferenceConstants.PREFERENCE_LEVEL_INDEX, mLevelIndex);
    675     		mPrefsEditor.putInt(PreferenceConstants.PREFERENCE_LEVEL_COMPLETED, completed);
    676     		mPrefsEditor.putLong(PreferenceConstants.PREFERENCE_SESSION_ID, mSessionId);
    677     		mPrefsEditor.putFloat(PreferenceConstants.PREFERENCE_TOTAL_GAME_TIME, mTotalGameTime);
    678     		mPrefsEditor.putInt(PreferenceConstants.PREFERENCE_LAST_ENDING, mLastEnding);
    679     		mPrefsEditor.putInt(PreferenceConstants.PREFERENCE_ROBOTS_DESTROYED, mRobotsDestroyed);
    680     		mPrefsEditor.putInt(PreferenceConstants.PREFERENCE_PEARLS_COLLECTED, mPearlsCollected);
    681     		mPrefsEditor.putInt(PreferenceConstants.PREFERENCE_PEARLS_TOTAL, mPearlsTotal);
    682     		mPrefsEditor.putInt(PreferenceConstants.PREFERENCE_LINEAR_MODE, mLinearMode);
    683     		mPrefsEditor.putBoolean(PreferenceConstants.PREFERENCE_EXTRAS_UNLOCKED, mExtrasUnlocked);
    684     		mPrefsEditor.putInt(PreferenceConstants.PREFERENCE_DIFFICULTY, mDifficulty);
    685     		mPrefsEditor.commit();
    686     	}
    687     }
    688 
    689     protected void showPauseMessage() {
    690     	if (mPauseMessage != null) {
    691     		mPauseMessage.setVisibility(View.VISIBLE);
    692     	}
    693     	if (mLevelNameBox != null && mLevelName != null) {
    694     		mLevelName.setText(LevelTree.get(mLevelRow, mLevelIndex).name);
    695     		mLevelNameBox.setVisibility(View.VISIBLE);
    696     	}
    697     }
    698 
    699     protected void hidePauseMessage() {
    700     	if (mPauseMessage != null) {
    701     		mPauseMessage.setVisibility(View.GONE);
    702     	}
    703     	if (mLevelNameBox != null) {
    704     		mLevelNameBox.setVisibility(View.GONE);
    705     	}
    706     }
    707 
    708     protected void showWaitMessage() {
    709     	if (mWaitMessage != null) {
    710     		mWaitMessage.setVisibility(View.VISIBLE);
    711     		mWaitMessage.startAnimation(mWaitFadeAnimation);
    712     	}
    713     }
    714 
    715     protected void hideWaitMessage() {
    716     	if (mWaitMessage != null) {
    717     		mWaitMessage.setVisibility(View.GONE);
    718     		mWaitMessage.clearAnimation();
    719     	}
    720     }
    721 
    722 
    723     public void onAccuracyChanged(Sensor sensor, int accuracy) {
    724         // TODO Auto-generated method stub
    725 
    726     }
    727 
    728 
    729     public void onSensorChanged(SensorEvent event) {
    730        synchronized (this) {
    731            if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
    732                final float x = event.values[1];
    733                final float y = event.values[2];
    734                final float z = event.values[0];
    735                mGame.onOrientationEvent(x, y, z);
    736            }
    737        }
    738     }
    739 
    740     @Override
    741     protected Dialog onCreateDialog(int id) {
    742         Dialog dialog = null;
    743         if (id == QUIT_GAME_DIALOG) {
    744 
    745             dialog = new AlertDialog.Builder(this)
    746                 .setTitle(R.string.quit_game_dialog_title)
    747                 .setPositiveButton(R.string.quit_game_dialog_ok, new DialogInterface.OnClickListener() {
    748                     public void onClick(DialogInterface dialog, int whichButton) {
    749                     	finish();
    750                     	if (UIConstants.mOverridePendingTransition != null) {
    751          	 		       try {
    752          	 		    	  UIConstants.mOverridePendingTransition.invoke(AndouKun.this, R.anim.activity_fade_in, R.anim.activity_fade_out);
    753          	 		       } catch (InvocationTargetException ite) {
    754          	 		           DebugLog.d("Activity Transition", "Invocation Target Exception");
    755          	 		       } catch (IllegalAccessException ie) {
    756          	 		    	   DebugLog.d("Activity Transition", "Illegal Access Exception");
    757          	 		       }
    758          	            }
    759                     }
    760                 })
    761                 .setNegativeButton(R.string.quit_game_dialog_cancel, null)
    762                 .setMessage(R.string.quit_game_dialog_message)
    763                 .create();
    764         }
    765         return dialog;
    766     }
    767 }
    768