19bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerpackage com.android.dreamtheater;
29bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
39bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.animation.PropertyValuesHolder;
49bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.animation.TimeAnimator;
59bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.app.Activity;
69bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.content.Context;
79bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.content.Intent;
89bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.graphics.Canvas;
99bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.graphics.Matrix;
109bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.graphics.Paint;
119bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.graphics.RectF;
129bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.os.Bundle;
139bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.util.AttributeSet;
149bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.util.Log;
159bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.view.MotionEvent;
169bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.view.View;
179bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.view.Gravity;
189bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.view.ViewGroup;
199bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.widget.Button;
209bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.widget.FrameLayout;
219bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport android.widget.ImageView;
229bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
239bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport java.util.LinkedList;
249bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerimport java.util.HashMap;
259bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
269bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandlerpublic class BouncyDroid extends Activity {
279bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler    static final boolean DEBUG = true;
289bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler    static final boolean CENTER_DROID = true;
299bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
309bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler    public static class BouncyView extends FrameLayout
319bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler    {
329bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        boolean mShowDebug = false;
339bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
342a92200023d2554a9bf3b18e8b8e03e6ca6e6179Daniel Sandler        static final int RADIUS = 100;
359bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
369bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        static final boolean HAS_INITIAL_IMPULSE = true;
379bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        static final boolean HAS_GRAVITY = true;
389bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        static final boolean HAS_FRICTION = false;
399bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        static final boolean HAS_EDGES = true;
409bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
419bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        static final boolean STICKY_FINGERS = true;
429bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
439bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        static final float MAX_SPEED = 5000f;
449bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
452a92200023d2554a9bf3b18e8b8e03e6ca6e6179Daniel Sandler        static final float RANDOM_IMPULSE_PROB = 0.001f;
462a92200023d2554a9bf3b18e8b8e03e6ca6e6179Daniel Sandler
479bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        public static class World {
489bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            public static final float PX_PER_METER = 100f;
492a92200023d2554a9bf3b18e8b8e03e6ca6e6179Daniel Sandler            public static final float GRAVITY = 500f;
509bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            public static class Vec {
519bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                float x;
529bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                float y;
539bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public Vec() {
549bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    x = y = 0;
559bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
569bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public Vec(float _x, float _y) {
579bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    x = _x;
589bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    y = _y;
599bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
609bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public Vec add(Vec v) {
619bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    return new Vec(x + v.x, y + v.y);
629bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
639bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public Vec mul(float a) {
649bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    return new Vec(x * a, y * a);
659bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
669bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public Vec sub(Vec v) {
679bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    return new Vec(x - v.x, y - v.y);
689bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
699bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public float mag() {
709bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    return (float) Math.hypot(x, y);
719bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
729bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public Vec norm() {
739bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    float k = 1/mag();
749bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    return new Vec(x*k, y*k);
759bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
769bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public String toString() {
779bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    return "(" + x + "," + y + ")";
789bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
799bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            }
809bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            public static class Body {
819bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                float m, r;
829bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                Vec p = new Vec();
839bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                Vec v = new Vec();
849bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                LinkedList<Vec> forces = new LinkedList<Vec>();
859bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                LinkedList<Vec> impulses = new LinkedList<Vec>();
869bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public Body(float _m, Vec _p) {
879bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    m = _m;
889bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    p = _p;
899bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
909bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public void applyForce(Vec f) {
919bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    forces.add(f);
929bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
939bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public void applyImpulse(Vec f) {
949bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    impulses.add(f);
959bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
969bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public void clearForces() {
979bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    forces.clear();
989bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
999bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public void removeForce(Vec f) {
1009bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    forces.remove(f);
1019bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
1029bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public void step(float dt) {
1039bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    p = p.add(v.mul(dt));
1049bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    for (Vec f : impulses) {
1059bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        v = v.add(f.mul(dt/m));
1069bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    }
1079bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    impulses.clear();
1089bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    for (Vec f : forces) {
1099bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        v = v.add(f.mul(dt/m));
1109bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    }
1119bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
1129bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public String toString() {
1139bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    return "Body(m=" + m + " p=" + p + " v=" + v + ")";
1149bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
1159bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            }
1169bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            LinkedList<Body> mBodies = new LinkedList<Body>();
1179bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            public void addBody(Body b) {
1189bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                mBodies.add(b);
1199bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            }
1209bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
1219bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            public void step(float dt) {
1229bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                for (Body b : mBodies) {
1239bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    b.step(dt);
1249bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
1259bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            }
1269bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        }
1279bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
1289bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
1299bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        TimeAnimator mAnim;
1309bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        World mWorld;
1319bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        ImageView mBug;
1329bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        View mShowDebugView;
1339bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        HashMap<Integer, World.Vec> mFingers = new HashMap<Integer, World.Vec>();
1349bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        World.Body mBody;
1359bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        World.Vec mGrabSpot;
1369bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        int mGrabbedPointer = -1;
1379bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
1389bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        public BouncyView(Context context, AttributeSet as) {
1399bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            super(context, as);
1409bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
1419bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            /*
1429bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
1439bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                @Override
1449bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public void onSystemUiVisibilityChange(int visibility) {
1459bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    if (visibility == View.STATUS_BAR_VISIBLE) {
1469bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        ((Activity)getContext()).finish();
1479bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    }
1489bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
1499bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            });
1509bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            */
1519bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
1522a92200023d2554a9bf3b18e8b8e03e6ca6e6179Daniel Sandler            setBackgroundColor(0xFF444444);
1532a92200023d2554a9bf3b18e8b8e03e6ca6e6179Daniel Sandler
1549bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            mBug = new ImageView(context);
1559bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            mBug.setScaleType(ImageView.ScaleType.MATRIX);
1569bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            addView(mBug, new ViewGroup.LayoutParams(
1579bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        ViewGroup.LayoutParams.WRAP_CONTENT,
1589bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        ViewGroup.LayoutParams.WRAP_CONTENT));
1599bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
1609bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            if (DEBUG) {
1619bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                Button b = new Button(getContext());
1629bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                b.setText("Debugzors");
1639bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                b.setBackgroundColor(0); // very hard to see! :)
1649bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                b.setOnClickListener(new View.OnClickListener() {
1659bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    @Override
1669bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    public void onClick(View v) {
1679bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        setDebug(!mShowDebug);
1689bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    }
1699bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                });
1709bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                addView(b, new FrameLayout.LayoutParams(
1719bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            ViewGroup.LayoutParams.WRAP_CONTENT,
1729bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            ViewGroup.LayoutParams.WRAP_CONTENT,
1739bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            Gravity.TOP|Gravity.RIGHT));
1749bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            }
1759bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        }
1769bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
1779bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        public void setDebug(boolean d) {
1789bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            if (d != mShowDebug) {
1799bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                if (d) {
1809bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    mShowDebugView = new DebugView(getContext());
1819bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    mShowDebugView.setLayoutParams(
1829bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        new ViewGroup.LayoutParams(
1839bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            ViewGroup.LayoutParams.MATCH_PARENT,
1849bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            ViewGroup.LayoutParams.MATCH_PARENT
1859bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        ));
1869bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    addView(mShowDebugView);
1879bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
1889bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    mBug.setBackgroundColor(0x2000FF00);
1899bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                } else {
1909bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    if (mShowDebugView != null) {
1919bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        removeView(mShowDebugView);
1929bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        mShowDebugView = null;
1939bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    }
1949bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    mBug.setBackgroundColor(0);
1959bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
1969bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                invalidate();
1979bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                mShowDebug = d;
1989bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            }
1999bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        }
2009bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
2019bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        private void reset() {
2029bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            mWorld = new World();
2039bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            final float mass = 100;
2049bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            mBody = new World.Body(mass, new World.Vec(200,200));
2059bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            mBody.r = RADIUS;
2069bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            mWorld.addBody(mBody);
2079bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            mGrabbedPointer = -1;
2089bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
2099bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            mAnim = new TimeAnimator();
2109bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            mAnim.setTimeListener(new TimeAnimator.TimeListener() {
2119bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
2129bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    if (deltaTime > 0) {
2139bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        int STEPS = 5;
2149bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        final float dt = deltaTime / (float) STEPS;
2159bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        while (STEPS-->0) {
2169bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            mBody.clearForces();
2179bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
2189bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            if (HAS_INITIAL_IMPULSE) {
2199bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                // initial oomph
2209bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                if (totalTime == 0) {
2219bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    mBody.applyImpulse(new World.Vec(400000, -200000));
2229bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                }
2239bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            }
2249bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
2259bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            if (HAS_GRAVITY) {
2269bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                // gravity points down
2279bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                mBody.applyForce(new World.Vec(0, mass * World.GRAVITY));
2289bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            }
2299bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
2309bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            if (mGrabbedPointer >= 0) {
2319bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                World.Vec finger = mFingers.get(mGrabbedPointer);
2329bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                if (finger == null) {
2339bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    // let go!
2349bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    mGrabbedPointer = -1;
2359bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                } else {
2369bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    // never gonna let you go
2379bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    World.Vec newPos = finger.add(mGrabSpot);
2389bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    mBody.v = mBody.v.add(newPos.sub(mBody.p).mul(dt));
2399bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    mBody.p = newPos;
2409bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                }
2419bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            } else {
2429bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                // springs
2439bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                // ideal Hooke's Law plus a maximum force and a minimum length cutoff
2449bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                for (Integer i : mFingers.keySet()) {
2459bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    World.Vec finger = mFingers.get(i);
2469bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    World.Vec springForce = finger.sub(mBody.p);
2479bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    float mag = springForce.mag();
2489bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
2499bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    if (STICKY_FINGERS && mag < mBody.r*0.75) {
2509bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                        // close enough; we'll call this a "stick"
2519bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                        mGrabbedPointer = i;
2529bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                        mGrabSpot = mBody.p.sub(finger);
2539bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                        mBody.v = new World.Vec(0,0);
2549bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                        break;
2559bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    }
2569bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
2572a92200023d2554a9bf3b18e8b8e03e6ca6e6179Daniel Sandler                                    final float SPRING_K = 30000;
2589bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    final float FORCE_MAX = 10*SPRING_K;
2599bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    mag = (float) Math.min(mag * SPRING_K, FORCE_MAX); // Hooke's law
2609bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            //                    float mag = (float) (FORCE_MAX / Math.pow(springForce.mag(), 2)); // Gravitation
2619bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    springForce = springForce.norm().mul(mag);
2629bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    mBody.applyForce(springForce);
2639bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                }
2649bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            }
2659bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
2669bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            if (HAS_FRICTION) {
2679bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                // sliding friction opposes movement
2682a92200023d2554a9bf3b18e8b8e03e6ca6e6179Daniel Sandler                                mBody.applyForce(mBody.v.mul(-0.01f * mBody.m));
2699bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            }
2709bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
2719bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            if (HAS_EDGES) {
2729bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                if (mBody.p.x - mBody.r < 0) {
2739bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    mBody.v.x = (float) Math.abs(mBody.v.x) *
2742a92200023d2554a9bf3b18e8b8e03e6ca6e6179Daniel Sandler                                        (HAS_FRICTION ? 0.95f : 1f);
2759bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                } else if (mBody.p.x + mBody.r > getWidth()) {
2769bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    mBody.v.x = (float) Math.abs(mBody.v.x) *
2772a92200023d2554a9bf3b18e8b8e03e6ca6e6179Daniel Sandler                                        (HAS_FRICTION ? -0.95f : -1f);
2789bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                }
2799bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                if (mBody.p.y - mBody.r < 0) {
2809bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    mBody.v.y = (float) Math.abs(mBody.v.y) *
2812a92200023d2554a9bf3b18e8b8e03e6ca6e6179Daniel Sandler                                        (HAS_FRICTION ? 0.95f : 1f);
2829bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                } else if (mBody.p.y + mBody.r > getHeight()) {
2839bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    mBody.v.y = (float) Math.abs(mBody.v.y) *
2842a92200023d2554a9bf3b18e8b8e03e6ca6e6179Daniel Sandler                                        (HAS_FRICTION ? -0.95f : -1f);
2859bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                }
2869bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            }
2879bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
2889bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            if (MAX_SPEED > 0) {
2899bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                if (mBody.v.mag() > MAX_SPEED) {
2909bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                    mBody.v = mBody.v.norm().mul(MAX_SPEED);
2919bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                }
2929bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            }
2939bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
2949bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            // ok, Euler, do your thing
2959bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            mWorld.step(dt / 1000f); // dt is in sec
2969bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        }
2979bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    }
2989bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    mBug.setTranslationX(mBody.p.x - mBody.r);
2999bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    mBug.setTranslationY(mBody.p.y - mBody.r);
3009bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
3019bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    Matrix m = new Matrix();
3029bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    m.setScale(
3039bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        (mBody.v.x < 0)    ? -1 : 1,
3049bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        (mBody.v.y > 1500) ? -1 : 1, // AAAAAAAAAAAAAAAA
3059bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        RADIUS, RADIUS);
3069bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    mBug.setImageMatrix(m);
3079bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    if (CENTER_DROID) {
3089bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        mBug.setImageResource(
3099bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                            (Math.abs(mBody.v.x) < 25)
3109bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                ? R.drawable.bouncy_center
3119bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                : R.drawable.bouncy);
3129bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    }
3139bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
3149bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    if (mShowDebug) mShowDebugView.invalidate();
3159bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
3169bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            });
3179bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        }
3189bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
3199bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        @Override
3209bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        protected void onAttachedToWindow() {
3219bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            super.onAttachedToWindow();
3229bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            setSystemUiVisibility(View.STATUS_BAR_HIDDEN);
3239bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
3249bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            reset();
3259bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            mAnim.start();
3269bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        }
3279bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
3289bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        @Override
3299bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        protected void onDetachedFromWindow() {
3309bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            super.onDetachedFromWindow();
3319bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            mAnim.cancel();
3329bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        }
3339bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
3349bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        @Override
3359bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        public boolean onTouchEvent(MotionEvent event) {
3369bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            int i;
3379bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            for (i=0; i<event.getPointerCount(); i++) {
3389bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                switch (event.getActionMasked()) {
3399bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    case MotionEvent.ACTION_DOWN:
3409bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    case MotionEvent.ACTION_MOVE:
3419bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    case MotionEvent.ACTION_POINTER_DOWN:
3429bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        mFingers.put(event.getPointerId(i),
3439bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                                new World.Vec(event.getX(i), event.getY(i)));
3449bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        break;
3459bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
3469bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    case MotionEvent.ACTION_UP:
3479bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    case MotionEvent.ACTION_POINTER_UP:
3489bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        mFingers.remove(event.getPointerId(i));
3499bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        break;
3509bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
3519bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    case MotionEvent.ACTION_CANCEL:
3529bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        mFingers.clear();
3539bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        break;
3549bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
3559bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            }
3569bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            // expired pointers
3579bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler    //        for (; i<mFingers.length; i++) {
3589bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler    //            mFingers[i] = null;
3599bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler    //        }
3609bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            return true;
3619bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        }
3629bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
3639bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        @Override
3649bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        public boolean isOpaque() {
3659bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            return true;
3669bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        }
3679bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
3689bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        class DebugView extends View {
3699bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            public DebugView(Context ct) {
3709bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                super(ct);
3719bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            }
3729bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
3739bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            private void drawVector(Canvas canvas,
3749bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    float x, float y, float vx, float vy,
3759bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    Paint pt) {
3769bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                final float mag = (float) Math.hypot(vx, vy);
3779bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
3789bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                canvas.save();
3799bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                Matrix mx = new Matrix();
3809bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                mx.setSinCos(-vx/mag, vy/mag);
3819bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                mx.postTranslate(x, y);
3829bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                canvas.setMatrix(mx);
3839bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
3849bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                canvas.drawLine(0,0, 0, mag, pt);
3859bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                canvas.drawLine(0, mag, -4, mag-4, pt);
3869bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                canvas.drawLine(0, mag, 4, mag-4, pt);
3879bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
3889bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                canvas.restore();
3899bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            }
3909bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
3919bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            @Override
3929bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            protected void onDraw(Canvas canvas) {
3939bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                super.onDraw(canvas);
3949bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
3959bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                Paint pt = new Paint(Paint.ANTI_ALIAS_FLAG);
3969bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                pt.setColor(0xFFCC0000);
3979bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                pt.setTextSize(30f);
3989bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                pt.setStrokeWidth(1.0f);
3999bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
4009bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                for (Integer id : mFingers.keySet()) {
4019bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    World.Vec v = mFingers.get(id);
4029bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    float x = v.x;
4039bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    float y = v.y;
4049bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    pt.setStyle(Paint.Style.FILL);
4059bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    canvas.drawText("#"+id, x+38, y-38, pt);
4069bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    pt.setStyle(Paint.Style.STROKE);
4079bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    canvas.drawLine(x-40, y, x+40, y, pt);
4089bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    canvas.drawLine(x, y-40, x, y+40, pt);
4099bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    canvas.drawCircle(x, y, 40, pt);
4109bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
4119bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                pt.setStyle(Paint.Style.STROKE);
4129bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                if (mBody != null) {
4139bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    float x = mBody.p.x;
4149bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    float y = mBody.p.y;
4159bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    float r = mBody.r;
4169bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    pt.setColor(0xFF6699FF);
4179bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    RectF bounds = new RectF(x-r, y-r, x+r, y+r);
4189bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    canvas.drawOval(bounds, pt);
4199bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
4209bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    pt.setStrokeWidth(3);
4212a92200023d2554a9bf3b18e8b8e03e6ca6e6179Daniel Sandler                    drawVector(canvas, x, y, mBody.v.x/100, mBody.v.y/100, pt);
4229bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
4239bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    pt.setColor(0xFF0033FF);
4249bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    for (World.Vec f : mBody.forces) {
4259bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                        drawVector(canvas, x, y, f.x/1000, f.y/1000, pt);
4269bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                    }
4279bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler                }
4289bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler            }
4299bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        }
4309bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler    }
4319bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler
4329bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler    @Override
4339bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler    public void onStart() {
4349bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        super.onStart();
4359bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler        setContentView(new BouncyView(this, null));
4369bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler    }
4379bb57352244a7e2db1e1041ebf91ebef692152c0Daniel Sandler}
438