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.ValueAnimator;
     25 import android.app.Activity;
     26 import android.content.Intent;
     27 import android.graphics.Color;
     28 import android.os.Bundle;
     29 import android.view.MotionEvent;
     30 import android.view.View;
     31 import android.view.View.OnTouchListener;
     32 import android.view.ViewGroup;
     33 import android.view.ViewTreeObserver;
     34 import android.view.animation.AccelerateInterpolator;
     35 import android.view.animation.DecelerateInterpolator;
     36 import android.view.animation.LinearInterpolator;
     37 import android.widget.Button;
     38 
     39 /**
     40  * This application shows various cartoon animation techniques in the context of
     41  * a larger application, to show how such animations might be used to create a more
     42  * interactive, fun, and engaging experience.
     43  *
     44  * This main activity launches a sub-activity when the Play button is clicked. The
     45  * main action in this master activity is bouncing the Play button in, randomly
     46  * bouncing it while waiting for input, and animating its press and click behaviors
     47  * when the user interacts with it.
     48  *
     49  * Watch the associated video for this demo on the DevBytes channel of developer.android.com
     50  * or on the DevBytes playlist in the androiddevelopers channel on YouTube at
     51  * https://www.youtube.com/playlist?list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0.
     52  */
     53 public class ToonGame extends Activity {
     54 
     55     Button mStarter;
     56     ViewGroup mContainer;
     57     private static final AccelerateInterpolator sAccelerator = new AccelerateInterpolator();
     58     private static final DecelerateInterpolator sDecelerator = new DecelerateInterpolator();
     59     private static final LinearInterpolator sLinearInterpolator = new LinearInterpolator();
     60     static long SHORT_DURATION = 100;
     61     static long MEDIUM_DURATION = 200;
     62     static long REGULAR_DURATION = 300;
     63     static long LONG_DURATION = 500;
     64 
     65     private static float sDurationScale = 1f;
     66 
     67     @Override
     68     protected void onCreate(Bundle savedInstanceState) {
     69         super.onCreate(savedInstanceState);
     70         overridePendingTransition(0, 0);
     71         setContentView(R.layout.activity_toon_game);
     72 
     73         mStarter = (Button) findViewById(R.id.startButton);
     74         mContainer = (ViewGroup) findViewById(R.id.container);
     75         mStarter.setOnTouchListener(funButtonListener);
     76         mStarter.animate().setDuration(100);
     77 
     78     }
     79 
     80     @Override
     81     protected void onResume() {
     82         super.onResume();
     83         mContainer.setScaleX(1);
     84         mContainer.setScaleY(1);
     85         mContainer.setAlpha(1);
     86         mStarter.setVisibility(View.INVISIBLE);
     87         mContainer.getViewTreeObserver().addOnPreDrawListener(mOnPreDrawListener);
     88     }
     89 
     90     @Override
     91     protected void onPause() {
     92         super.onPause();
     93         mStarter.removeCallbacks(mSquishRunnable);
     94     }
     95 
     96     private OnTouchListener funButtonListener = new OnTouchListener() {
     97 
     98         @Override
     99         public boolean onTouch(View v, MotionEvent event) {
    100             switch (event.getAction()) {
    101             case MotionEvent.ACTION_DOWN:
    102                 mStarter.animate().scaleX(.8f).scaleY(.8f).setInterpolator(sDecelerator);
    103                 mStarter.setTextColor(Color.CYAN);
    104                 mStarter.removeCallbacks(mSquishRunnable);
    105                 mStarter.setPressed(true);
    106                 break;
    107             case MotionEvent.ACTION_MOVE:
    108                 float x = event.getX();
    109                 float y = event.getY();
    110                 boolean isInside = (x > 0 && x < mStarter.getWidth() &&
    111                         y > 0 && y < mStarter.getHeight());
    112                 if (mStarter.isPressed() != isInside) {
    113                     mStarter.setPressed(isInside);
    114                 }
    115                 break;
    116             case MotionEvent.ACTION_UP:
    117                 if (mStarter.isPressed()) {
    118                     mStarter.performClick();
    119                     mStarter.setPressed(false);
    120                 } else {
    121                     mStarter.animate().scaleX(1).scaleY(1).setInterpolator(sAccelerator);
    122                 }
    123                 mStarter.setTextColor(Color.BLUE);
    124                 break;
    125             }
    126             return true;
    127         }
    128     };
    129 
    130     private Runnable mSquishRunnable = new Runnable() {
    131         public void run() {
    132             squishyBounce(mStarter, 0,
    133                     mContainer.getHeight() - mStarter.getTop() - mStarter.getHeight(),
    134                     0, .5f, 1.5f);
    135         }
    136     };
    137 
    138     public void play(View view) {
    139         mContainer.animate().scaleX(5).scaleY(5).alpha(0).setDuration(LONG_DURATION).
    140                 setInterpolator(sLinearInterpolator).
    141                 withEndAction(new Runnable() {
    142             @Override
    143             public void run() {
    144                 mStarter.postOnAnimation(new Runnable() {
    145                     public void run() {
    146                         Intent intent = new Intent(ToonGame.this,
    147                                 PlayerSetupActivity.class);
    148                         startActivity(intent);
    149                         overridePendingTransition(0, 0);
    150                     }
    151                 });
    152             }
    153         });
    154         view.removeCallbacks(mSquishRunnable);
    155     }
    156 
    157     private ViewTreeObserver.OnPreDrawListener mOnPreDrawListener =
    158             new ViewTreeObserver.OnPreDrawListener() {
    159 
    160                 @Override
    161                 public boolean onPreDraw() {
    162                     mContainer.getViewTreeObserver().removeOnPreDrawListener(this);
    163                     mContainer.postDelayed(new Runnable() {
    164                         public void run() {
    165                             // Drop in the button from off the top of the screen
    166                             mStarter.setVisibility(View.VISIBLE);
    167                             mStarter.setY(-mStarter.getHeight());
    168                             squishyBounce(mStarter,
    169                                     -(mStarter.getTop() + mStarter.getHeight()),
    170                                     mContainer.getHeight() - mStarter.getTop() -
    171                                             mStarter.getHeight(),
    172                                     0, .5f, 1.5f);
    173                         }
    174                     }, 500);
    175                     return true;
    176                 }
    177             };
    178 
    179     private void squishyBounce(final View view, final float startTY, final float bottomTY,
    180             final float endTY, final float squash, final float stretch) {
    181         view.setPivotX(view.getWidth() / 2);
    182         view.setPivotY(view.getHeight());
    183         PropertyValuesHolder pvhTY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y,
    184                 startTY, bottomTY);
    185         PropertyValuesHolder pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, .7f);
    186         PropertyValuesHolder pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1.2f);
    187         ObjectAnimator downAnim = ObjectAnimator.ofPropertyValuesHolder(view, pvhTY, pvhSX, pvhSY);
    188         downAnim.setInterpolator(sAccelerator);
    189 
    190         pvhTY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, bottomTY, endTY);
    191         pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, 1);
    192         pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1);
    193         ObjectAnimator upAnim = ObjectAnimator.ofPropertyValuesHolder(view, pvhTY, pvhSX, pvhSY);
    194         upAnim.setInterpolator(sDecelerator);
    195 
    196         pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, stretch);
    197         pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, squash);
    198         ObjectAnimator stretchAnim = ObjectAnimator.ofPropertyValuesHolder(view, pvhSX, pvhSY);
    199         stretchAnim.setRepeatCount(1);
    200         stretchAnim.setRepeatMode(ValueAnimator.REVERSE);
    201         stretchAnim.setInterpolator(sDecelerator);
    202 
    203         AnimatorSet set = new AnimatorSet();
    204         set.playSequentially(downAnim, stretchAnim, upAnim);
    205         set.setDuration(getDuration(SHORT_DURATION));
    206         set.start();
    207         set.addListener(new AnimatorListenerAdapter() {
    208             public void onAnimationEnd(Animator animation) {
    209                 view.postDelayed(mSquishRunnable, (long) (500 + Math.random() * 2000));
    210             }
    211         });
    212     }
    213 
    214     public static long getDuration(long baseDuration) {
    215         return (long) (baseDuration * sDurationScale);
    216     }
    217 
    218 
    219 }
    220