/*
* Copyright (C) 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.apps.santatracker.village;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.app.UiModeManager;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import com.google.android.apps.santatracker.util.AnalyticsManager;
import com.google.android.apps.santatracker.util.MeasurementManager;
import com.google.firebase.analytics.FirebaseAnalytics;
/**
* Santa's village.
*/
public class Village extends Fragment implements VillageView.VillageInterface {
private HorizontalScrollingImage mImageUfo;
private HorizontalScrollingImage mImagePlane;
private HorizontalScrollingImageGroup mImageClouds;
private int mOffsetVertical = 0;
private boolean mPlaneEnabled = true;
private boolean mImagesInitialised = false;
private TouchListener mTouchListener = new TouchListener();
private VillageListener mCallback;
private FirebaseAnalytics mMeasurement;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mCallback = (VillageListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + "must implement VillageInterface.");
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mMeasurement = FirebaseAnalytics.getInstance(getContext());
}
public void initialiseVillageViews() {
Resources resources = getResources();
if (!mImagesInitialised) {
UiModeManager mgr = (UiModeManager) getActivity().
getApplicationContext().getSystemService(Context.UI_MODE_SERVICE);
if (Configuration.UI_MODE_TYPE_WATCH == mgr.getCurrentModeType()) {
int referenceHeight = resources.getInteger(R.integer.wear_referenceHeight);
mImageUfo = new HorizontalScrollingImage(R.drawable.ufo, referenceHeight,
resources.getInteger(R.integer.wear_ufoVerticalOffset), false,
resources.getInteger(R.integer.wear_ufoPercentagePerSecond));
mImagePlane = new HorizontalScrollingImage(R.drawable.plane, referenceHeight,
resources.getInteger(R.integer.wear_planeVerticalOffset), true,
resources.getInteger(R.integer.wear_planePercentagePerSecond));
mImageClouds = new HorizontalScrollingImageGroup(R.drawable.cloud,
resources.getInteger(R.integer.wear_numClouds),
resources.getInteger(R.integer.wear_skyStart),
resources.getInteger(R.integer.wear_cloudsEnd),
resources.getInteger(R.integer.wear_cloudPercentagePerSecond),
resources.getInteger(R.integer.wear_cloudSpeedJitterPercent),
referenceHeight);
mOffsetVertical = -1 * resources.getInteger(R.integer.wear_verticalOffset);
} else {
int referenceHeight = resources.getInteger(R.integer.referenceHeight);
mImageUfo = new HorizontalScrollingImage(R.drawable.ufo, referenceHeight,
resources.getInteger(R.integer.ufoVerticalOffset), false,
resources.getInteger(R.integer.ufoPercentagePerSecond));
mImagePlane = new HorizontalScrollingImage(R.drawable.plane, referenceHeight,
resources.getInteger(R.integer.planeVerticalOffset), true,
resources.getInteger(R.integer.planePercentagePerSecond));
mImageClouds = new HorizontalScrollingImageGroup(R.drawable.cloud,
resources.getInteger(R.integer.numClouds),
resources.getInteger(R.integer.skyStart),
resources.getInteger(R.integer.cloudsEnd),
resources.getInteger(R.integer.cloudPercentagePerSecond),
resources.getInteger(R.integer.cloudSpeedJitterPercent),
referenceHeight);
}
mImagePlane.loadImages(resources);
mImageClouds.loadImages(resources);
mImagesInitialised = true;
}
// Set easter egg state to empty
for (int i = 0; i < EGG_COUNT; i++) {
mEasterEggTracker[i] = false;
}
}
public void onDraw(Canvas canvas, int height, int width) {
if (mPlaneEnabled) {
mImagePlane.onDraw(canvas, height, 3 * width, mOffsetVertical);
}
mImageClouds.onDraw(canvas, height, width, mOffsetVertical);
mImageUfo.onDraw(canvas, height, width, mOffsetVertical);
}
public TouchListener getTouchListener() {
return mTouchListener;
}
public void setPlaneEnabled(boolean planeEnabled) {
mPlaneEnabled = planeEnabled;
}
public class TouchListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onDown(MotionEvent e) {
boolean handled = false;
if (mImagePlane.isTouched(Math.round(e.getX()), Math.round(e.getY()))) {
trackClick(R.string.analytics_event_village_plane);
easterEggProgress(EGG_PLANE);
handled = true;
} else if (mImageUfo.isTouched(Math.round(e.getX()), Math.round(e.getY()))) {
trackClick(R.string.analytics_event_village_ufo);
easterEggInteraction();
handled = true;
}
if (!handled) {
handled = super.onDown(e);
}
return handled;
}
}
private static final int EGG_PLANE = 0;
private static final int EGG_COUNT = 1;
private boolean[] mEasterEggTracker = new boolean[EGG_COUNT];
private void easterEggProgress(int eggIndex) {
int eggsFound = 0;
for (int i = 0; i < EGG_COUNT; i++) {
if (mEasterEggTracker[i]) {
eggsFound++;
}
}
if (!mEasterEggTracker[eggIndex]) {
mEasterEggTracker[eggIndex] = true;
eggsFound++;
// Play sound
switch (eggsFound) {
case 1:
mCallback.playSoundOnce(R.raw.confirm1);
break;
case 2:
mCallback.playSoundOnce(R.raw.confirm2);
break;
case 3:
mCallback.playSoundOnce(R.raw.confirm3);
break;
}
}
if (eggsFound == EGG_COUNT) {
showEasterEgg();
// reset easter egg state
for (int i = 0; i < EGG_COUNT; i++) {
mEasterEggTracker[i] = false;
}
}
}
private void showEasterEgg() {
ObjectAnimator anim = ObjectAnimator.ofFloat(mImageUfo, "size", 0f, 1.0f);
anim.setInterpolator(new DecelerateInterpolator());
anim.setDuration(ImageWithAlphaAndSize.ANIM_DURATION);
anim.start();
mImageUfo.setAlpha(ImageWithAlphaAndSize.OPAQUE);
// App Measurement
MeasurementManager.recordCustomEvent(mMeasurement,
getString(R.string.analytics_event_category_village),
getString(R.string.analytics_event_village_unlock_easteregg), null);
// [ANALYTICS EVENT]: Village Click
AnalyticsManager.sendEvent(R.string.analytics_event_category_village,
R.string.analytics_event_village_unlock_easteregg);
}
// Make the UFO spin around and fly away
private void easterEggInteraction() {
mCallback.playSoundOnce(R.raw.easter_egg);
// Fade into the distance
ObjectAnimator anim = ObjectAnimator.ofFloat(mImageUfo, "size", 1.0f, 0f);
anim.setInterpolator(new AccelerateInterpolator());
anim.setDuration(ImageWithAlphaAndSize.ANIM_DURATION);
anim.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
mImageUfo.setAlpha(ImageWithAlphaAndSize.INVISIBLE);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
anim.start();
}
private void trackClick(int resId) {
// App Measurement
MeasurementManager.recordCustomEvent(mMeasurement,
getString(R.string.analytics_event_category_village),
getString(R.string.analytics_event_village_click),
getString(resId));
// [ANALYTICS EVENT]: Village Click
AnalyticsManager.sendEvent(R.string.analytics_event_category_village,
R.string.analytics_event_village_click,
resId);
}
public interface VillageListener {
void playSoundOnce(int resSoundId);
}
}