Home | History | Annotate | Download | only in toongame
      1 /*
      2  * Copyright (C) 2013 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 
     17 package com.example.android.toongame;
     18 
     19 import android.animation.Animator;
     20 import android.animation.AnimatorListenerAdapter;
     21 import android.animation.AnimatorSet;
     22 import android.animation.ObjectAnimator;
     23 import android.animation.PropertyValuesHolder;
     24 import android.animation.TimeInterpolator;
     25 import android.animation.ValueAnimator;
     26 import android.app.Activity;
     27 import android.content.res.ColorStateList;
     28 import android.graphics.Color;
     29 import android.graphics.Typeface;
     30 import android.graphics.drawable.ShapeDrawable;
     31 import android.graphics.drawable.shapes.OvalShape;
     32 import android.os.Bundle;
     33 import android.util.TypedValue;
     34 import android.view.MotionEvent;
     35 import android.view.View;
     36 import android.view.ViewGroup;
     37 import android.view.ViewTreeObserver;
     38 import android.view.animation.AccelerateInterpolator;
     39 import android.view.animation.DecelerateInterpolator;
     40 import android.view.animation.LinearInterpolator;
     41 import android.view.animation.OvershootInterpolator;
     42 import android.widget.Button;
     43 import android.widget.EditText;
     44 import android.widget.RelativeLayout;
     45 
     46 /**
     47  * This activity, launched from the ToonGame activity, takes the user between three
     48  * different setup screens where they choose a name, choose a difficulty rating, and
     49  * enter important financial information. All of the screens are meant to be
     50  * simple, engaging, and fun.
     51  */
     52 public class PlayerSetupActivity extends Activity {
     53 
     54     private static final AccelerateInterpolator sAccelerator = new AccelerateInterpolator();
     55     private static final LinearInterpolator sLinearInterpolator = new LinearInterpolator();
     56     ViewGroup mContainer;
     57     EditText mEditText;
     58 
     59     private static final int NAME_STATE = 0;
     60     private static final int DIFFICULTY_STATE = 1;
     61     private static final int CREDIT_STATE = 2;
     62     private int mEntryState = NAME_STATE;
     63 
     64     SkewableTextView mNameTV, mDifficultyTV, mCreditTV;
     65 
     66     ViewGroup mNameButtons, mDifficultyButtons, mCreditButtons1, mCreditButtons2;
     67 
     68     Button mBobButton, mJaneButton, mPatButton;
     69 
     70     private static final TimeInterpolator sOvershooter = new OvershootInterpolator();
     71     private static final DecelerateInterpolator sDecelerator = new DecelerateInterpolator();
     72 
     73     @Override
     74     protected void onCreate(Bundle savedInstanceState) {
     75         super.onCreate(savedInstanceState);
     76         setContentView(R.layout.player_setup_layout);
     77         overridePendingTransition(0, 0);
     78 
     79         mContainer = (ViewGroup) findViewById(R.id.container);
     80         mContainer.getViewTreeObserver().addOnPreDrawListener(mPreDrawListener);
     81 
     82         mNameTV = (SkewableTextView) findViewById(R.id.nameTV);
     83         mDifficultyTV = (SkewableTextView) findViewById(R.id.ageTV);
     84         mCreditTV = (SkewableTextView) findViewById(R.id.creditTV);
     85 
     86         mBobButton = setupButton(R.id.bobButton);
     87         setupButton(R.id.janeButton);
     88         setupButton(R.id.patButton);
     89         setupButton(R.id.easyButton);
     90         setupButton(R.id.hardButton);
     91         setupButton(R.id.megaHardButton);
     92 
     93         mNameButtons = (ViewGroup) findViewById(R.id.nameButtons);
     94         mDifficultyButtons = (ViewGroup) findViewById(R.id.difficultyButtons);
     95         mCreditButtons1 = (ViewGroup) findViewById(R.id.creditButtons1);
     96         mCreditButtons2 = (ViewGroup) findViewById(R.id.creditButtons2);
     97     }
     98 
     99     @Override
    100     public void finish() {
    101         super.finish();
    102         overridePendingTransition(0, 0);
    103     }
    104 
    105     private Button setupButton(int resourceId) {
    106         Button button = (Button) findViewById(resourceId);
    107         button.setOnTouchListener(mButtonPressListener);
    108         return button;
    109     }
    110 
    111     private View.OnTouchListener mButtonPressListener =
    112             new View.OnTouchListener() {
    113                 public boolean onTouch(View v, MotionEvent event) {
    114                     switch (event.getAction()) {
    115                     case MotionEvent.ACTION_DOWN:
    116                         v.animate().setDuration(ToonGame.SHORT_DURATION).
    117                                 scaleX(.8f).scaleY(.8f).setInterpolator(sDecelerator);
    118                         break;
    119                     case MotionEvent.ACTION_UP:
    120                         v.animate().setDuration(ToonGame.SHORT_DURATION).
    121                                 scaleX(1).scaleY(1).setInterpolator(sAccelerator);
    122                         break;
    123                     default:
    124                         break;
    125                     }
    126                     return false;
    127                 }
    128             };
    129 
    130     public void buttonClick(View clickedView, int alignmentRule) {
    131         ViewGroup parent = (ViewGroup) clickedView.getParent();
    132         for (int i = 0; i < parent.getChildCount(); ++i) {
    133             Button child = (Button) parent.getChildAt(i);
    134             if (child != clickedView) {
    135                 child.animate().alpha(0);
    136             } else {
    137                 final Button buttonCopy = new Button(this);
    138                 child.setVisibility(View.INVISIBLE);
    139                 buttonCopy.setBackground(child.getBackground());
    140                 buttonCopy.setText(((Button) child).getText());
    141                 RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
    142                         RelativeLayout.LayoutParams.WRAP_CONTENT,
    143                         RelativeLayout.LayoutParams.WRAP_CONTENT);
    144                 params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
    145                 params.addRule(alignmentRule);
    146                 params.setMargins(25, 50, 25, 50);
    147                 buttonCopy.setLayoutParams(params);
    148                 buttonCopy.setPadding(child.getPaddingLeft(), child.getPaddingTop(),
    149                         child.getPaddingRight(), child.getPaddingBottom());
    150                 buttonCopy.setTextSize(TypedValue.COMPLEX_UNIT_PX, child.getTextSize());
    151                 buttonCopy.setTypeface(child.getTypeface(), Typeface.BOLD);
    152                 ColorStateList colors = child.getTextColors();
    153                 buttonCopy.setTextColor(colors.getDefaultColor());
    154                 final int[] oldLocationInWindow = new int[2];
    155                 child.getLocationInWindow(oldLocationInWindow);
    156                 mContainer.addView(buttonCopy);
    157                 buttonCopy.getViewTreeObserver().addOnPreDrawListener(
    158                         new ViewTreeObserver.OnPreDrawListener() {
    159 
    160                     @Override
    161                     public boolean onPreDraw() {
    162                         buttonCopy.getViewTreeObserver().removeOnPreDrawListener(this);
    163                         int[] locationInWindow = new int[2];
    164                         buttonCopy.getLocationInWindow(locationInWindow);
    165                         float deltaX = oldLocationInWindow[0] - locationInWindow[0];
    166                         float deltaY = oldLocationInWindow[1] - locationInWindow[1];
    167 
    168                         buttonCopy.setTranslationX(deltaX);
    169                         buttonCopy.setTranslationY(deltaY);
    170 
    171                         PropertyValuesHolder pvhSX =
    172                                 PropertyValuesHolder.ofFloat(View.SCALE_X, 3);
    173                         PropertyValuesHolder pvhSY =
    174                                 PropertyValuesHolder.ofFloat(View.SCALE_Y, 3);
    175                         ObjectAnimator bounceAnim = ObjectAnimator.ofPropertyValuesHolder(
    176                                 buttonCopy, pvhSX, pvhSY);
    177                         bounceAnim.setRepeatCount(1);
    178                         bounceAnim.setRepeatMode(ValueAnimator.REVERSE);
    179                         bounceAnim.setInterpolator(sDecelerator);
    180                         bounceAnim.setDuration(300);
    181 
    182                         PropertyValuesHolder pvhTX =
    183                                 PropertyValuesHolder.ofFloat(View.TRANSLATION_X, 0);
    184                         PropertyValuesHolder pvhTY =
    185                                 PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, 0);
    186                         ObjectAnimator moveAnim = ObjectAnimator.ofPropertyValuesHolder(
    187                                 buttonCopy, pvhTX, pvhTY);
    188                         moveAnim.setDuration(600);
    189                         bounceAnim.start();
    190                         moveAnim.start();
    191                         moveAnim.addListener(new AnimatorListenerAdapter() {
    192                             public void onAnimationEnd(Animator animation) {
    193                                 switch (mEntryState) {
    194                                 case (NAME_STATE) :
    195                                 {
    196                                     Runnable runnable = new Runnable() {
    197                                         public void run() {
    198                                             mDifficultyButtons.setVisibility(View.VISIBLE);
    199                                             mNameButtons.setVisibility(View.GONE);
    200                                             popChildrenIn(mDifficultyButtons, null);
    201                                         }
    202                                     };
    203                                     slideToNext(mNameTV, mDifficultyTV, runnable);
    204                                     mEntryState = DIFFICULTY_STATE;
    205                                     break;
    206                                 }
    207                                 case (DIFFICULTY_STATE) :
    208                                 {
    209                                     mDifficultyButtons.setVisibility(View.GONE);
    210                                     for (int i = 0; i < 5; ++i) {
    211                                         mCreditButtons1.addView(setupNumberButton(i));
    212                                     }
    213                                     for (int i = 5; i < 10; ++i) {
    214                                         mCreditButtons2.addView(setupNumberButton(i));
    215                                     }
    216                                     Runnable runnable = new Runnable() {
    217                                         public void run() {
    218                                             mCreditButtons1.setVisibility(View.VISIBLE);
    219                                             Runnable runnable = new Runnable() {
    220                                                 public void run() {
    221                                                     mCreditButtons2.setVisibility(View.VISIBLE);
    222                                                     popChildrenIn(mCreditButtons2, null);
    223                                                 }
    224                                             };
    225                                             popChildrenIn(mCreditButtons1, runnable);
    226                                         }
    227                                     };
    228                                     slideToNext(mDifficultyTV, mCreditTV, runnable);
    229                                     mEntryState = CREDIT_STATE;
    230                                 }
    231                                     break;
    232                                 }
    233                             }
    234                         });
    235                         return true;
    236                     }
    237                 });
    238             }
    239         }
    240     }
    241 
    242     public void selectDifficulty(View clickedView) {
    243         buttonClick(clickedView, RelativeLayout.ALIGN_PARENT_RIGHT);
    244     }
    245 
    246     public void selectName(View clickedView) {
    247         buttonClick(clickedView, RelativeLayout.ALIGN_PARENT_LEFT);
    248     }
    249 
    250     private Button setupNumberButton(int number) {
    251         Button button = new Button(PlayerSetupActivity.this);
    252         button.setTextSize(15);
    253         button.setTextColor(Color.WHITE);
    254         button.setTypeface(mBobButton.getTypeface(), Typeface.BOLD);
    255         button.setText(Integer.toString(number));
    256         button.setPadding(0, 0, 0, 0);
    257 
    258         OvalShape oval = new OvalShape();
    259         ShapeDrawable drawable = new ShapeDrawable(oval);
    260         drawable.getPaint().setColor(0xFF << 24 | (int) (50 + 150 * Math.random()) << 16 |
    261                 (int) (50 + 150 * Math.random()) << 8 |  (int) (50 + 150 * Math.random()));
    262         button.setBackground(drawable);
    263 
    264         button.setOnTouchListener(mButtonPressListener);
    265 
    266         return button;
    267     }
    268 
    269     ViewTreeObserver.OnPreDrawListener mPreDrawListener =
    270             new ViewTreeObserver.OnPreDrawListener() {
    271 
    272         @Override
    273         public boolean onPreDraw() {
    274             mContainer.getViewTreeObserver().removeOnPreDrawListener(this);
    275             mContainer.setScaleX(0);
    276             mContainer.setScaleY(0);
    277             mContainer.animate().scaleX(1).scaleY(1).setInterpolator(new OvershootInterpolator());
    278             mContainer.animate().setDuration(ToonGame.LONG_DURATION).withEndAction(new Runnable() {
    279 
    280                 @Override
    281                 public void run() {
    282                     ViewGroup buttonsParent = (ViewGroup) findViewById(R.id.nameButtons);
    283                     buttonsParent.setVisibility(View.VISIBLE);
    284                     popChildrenIn(buttonsParent, null);
    285                 }
    286             });
    287             return false;
    288         }
    289     };
    290 
    291     private void popChildrenIn(ViewGroup parent, final Runnable endAction) {
    292         // for all children, scale in one at a time
    293         TimeInterpolator overshooter = new OvershootInterpolator();
    294         int childCount = parent.getChildCount();
    295         ObjectAnimator[] childAnims = new ObjectAnimator[childCount];
    296         for (int i = 0; i < childCount; ++i) {
    297             View child = parent.getChildAt(i);
    298             child.setScaleX(0);
    299             child.setScaleY(0);
    300             PropertyValuesHolder pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, 1);
    301             PropertyValuesHolder pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1);
    302             ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(child, pvhSX, pvhSY);
    303             anim.setDuration(150);
    304             anim.setInterpolator(overshooter);
    305             childAnims[i] = anim;
    306         }
    307         AnimatorSet set = new AnimatorSet();
    308         set.playSequentially(childAnims);
    309         set.start();
    310         if (endAction != null) {
    311             set.addListener(new AnimatorListenerAdapter() {
    312                 public void onAnimationEnd(Animator animation) {
    313                     endAction.run();
    314                 }
    315             });
    316         }
    317     }
    318 
    319     private void slideToNext(final SkewableTextView currentView,
    320             final SkewableTextView nextView, final Runnable endAction) {
    321         // skew/anticipate current view, slide off, set GONE, restore translation
    322         ObjectAnimator currentSkewer = ObjectAnimator.ofFloat(currentView, "skewX", -.5f);
    323         currentSkewer.setInterpolator(sDecelerator);
    324         ObjectAnimator currentMover = ObjectAnimator.ofFloat(currentView, View.TRANSLATION_X,
    325                 -mContainer.getWidth());
    326         currentMover.setInterpolator(sLinearInterpolator);
    327         currentMover.setDuration(ToonGame.MEDIUM_DURATION);
    328 
    329         // set next view visible, translate off to right, skew,
    330         // slide on in parallel, overshoot/wobble, unskew
    331         nextView.setVisibility(View.VISIBLE);
    332         nextView.setSkewX(-.5f);
    333         nextView.setTranslationX(mContainer.getWidth());
    334 
    335         ObjectAnimator nextMover = ObjectAnimator.ofFloat(nextView, View.TRANSLATION_X, 0);
    336         nextMover.setInterpolator(sAccelerator);
    337         nextMover.setDuration(ToonGame.MEDIUM_DURATION);
    338         ObjectAnimator nextSkewer = ObjectAnimator.ofFloat(nextView, "skewX", 0);
    339         nextSkewer.setInterpolator(sOvershooter);
    340 
    341         AnimatorSet moverSet = new AnimatorSet();
    342         moverSet.playTogether(currentMover, nextMover);
    343         AnimatorSet fullSet = new AnimatorSet();
    344         fullSet.playSequentially(currentSkewer, moverSet, nextSkewer);
    345         fullSet.addListener(new AnimatorListenerAdapter() {
    346             @Override
    347             public void onAnimationEnd(Animator animation) {
    348                 currentView.setSkewX(0);
    349                 currentView.setVisibility(View.GONE);
    350                 currentView.setTranslationX(0);
    351                 if (endAction != null) {
    352                     endAction.run();
    353                 }
    354             }
    355         });
    356 
    357         fullSet.start();
    358     }
    359 
    360 }
    361