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