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
onCreate(Bundle savedInstanceState)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
onDestroy()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
onPause()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
onResume()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
onTrackballEvent(MotionEvent event)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
onTouchEvent(MotionEvent event)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
onKeyDown(int keyCode, KeyEvent event)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
onKeyUp(int keyCode, KeyEvent event)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
onCreateOptionsMenu(Menu menu)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
onMenuItemSelected(int featureId, MenuItem item)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
onActivityResult(int requestCode, int resultCode, Intent intent)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      */
onGameFlowEvent(int eventCode, int index)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 
saveGame()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 
showPauseMessage()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 
hidePauseMessage()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 
showWaitMessage()708     protected void showWaitMessage() {
709     	if (mWaitMessage != null) {
710     		mWaitMessage.setVisibility(View.VISIBLE);
711     		mWaitMessage.startAnimation(mWaitFadeAnimation);
712     	}
713     }
714 
hideWaitMessage()715     protected void hideWaitMessage() {
716     	if (mWaitMessage != null) {
717     		mWaitMessage.setVisibility(View.GONE);
718     		mWaitMessage.clearAnimation();
719     	}
720     }
721 
722 
onAccuracyChanged(Sensor sensor, int accuracy)723     public void onAccuracyChanged(Sensor sensor, int accuracy) {
724         // TODO Auto-generated method stub
725 
726     }
727 
728 
onSensorChanged(SensorEvent event)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
onCreateDialog(int id)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