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
17package com.replica.replicaisland;
18
19import java.lang.reflect.InvocationTargetException;
20import java.lang.reflect.Method;
21
22import android.app.Activity;
23import android.app.AlertDialog;
24import android.app.Dialog;
25import android.content.DialogInterface;
26import android.content.Intent;
27import android.content.SharedPreferences;
28import android.hardware.Sensor;
29import android.hardware.SensorEvent;
30import android.hardware.SensorEventListener;
31import android.hardware.SensorManager;
32import android.media.AudioManager;
33import android.os.Bundle;
34import android.os.Debug;
35import android.util.DisplayMetrics;
36import android.view.KeyEvent;
37import android.view.Menu;
38import android.view.MenuItem;
39import android.view.MotionEvent;
40import android.view.View;
41import android.view.animation.Animation;
42import android.view.animation.AnimationUtils;
43import 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 */
50public 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