/androidsays/src/com/google/marvin/androidsays/WidgetGameService.java

http://eyes-free.googlecode.com/ · Java · 222 lines · 162 code · 33 blank · 27 comment · 21 complexity · d0b7b1eb7849d55dd9ebd2682c8af2c2 MD5 · raw file

  1. package com.google.marvin.androidsays;
  2. import java.util.ArrayList;
  3. import com.google.marvin.androidsays.GameView.SequencePlayer;
  4. import android.app.Service;
  5. import android.content.Context;
  6. import android.content.Intent;
  7. import android.os.IBinder;
  8. import android.os.RemoteException;
  9. import android.os.Vibrator;
  10. import android.util.Log;
  11. import android.widget.Toast;
  12. public class WidgetGameService extends Service {
  13. private WidgetGameService self;
  14. private boolean needReset = true;
  15. private Vibrator vibe;
  16. private long[] pattern = {
  17. 0, 1, 40, 41
  18. };
  19. private int currentIndex;
  20. private ArrayList<Integer> sequence;
  21. private int score;
  22. private SfxController sfx;
  23. // These are timings used to control pauses between actions
  24. // All times are specified in ms
  25. private int initialWaitTime = 550;
  26. private int waitTimeBetweenTones = 310;
  27. private int flashDuration = 250;
  28. // Used for locking the screen
  29. private boolean screenActive;
  30. private int inputCount;
  31. public void onStart(Intent intent, int startId) {
  32. super.onStart(intent, startId);
  33. this.setForeground(true);
  34. if (needReset) {
  35. self = this;
  36. sfx = new SfxController(this);
  37. // Hard code this for now
  38. sfx.loadSoundResource("[0]", R.raw.green_snd);
  39. sfx.loadSoundResource("[1]", R.raw.red_snd);
  40. sfx.loadSoundResource("[2]", R.raw.yellow_snd);
  41. sfx.loadSoundResource("[3]", R.raw.blue_snd);
  42. vibe = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
  43. sequence = new ArrayList<Integer>();
  44. currentIndex = 0;
  45. screenActive = false;
  46. score = 0;
  47. inputCount = 0;
  48. needReset = false;
  49. sfx.play("Android says:", 0);
  50. playSequence();
  51. } else {
  52. if (screenActive) {
  53. inputCount++;
  54. if (inputCount >= sequence.size()) {
  55. screenActive = false;
  56. }
  57. String input = intent.getStringExtra("input");
  58. input = input.replaceAll("com.google.marvin.androidsays.0", "");
  59. sfx.play("[" + input + "]", 0);
  60. vibe.vibrate(pattern, -1);
  61. evalInput(Integer.parseInt(input));
  62. }
  63. }
  64. }
  65. private void evalInput(final int input) {
  66. Thread t = new Thread() {
  67. @Override
  68. public void run() {
  69. try {
  70. Thread.sleep(1000);
  71. } catch (InterruptedException e) {
  72. // This should not get interrupted
  73. e.printStackTrace();
  74. }
  75. Log.e("evalInput", "input is: " + input);
  76. if (currentIndex >= sequence.size()) {
  77. return;
  78. }
  79. if (input == sequence.get(currentIndex)) {
  80. currentIndex++;
  81. if (currentIndex >= sequence.size()) {
  82. currentIndex = 0;
  83. sfx.play("[right]", 1);
  84. score++;
  85. playSequence();
  86. }
  87. } else {
  88. sfx.play("[wrong]", 1);
  89. gameOver();
  90. }
  91. }
  92. };
  93. t.start();
  94. }
  95. private void playSequence() {
  96. (new Thread(new SequencePlayer())).start();
  97. }
  98. // Generates sequence either by adding one random number to the end
  99. // (classic)
  100. // or by generating a brand new sequence of a set length (challenge).
  101. private void generateSequence() {
  102. currentIndex = 0;
  103. int random = ((int)(Math.random() * 100)) % 4;
  104. sequence.add(random);
  105. }
  106. /**
  107. * Plays back the sequence This needs to be done in a different thread
  108. * because it uses sleep to keep the visual flashing in sync with the
  109. * sounds.
  110. */
  111. public class SequencePlayer implements Runnable {
  112. public void run() {
  113. screenActive = false;
  114. generateSequence();
  115. try {
  116. Thread.sleep(initialWaitTime);
  117. } catch (InterruptedException e) {
  118. // Nothing needs to be done if the sleep is interrupted.
  119. e.printStackTrace();
  120. }
  121. for (int i = 0; i < sequence.size(); i++) {
  122. // TODO(clchen): - find a more graceful way of stopping the
  123. // sound
  124. // if (parent.halt) {
  125. // inputCount = 0;
  126. // screenActive = true;
  127. // return;
  128. // }
  129. // TODO: Use prefs here!
  130. int delay = -1; // parent.speedPrefDelay;
  131. // Negative speed_pref_delay means scaling
  132. if (delay < 0) {
  133. delay = 300 - (sequence.size() * 10);
  134. }
  135. // Scaled delay must be 0 or positive
  136. if (delay < 0) {
  137. delay = 0;
  138. }
  139. try {
  140. Thread.sleep(waitTimeBetweenTones + delay);
  141. } catch (InterruptedException e) {
  142. // Nothing needs to be done if the sleep is interrupted.
  143. e.printStackTrace();
  144. }
  145. Log.e("SequencePlayer", sequence.get(i) + "");
  146. Intent flashIntent;
  147. if (sequence.get(i) == 0) {
  148. flashIntent = new Intent("com.google.marvin.androidsays.flash.00");
  149. sfx.play("[0]", 1);
  150. } else if (sequence.get(i) == 1) {
  151. flashIntent = new Intent("com.google.marvin.androidsays.flash.01");
  152. sfx.play("[1]", 1);
  153. } else if (sequence.get(i) == 2) {
  154. flashIntent = new Intent("com.google.marvin.androidsays.flash.02");
  155. sfx.play("[2]", 1);
  156. } else {
  157. flashIntent = new Intent("com.google.marvin.androidsays.flash.03");
  158. sfx.play("[3]", 1);
  159. }
  160. self.sendBroadcast(flashIntent);
  161. try {
  162. Thread.sleep(flashDuration);
  163. } catch (InterruptedException e) {
  164. // Nothing needs to be done if the sleep is interrupted.
  165. e.printStackTrace();
  166. }
  167. Intent unflashIntent = new Intent("com.google.marvin.androidsays.unflash");
  168. self.sendBroadcast(unflashIntent);
  169. }
  170. inputCount = 0;
  171. screenActive = true;
  172. }
  173. }
  174. private void gameOver() {
  175. String scoreStr = Integer.toString(score);
  176. sfx.play("Game over. Your score is:", 1);
  177. sfx.play(scoreStr, 1);
  178. Intent showScoreIntent = new Intent("com.google.marvin.androidsays.showScore");
  179. showScoreIntent.putExtra("score", scoreStr);
  180. self.sendBroadcast(showScoreIntent);
  181. needReset = true;
  182. screenActive = true;
  183. }
  184. @Override
  185. public IBinder onBind(Intent arg0) {
  186. // Not binding to the service
  187. return null;
  188. }
  189. }