126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerpackage com.android.dreamtheater;
226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.animation.PropertyValuesHolder;
426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.animation.TimeAnimator;
526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.app.Activity;
626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.content.Context;
726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.content.Intent;
826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.graphics.Canvas;
926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.graphics.Matrix;
1026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.graphics.Paint;
1126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.graphics.RectF;
1226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.os.Bundle;
1326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.util.AttributeSet;
1426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.util.Log;
1526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.view.MotionEvent;
1626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.view.View;
1726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.view.Gravity;
1826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.view.ViewGroup;
1926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.widget.Button;
2026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.widget.FrameLayout;
2126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport android.widget.ImageView;
2226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
2326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport java.util.LinkedList;
2426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerimport java.util.HashMap;
2526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
2626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandlerpublic class BouncyDroid extends Activity {
2726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler    static final boolean DEBUG = true;
2826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler    static final boolean CENTER_DROID = true;
2926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
3026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler    public static class BouncyView extends FrameLayout
3126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler    {
3226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        boolean mShowDebug = false;
3326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
3440a5d064fc5eded6cca78c585304e46f1f3928e3Daniel Sandler        static final int RADIUS = 100;
3526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
3626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        static final boolean HAS_INITIAL_IMPULSE = true;
3726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        static final boolean HAS_GRAVITY = true;
3826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        static final boolean HAS_FRICTION = false;
3926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        static final boolean HAS_EDGES = true;
4026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
4126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        static final boolean STICKY_FINGERS = true;
4226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
4326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        static final float MAX_SPEED = 5000f;
4426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
4540a5d064fc5eded6cca78c585304e46f1f3928e3Daniel Sandler        static final float RANDOM_IMPULSE_PROB = 0.001f;
4640a5d064fc5eded6cca78c585304e46f1f3928e3Daniel Sandler
4726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        public static class World {
4826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            public static final float PX_PER_METER = 100f;
4940a5d064fc5eded6cca78c585304e46f1f3928e3Daniel Sandler            public static final float GRAVITY = 500f;
5026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            public static class Vec {
5126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                float x;
5226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                float y;
5326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public Vec() {
5426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    x = y = 0;
5526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
5626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public Vec(float _x, float _y) {
5726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    x = _x;
5826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    y = _y;
5926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
6026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public Vec add(Vec v) {
6126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    return new Vec(x + v.x, y + v.y);
6226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
6326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public Vec mul(float a) {
6426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    return new Vec(x * a, y * a);
6526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
6626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public Vec sub(Vec v) {
6726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    return new Vec(x - v.x, y - v.y);
6826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
6926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public float mag() {
7026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    return (float) Math.hypot(x, y);
7126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
7226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public Vec norm() {
7326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    float k = 1/mag();
7426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    return new Vec(x*k, y*k);
7526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
7626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public String toString() {
7726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    return "(" + x + "," + y + ")";
7826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
7926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            }
8026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            public static class Body {
8126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                float m, r;
8226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                Vec p = new Vec();
8326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                Vec v = new Vec();
8426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                LinkedList<Vec> forces = new LinkedList<Vec>();
8526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                LinkedList<Vec> impulses = new LinkedList<Vec>();
8626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public Body(float _m, Vec _p) {
8726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    m = _m;
8826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    p = _p;
8926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
9026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public void applyForce(Vec f) {
9126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    forces.add(f);
9226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
9326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public void applyImpulse(Vec f) {
9426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    impulses.add(f);
9526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
9626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public void clearForces() {
9726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    forces.clear();
9826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
9926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public void removeForce(Vec f) {
10026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    forces.remove(f);
10126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
10226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public void step(float dt) {
10326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    p = p.add(v.mul(dt));
10426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    for (Vec f : impulses) {
10526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        v = v.add(f.mul(dt/m));
10626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    }
10726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    impulses.clear();
10826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    for (Vec f : forces) {
10926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        v = v.add(f.mul(dt/m));
11026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    }
11126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
11226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public String toString() {
11326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    return "Body(m=" + m + " p=" + p + " v=" + v + ")";
11426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
11526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            }
11626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            LinkedList<Body> mBodies = new LinkedList<Body>();
11726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            public void addBody(Body b) {
11826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                mBodies.add(b);
11926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            }
12026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
12126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            public void step(float dt) {
12226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                for (Body b : mBodies) {
12326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    b.step(dt);
12426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
12526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            }
12626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        }
12726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
12826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
12926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        TimeAnimator mAnim;
13026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        World mWorld;
13126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        ImageView mBug;
13226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        View mShowDebugView;
13326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        HashMap<Integer, World.Vec> mFingers = new HashMap<Integer, World.Vec>();
13426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        World.Body mBody;
13526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        World.Vec mGrabSpot;
13626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        int mGrabbedPointer = -1;
13726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
13826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        public BouncyView(Context context, AttributeSet as) {
13926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            super(context, as);
14026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
14126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            /*
14226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
14326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                @Override
14426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public void onSystemUiVisibilityChange(int visibility) {
14526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    if (visibility == View.STATUS_BAR_VISIBLE) {
14626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        ((Activity)getContext()).finish();
14726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    }
14826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
14926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            });
15026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            */
15126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
15240a5d064fc5eded6cca78c585304e46f1f3928e3Daniel Sandler            setBackgroundColor(0xFF444444);
15340a5d064fc5eded6cca78c585304e46f1f3928e3Daniel Sandler
15426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            mBug = new ImageView(context);
15526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            mBug.setScaleType(ImageView.ScaleType.MATRIX);
15626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            addView(mBug, new ViewGroup.LayoutParams(
15726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        ViewGroup.LayoutParams.WRAP_CONTENT,
15826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        ViewGroup.LayoutParams.WRAP_CONTENT));
15926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
16026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            if (DEBUG) {
16126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                Button b = new Button(getContext());
16226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                b.setText("Debugzors");
16326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                b.setBackgroundColor(0); // very hard to see! :)
16426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                b.setOnClickListener(new View.OnClickListener() {
16526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    @Override
16626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    public void onClick(View v) {
16726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        setDebug(!mShowDebug);
16826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    }
16926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                });
17026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                addView(b, new FrameLayout.LayoutParams(
17126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            ViewGroup.LayoutParams.WRAP_CONTENT,
17226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            ViewGroup.LayoutParams.WRAP_CONTENT,
17326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            Gravity.TOP|Gravity.RIGHT));
17426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            }
17526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        }
17626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
17726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        public void setDebug(boolean d) {
17826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            if (d != mShowDebug) {
17926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                if (d) {
18026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    mShowDebugView = new DebugView(getContext());
18126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    mShowDebugView.setLayoutParams(
18226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        new ViewGroup.LayoutParams(
18326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            ViewGroup.LayoutParams.MATCH_PARENT,
18426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            ViewGroup.LayoutParams.MATCH_PARENT
18526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        ));
18626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    addView(mShowDebugView);
18726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
18826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    mBug.setBackgroundColor(0x2000FF00);
18926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                } else {
19026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    if (mShowDebugView != null) {
19126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        removeView(mShowDebugView);
19226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        mShowDebugView = null;
19326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    }
19426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    mBug.setBackgroundColor(0);
19526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
19626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                invalidate();
19726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                mShowDebug = d;
19826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            }
19926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        }
20026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
20126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        private void reset() {
20226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            mWorld = new World();
20326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            final float mass = 100;
20426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            mBody = new World.Body(mass, new World.Vec(200,200));
20526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            mBody.r = RADIUS;
20626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            mWorld.addBody(mBody);
20726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            mGrabbedPointer = -1;
20826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
20926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            mAnim = new TimeAnimator();
21026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            mAnim.setTimeListener(new TimeAnimator.TimeListener() {
21126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
21226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    if (deltaTime > 0) {
21326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        int STEPS = 5;
21426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        final float dt = deltaTime / (float) STEPS;
21526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        while (STEPS-->0) {
21626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            mBody.clearForces();
21726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
21826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            if (HAS_INITIAL_IMPULSE) {
21926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                // initial oomph
22026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                if (totalTime == 0) {
22126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    mBody.applyImpulse(new World.Vec(400000, -200000));
22226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                }
22326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            }
22426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
22526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            if (HAS_GRAVITY) {
22626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                // gravity points down
22726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                mBody.applyForce(new World.Vec(0, mass * World.GRAVITY));
22826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            }
22926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
23026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            if (mGrabbedPointer >= 0) {
23126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                World.Vec finger = mFingers.get(mGrabbedPointer);
23226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                if (finger == null) {
23326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    // let go!
23426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    mGrabbedPointer = -1;
23526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                } else {
23626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    // never gonna let you go
23726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    World.Vec newPos = finger.add(mGrabSpot);
23826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    mBody.v = mBody.v.add(newPos.sub(mBody.p).mul(dt));
23926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    mBody.p = newPos;
24026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                }
24126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            } else {
24226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                // springs
24326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                // ideal Hooke's Law plus a maximum force and a minimum length cutoff
24426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                for (Integer i : mFingers.keySet()) {
24526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    World.Vec finger = mFingers.get(i);
24626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    World.Vec springForce = finger.sub(mBody.p);
24726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    float mag = springForce.mag();
24826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
24926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    if (STICKY_FINGERS && mag < mBody.r*0.75) {
25026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                        // close enough; we'll call this a "stick"
25126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                        mGrabbedPointer = i;
25226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                        mGrabSpot = mBody.p.sub(finger);
25326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                        mBody.v = new World.Vec(0,0);
25426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                        break;
25526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    }
25626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
25740a5d064fc5eded6cca78c585304e46f1f3928e3Daniel Sandler                                    final float SPRING_K = 30000;
25826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    final float FORCE_MAX = 10*SPRING_K;
25926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    mag = (float) Math.min(mag * SPRING_K, FORCE_MAX); // Hooke's law
26026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            //                    float mag = (float) (FORCE_MAX / Math.pow(springForce.mag(), 2)); // Gravitation
26126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    springForce = springForce.norm().mul(mag);
26226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    mBody.applyForce(springForce);
26326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                }
26426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            }
26526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
26626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            if (HAS_FRICTION) {
26726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                // sliding friction opposes movement
26840a5d064fc5eded6cca78c585304e46f1f3928e3Daniel Sandler                                mBody.applyForce(mBody.v.mul(-0.01f * mBody.m));
26926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            }
27026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
27126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            if (HAS_EDGES) {
27226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                if (mBody.p.x - mBody.r < 0) {
27326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    mBody.v.x = (float) Math.abs(mBody.v.x) *
27440a5d064fc5eded6cca78c585304e46f1f3928e3Daniel Sandler                                        (HAS_FRICTION ? 0.95f : 1f);
27526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                } else if (mBody.p.x + mBody.r > getWidth()) {
27626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    mBody.v.x = (float) Math.abs(mBody.v.x) *
27740a5d064fc5eded6cca78c585304e46f1f3928e3Daniel Sandler                                        (HAS_FRICTION ? -0.95f : -1f);
27826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                }
27926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                if (mBody.p.y - mBody.r < 0) {
28026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    mBody.v.y = (float) Math.abs(mBody.v.y) *
28140a5d064fc5eded6cca78c585304e46f1f3928e3Daniel Sandler                                        (HAS_FRICTION ? 0.95f : 1f);
28226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                } else if (mBody.p.y + mBody.r > getHeight()) {
28326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    mBody.v.y = (float) Math.abs(mBody.v.y) *
28440a5d064fc5eded6cca78c585304e46f1f3928e3Daniel Sandler                                        (HAS_FRICTION ? -0.95f : -1f);
28526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                }
28626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            }
28726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
28826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            if (MAX_SPEED > 0) {
28926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                if (mBody.v.mag() > MAX_SPEED) {
29026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                    mBody.v = mBody.v.norm().mul(MAX_SPEED);
29126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                }
29226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            }
29326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
29426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            // ok, Euler, do your thing
29526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            mWorld.step(dt / 1000f); // dt is in sec
29626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        }
29726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    }
29826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    mBug.setTranslationX(mBody.p.x - mBody.r);
29926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    mBug.setTranslationY(mBody.p.y - mBody.r);
30026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
30126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    Matrix m = new Matrix();
30226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    m.setScale(
30326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        (mBody.v.x < 0)    ? -1 : 1,
30426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        (mBody.v.y > 1500) ? -1 : 1, // AAAAAAAAAAAAAAAA
30526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        RADIUS, RADIUS);
30626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    mBug.setImageMatrix(m);
30726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    if (CENTER_DROID) {
30826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        mBug.setImageResource(
30926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                            (Math.abs(mBody.v.x) < 25)
31026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                ? R.drawable.bouncy_center
31126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                : R.drawable.bouncy);
31226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    }
31326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
31426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    if (mShowDebug) mShowDebugView.invalidate();
31526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
31626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            });
31726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        }
31826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
31926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        @Override
32026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        protected void onAttachedToWindow() {
32126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            super.onAttachedToWindow();
32226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            setSystemUiVisibility(View.STATUS_BAR_HIDDEN);
32326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
32426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            reset();
32526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            mAnim.start();
32626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        }
32726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
32826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        @Override
32926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        protected void onDetachedFromWindow() {
33026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            super.onDetachedFromWindow();
33126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            mAnim.cancel();
33226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        }
33326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
33426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        @Override
33526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        public boolean onTouchEvent(MotionEvent event) {
33626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            int i;
33726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            for (i=0; i<event.getPointerCount(); i++) {
33826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                switch (event.getActionMasked()) {
33926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    case MotionEvent.ACTION_DOWN:
34026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    case MotionEvent.ACTION_MOVE:
34126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    case MotionEvent.ACTION_POINTER_DOWN:
34226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        mFingers.put(event.getPointerId(i),
34326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                                new World.Vec(event.getX(i), event.getY(i)));
34426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        break;
34526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
34626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    case MotionEvent.ACTION_UP:
34726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    case MotionEvent.ACTION_POINTER_UP:
34826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        mFingers.remove(event.getPointerId(i));
34926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        break;
35026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
35126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    case MotionEvent.ACTION_CANCEL:
35226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        mFingers.clear();
35326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        break;
35426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
35526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            }
35626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            // expired pointers
35726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler    //        for (; i<mFingers.length; i++) {
35826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler    //            mFingers[i] = null;
35926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler    //        }
36026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            return true;
36126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        }
36226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
36326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        @Override
36426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        public boolean isOpaque() {
36526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            return true;
36626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        }
36726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
36826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        class DebugView extends View {
36926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            public DebugView(Context ct) {
37026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                super(ct);
37126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            }
37226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
37326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            private void drawVector(Canvas canvas,
37426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    float x, float y, float vx, float vy,
37526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    Paint pt) {
37626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                final float mag = (float) Math.hypot(vx, vy);
37726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
37826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                canvas.save();
37926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                Matrix mx = new Matrix();
38026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                mx.setSinCos(-vx/mag, vy/mag);
38126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                mx.postTranslate(x, y);
38226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                canvas.setMatrix(mx);
38326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
38426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                canvas.drawLine(0,0, 0, mag, pt);
38526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                canvas.drawLine(0, mag, -4, mag-4, pt);
38626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                canvas.drawLine(0, mag, 4, mag-4, pt);
38726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
38826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                canvas.restore();
38926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            }
39026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
39126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            @Override
39226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            protected void onDraw(Canvas canvas) {
39326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                super.onDraw(canvas);
39426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
39526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                Paint pt = new Paint(Paint.ANTI_ALIAS_FLAG);
39626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                pt.setColor(0xFFCC0000);
39726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                pt.setTextSize(30f);
39826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                pt.setStrokeWidth(1.0f);
39926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
40026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                for (Integer id : mFingers.keySet()) {
40126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    World.Vec v = mFingers.get(id);
40226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    float x = v.x;
40326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    float y = v.y;
40426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    pt.setStyle(Paint.Style.FILL);
40526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    canvas.drawText("#"+id, x+38, y-38, pt);
40626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    pt.setStyle(Paint.Style.STROKE);
40726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    canvas.drawLine(x-40, y, x+40, y, pt);
40826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    canvas.drawLine(x, y-40, x, y+40, pt);
40926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    canvas.drawCircle(x, y, 40, pt);
41026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
41126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                pt.setStyle(Paint.Style.STROKE);
41226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                if (mBody != null) {
41326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    float x = mBody.p.x;
41426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    float y = mBody.p.y;
41526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    float r = mBody.r;
41626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    pt.setColor(0xFF6699FF);
41726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    RectF bounds = new RectF(x-r, y-r, x+r, y+r);
41826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    canvas.drawOval(bounds, pt);
41926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
42026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    pt.setStrokeWidth(3);
42140a5d064fc5eded6cca78c585304e46f1f3928e3Daniel Sandler                    drawVector(canvas, x, y, mBody.v.x/100, mBody.v.y/100, pt);
42226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
42326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    pt.setColor(0xFF0033FF);
42426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    for (World.Vec f : mBody.forces) {
42526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                        drawVector(canvas, x, y, f.x/1000, f.y/1000, pt);
42626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                    }
42726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler                }
42826e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler            }
42926e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        }
43026e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler    }
43126e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler
43226e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler    @Override
43326e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler    public void onStart() {
43426e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        super.onStart();
43526e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler        setContentView(new BouncyView(this, null));
43626e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler    }
43726e4a6ce116b0a756dcaf9c80c466903789cac45Daniel Sandler}
438