1
1
package website .bloop .app .activities ;
2
2
3
- import android .app .Activity ;
4
3
import android .content .Context ;
5
4
import android .content .Intent ;
6
5
import android .content .SharedPreferences ;
10
9
import android .support .design .widget .FloatingActionButton ;
11
10
import android .support .v4 .view .animation .LinearOutSlowInInterpolator ;
12
11
import android .support .v4 .view .animation .PathInterpolatorCompat ;
13
- import android .support .v7 .app .AlertDialog ;
14
12
import android .support .v7 .app .AppCompatActivity ;
15
13
import android .support .v7 .widget .Toolbar ;
16
14
import android .util .Log ;
17
15
import android .view .Menu ;
18
16
import android .view .MenuInflater ;
19
17
import android .view .MenuItem ;
18
+ import android .view .View ;
20
19
import android .widget .RelativeLayout ;
20
+ import android .widget .Toast ;
21
21
22
22
import com .google .android .gms .common .api .GoogleApiClient ;
23
23
import com .google .android .gms .games .Games ;
37
37
import website .bloop .app .R ;
38
38
import website .bloop .app .api .BloopAPIService ;
39
39
import website .bloop .app .api .CapturedFlag ;
40
+ import website .bloop .app .api .NearbyFlag ;
40
41
import website .bloop .app .api .PlayerLocation ;
42
+ import website .bloop .app .dialogs .FlagCapturedDialogFragment ;
41
43
import website .bloop .app .fragments .BootprintMapFragment ;
42
44
import website .bloop .app .sound .BloopSoundPlayer ;
43
45
import website .bloop .app .views .BigButtonView ;
46
+ import website .bloop .app .views .FlagView ;
44
47
import website .bloop .app .views .SonarView ;
45
48
46
49
/**
47
- *
50
+ * Main game activity, which shows bloop animations and sounds, as well as controls
51
+ * game interaction such as capturing bloops or checking the leaderboards.
48
52
*/
49
53
public class BloopActivity extends AppCompatActivity {
50
54
private static final String PREF_SOUND = "MutePREF" ;
51
55
private static final String PREF_SOUND_VAL = "muted" ;
52
56
private static final String TAG = "BloopActivity" ;
57
+ private static final String FLAG_CAPTURED_DIALOG_TAG = "FlagDialog" ;
53
58
private static final long LOCATION_UPDATE_MS = 5000 ;
54
59
private static final int REQUEST_LEADERBOARD = 1000 ;
55
60
@@ -82,8 +87,7 @@ public class BloopActivity extends AppCompatActivity {
82
87
private long mLastBloopTime ;
83
88
private Runnable mBloopRunnable ;
84
89
85
- private long mNearbyFlagId ;
86
- private String mNearbyFlagOwner ;
90
+ private NearbyFlag mNearbyFlag ;
87
91
88
92
private GoogleApiClient mGoogleApiClient ;
89
93
private BloopAPIService mService ;
@@ -117,7 +121,7 @@ protected void onCreate(Bundle savedInstanceState) {
117
121
// hide flag by default
118
122
mPlaceFlagButtonMarginBottom = getResources ().getDimension (R .dimen .fab_margin );
119
123
// TODO: this doesn't actually animate the fab far enough
120
- mPlaceFlagButton .setTranslationY ( mPlaceFlagButton . getHeight () + mPlaceFlagButtonMarginBottom );
124
+ mPlaceFlagButton .setVisibility ( View . INVISIBLE );
121
125
122
126
mService .checkHasPlacedFlag (mApplication .getPlayerId ())
123
127
.subscribeOn (Schedulers .newThread ())
@@ -154,6 +158,9 @@ protected void onCreate(Bundle savedInstanceState) {
154
158
mute = mutePref .getBoolean (PREF_SOUND_VAL , false );
155
159
}
156
160
161
+ /**
162
+ * Hide the fab and blocking the ability to place a flag.
163
+ */
157
164
private void hidePlaceFlag () {
158
165
mPlaceFlagButton
159
166
.animate ()
@@ -163,7 +170,20 @@ private void hidePlaceFlag() {
163
170
.start ();
164
171
}
165
172
173
+ /**
174
+ * Show the fab and add the ability to place a flag.
175
+ */
166
176
private void showPlaceFlag () {
177
+ // if we have set the visibility to invisible (as we do in onCreate), we should put this
178
+ // below the screen
179
+ if (mPlaceFlagButton .getVisibility () == View .INVISIBLE ) {
180
+ mPlaceFlagButton .setTranslationY (
181
+ mPlaceFlagButton .getHeight () + mPlaceFlagButtonMarginBottom
182
+ );
183
+
184
+ mPlaceFlagButton .setVisibility (View .VISIBLE );
185
+ }
186
+
167
187
mPlaceFlagButton
168
188
.animate ()
169
189
.translationY (0 )
@@ -172,13 +192,17 @@ private void showPlaceFlag() {
172
192
.start ();
173
193
}
174
194
195
+ /**
196
+ * Draw a different bloop over the main bloops to prompt the user to click and capture a flag.
197
+ */
175
198
private void captureFlag () {
176
- if (mNearbyFlagId != 0 ) {
177
- CapturedFlag flag = new CapturedFlag (mNearbyFlagId , mApplication .getPlayerId ());
178
-
179
- String requestedFlagOwner = mNearbyFlagOwner ;
199
+ if (mNearbyFlag != null ) {
200
+ CapturedFlag flag = new CapturedFlag (
201
+ mNearbyFlag .getFlagId (),
202
+ mApplication .getPlayerId ()
203
+ );
180
204
181
- Activity self = this ;
205
+ // TODO: slowly mute the boop sounds so the bloop is better
182
206
183
207
mService .captureFlag (flag )
184
208
.subscribeOn (Schedulers .newThread ())
@@ -189,22 +213,65 @@ private void captureFlag() {
189
213
mBloopSoundPlayer .bloop ();
190
214
}
191
215
192
- final AlertDialog .Builder builder = new AlertDialog .Builder (self );
193
- builder .setTitle (String .format (getString (R .string .you_captured_x_flag_format_string ), requestedFlagOwner ))
194
- .setMessage ("Add one more to that collection" )
195
- .setNeutralButton (
196
- getString (R .string .dismiss_capture_flag_dialog_text ),
197
- (dialogInterface , i ) -> dialogInterface .dismiss ())
198
- .show ();
216
+ final FlagView flagView = new FlagView (getBaseContext ());
217
+ flagView .setFlagColor (mNearbyFlag .getColor ());
218
+
219
+ final FlagCapturedDialogFragment flagCapturedDialog = new FlagCapturedDialogFragment ();
220
+ final Bundle flagCapturedDialogBundle = new Bundle ();
221
+ flagCapturedDialogBundle .putString (
222
+ FlagCapturedDialogFragment .ARG_TITLE ,
223
+ String .format (getString (R .string .you_captured_x_flag_format_string ), mNearbyFlag .getPlayerName ())
224
+ );
225
+
226
+ flagCapturedDialogBundle .putInt (
227
+ FlagCapturedDialogFragment .ARG_FLAG_COLOR ,
228
+ mNearbyFlag .getColor ()
229
+ );
230
+
231
+ flagCapturedDialogBundle .putString (
232
+ FlagCapturedDialogFragment .ARG_POINTS_TEXT ,
233
+ "Flag capture: +1 point"
234
+ );
235
+
236
+ final int playerScore = 1 ; // TODO: from API
237
+
238
+ flagCapturedDialogBundle .putString (
239
+ FlagCapturedDialogFragment .ARG_TOTAL_SCORE ,
240
+ "Score: " + playerScore
241
+ );
242
+
243
+ Games .Leaderboards .submitScore (
244
+ mGoogleApiClient ,
245
+ getString (R .string .leaderboard_bloop_high_scores ),
246
+ playerScore
247
+ );
248
+
249
+ flagCapturedDialog .setArguments (flagCapturedDialogBundle );
250
+ flagCapturedDialog .show (getSupportFragmentManager (), "FlagDialog" );
251
+
199
252
mBigButtonView .hide ();
200
253
}, throwable -> {
254
+ Log .e (TAG , throwable .getMessage ());
201
255
mBigButtonView .hide ();
202
256
});
203
257
}
204
258
}
205
259
260
+ private void deleteFlag () {
261
+ mService .deleteFlag (mApplication .getPlayerId ())
262
+ .subscribeOn (Schedulers .newThread ())
263
+ .observeOn (AndroidSchedulers .mainThread ())
264
+ .subscribe (ownFlag -> {
265
+ Toast .makeText (this , "Flag deleted" , Toast .LENGTH_SHORT ).show ();
266
+ }, throwable -> {
267
+ Log .e (TAG , throwable .getMessage ());
268
+ });
269
+
270
+ showPlaceFlag ();
271
+ }
272
+
206
273
/**
207
- * Shows an activity that describes the open source libraries used in this project
274
+ * Shows an activity that describes the open source libraries used in this project.
208
275
*/
209
276
private void startAboutLibraries () {
210
277
new LibsBuilder ()
@@ -214,6 +281,10 @@ private void startAboutLibraries() {
214
281
.start (this );
215
282
}
216
283
284
+ /**
285
+ * Request location permissions so we can track location.
286
+ * @return
287
+ */
217
288
private Observable <Boolean > requestLocationPermissions () {
218
289
return RxPermissions .getInstance (this )
219
290
.request (android .Manifest .permission .ACCESS_FINE_LOCATION )
@@ -222,6 +293,9 @@ private Observable<Boolean> requestLocationPermissions() {
222
293
});
223
294
}
224
295
296
+ /**
297
+ * Main location tracking logic.
298
+ */
225
299
private void startTrackingLocation () {
226
300
Log .d (TAG , "Location tracking started" );
227
301
@@ -233,24 +307,31 @@ private void startTrackingLocation() {
233
307
// this should never be called if the permission hasn't been granted.
234
308
//noinspection MissingPermission
235
309
mLocationDisposable = mRxLocation .location ().updates (locationRequest )
236
- //TODO: we might want to clean this data before passing it on
237
310
.doOnEach (location -> mCurrentLocation = location .getValue ())
238
311
.doOnEach (location -> mBootprintMapFragment .updateMapCenter (location .getValue ()))
239
312
.doOnEach (location -> mBootprintMapFragment .updatePlayerLocation (location .getValue ()))
240
313
.doOnEach (location -> updateBloopFrequency ())
241
314
.subscribe ();
242
315
}
243
316
317
+ /**
318
+ * Lets a user customize and place a flag at their current location.
319
+ * Passes intent to FlagCreationActivity.
320
+ */
244
321
private void placeFlag () {
245
322
if (mCurrentLocation != null ) {
246
- // TODO organize bloop and placing flag better
247
323
248
324
final Intent placeFlagIntent = new Intent (this , FlagCreationActivity .class );
249
325
placeFlagIntent .putExtra (FlagCreationActivity .FLAG_LOCATION , mCurrentLocation );
250
326
startActivity (placeFlagIntent );
327
+
328
+ hidePlaceFlag ();
251
329
}
252
330
}
253
331
332
+ /**
333
+ * Check with server to compute closest flag and update how often bloops are animated on-screen.
334
+ */
254
335
private void updateBloopFrequency () {
255
336
if (mCurrentLocation != null ) {
256
337
mService .getNearestFlag (
@@ -265,13 +346,11 @@ private void updateBloopFrequency() {
265
346
// if player name is present, that means that there is a flag a
266
347
// capturable distance away
267
348
// TODO: alert the user that they can capture this flag
268
- mNearbyFlagId = nearbyFlag .getFlagId ();
269
- mNearbyFlagOwner = nearbyFlag .getPlayerName ();
349
+ mNearbyFlag = nearbyFlag ;
270
350
271
351
mBigButtonView .show ();
272
352
} else {
273
- mNearbyFlagId = 0 ; // this is the "null" value of the flag id
274
- mNearbyFlagOwner = null ;
353
+ mNearbyFlag = null ;
275
354
mBigButtonView .hide ();
276
355
}
277
356
@@ -280,6 +359,9 @@ private void updateBloopFrequency() {
280
359
}
281
360
}
282
361
362
+ /**
363
+ * Actually reschedule the "timer" to redraw a bloop on screen.
364
+ */
283
365
private void rescheduleBloops () {
284
366
double timeSinceLastBloop = (double ) (System .currentTimeMillis () - mLastBloopTime );
285
367
@@ -323,6 +405,9 @@ public void run() {
323
405
}
324
406
}
325
407
408
+ /**
409
+ * BLOOP!!!
410
+ */
326
411
private void bloop () {
327
412
mSonarView .bloop ();
328
413
if (!mute ) {
@@ -332,6 +417,11 @@ private void bloop() {
332
417
mLastBloopTime = System .currentTimeMillis ();
333
418
}
334
419
420
+ /**
421
+ * Inflate options dropdown, as well as set mute checkbox to preexisting value, if one available.
422
+ * @param menu
423
+ * @return
424
+ */
335
425
public boolean onCreateOptionsMenu (Menu menu ) {
336
426
MenuInflater inflater = getMenuInflater ();
337
427
inflater .inflate (R .menu .bloop_activity_menu , menu );
@@ -343,6 +433,11 @@ public boolean onCreateOptionsMenu(Menu menu) {
343
433
return true ;
344
434
}
345
435
436
+ /**
437
+ * Show leaderboards, mute audio, show library information.
438
+ * @param item
439
+ * @return
440
+ */
346
441
@ Override
347
442
public boolean onOptionsItemSelected (MenuItem item ) {
348
443
// Handle item selection
@@ -356,6 +451,9 @@ public boolean onOptionsItemSelected(MenuItem item) {
356
451
REQUEST_LEADERBOARD
357
452
);
358
453
return true ;
454
+ case R .id .item_delete :
455
+ deleteFlag ();
456
+ return true ;
359
457
case R .id .item_mute :
360
458
SharedPreferences .Editor ed = mutePref .edit ();
361
459
if (!mute ) {
0 commit comments