Android Open Source - 101AndroidApps Bouncy Balls View






From Project

Back to project page 101AndroidApps.

License

The source code is released under:

Licenced under the Creative Commons Attribution 4.0 licence. For full text see http://creativecommons.org/licenses/by/4.0/

If you think the Android project 101AndroidApps listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.hulzenga.ioi.android.app_002;
/* ww  w .  j a v a2s  .  com*/
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

import java.util.ArrayList;
import java.util.List;

class BouncyBallsView extends View implements OnTouchListener {

  /*
   * TODO: figure out bug which causes all balls to disappear. Encountered when
   * screen is full balls and one of the balls is forcefully pulled through the balls 
   * (might be a divide by almost zero thing in collision handling) 
   */

  private static final String TAG = "BouncyBallView";

  //drawing frequency parameters
  private static final long  TIMESTEP         = 16;
  private static final float TIMESTEP_SECONDS = TIMESTEP / 1000.0f;

  //performance limit
  private static final int MAX_NUMBER_OF_BALLS = 90;

  //lock so drawing and touch events don't interlace
  private static final Object lock = new Object();

  private Paint mBallPaint = new Paint();

  //list of the balls and a possible selected ball
  private List<Ball> mBalls        = new ArrayList<Ball>();
  private Ball       mSelectedBall = null;

  //state booleans
  private          boolean mBallSelected = false;
  private volatile boolean mRunning      = false;

  public BouncyBallsView(Context context) {
    super(context);
    this.setOnTouchListener(this);

    //Initialise paint
    mBallPaint.setColor(Color.GREEN);
  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    synchronized (lock) {
      for (Ball ball : mBalls) {
        drawBall(canvas, ball);
      }
      if (mBallSelected) {
        drawBall(canvas, mSelectedBall);
      }
    }
  }

  private void drawBall(Canvas canvas, Ball ball) {
    final int speed = Math.min(Math.max((int) Math.sqrt(ball.vX * ball.vX + ball.vY * ball.vY), 0), 255);

    mBallPaint.setColor(Color.rgb(speed, 255 - speed, 0));
    canvas.drawCircle(ball.x, ball.y, ball.r, mBallPaint);
  }

  public boolean onTouch(View view, MotionEvent event) {

    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:

        //Check if selecting an existing ball
        for (int i = 0; i < mBalls.size(); i++) {
          if (mBalls.get(i).isBallHere(event.getX(), event.getY())) {
            mSelectedBall = mBalls.get(i);
            mSelectedBall.select();
            mBallSelected = true;
            synchronized (lock) {
              mBalls.remove(i);
            }
            break;
          }
        }

        //If not selecting make a new ball and select it
        if (!mBallSelected && mBalls.size() < MAX_NUMBER_OF_BALLS) {
          mSelectedBall = new Ball(event.getX(), event.getY());
          mBallSelected = true;
        }
        break;
      case MotionEvent.ACTION_MOVE:
        if (mBallSelected) {
          mSelectedBall.dragBallTo(event.getX(), event.getY());
        }
        break;
      case MotionEvent.ACTION_UP:
        if (mBallSelected) {
          //return selected ball to the list
          synchronized (lock) {
            mBalls.add(mSelectedBall);
          }
          mBallSelected = false;
        }
        break;
    }

    return true;
  }

  public void start() {
    new Thread(new Runnable() {

      @Override
      public void run() {

        long time = System.currentTimeMillis();

        mRunning = true;

        while (mRunning) {

          synchronized (lock) {

            for (int i = 0; i < mBalls.size(); i++) {
              mBalls.get(i).updatePosition(TIMESTEP_SECONDS);

              for (int j = i + 1; j < mBalls.size(); j++) {
                mBalls.get(i).handleCollision(mBalls.get(j));
              }
              if (mBallSelected) {
                mBalls.get(i).handleCollision(mSelectedBall);
              }

            }
          }

          try {
            Thread.sleep(TIMESTEP - (System.currentTimeMillis() - time)); //tries to sync
          } catch (InterruptedException e) {
            e.printStackTrace();
          } catch (IllegalArgumentException e) {
            e.printStackTrace();
            Log.d(TAG, "Error: the numerical simulation per step takes longer than the desired timestep");
          }

          time = System.currentTimeMillis();
          postInvalidate();
        }

      }
    }).start();
  }

  public void stop() {
    mRunning = false;
  }


  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    Ball.setBounds(w, h);
  }


}




Java Source Code List

com.hulzenga.ioi.android.AppActivity.java
com.hulzenga.ioi.android.AppDetailsDialog.java
com.hulzenga.ioi.android.App.java
com.hulzenga.ioi.android.TableOfContentsActivity.java
com.hulzenga.ioi.android.app_001.HelloWorldActivity.java
com.hulzenga.ioi.android.app_002.Ball.java
com.hulzenga.ioi.android.app_002.BouncyBallsActivity.java
com.hulzenga.ioi.android.app_002.BouncyBallsView.java
com.hulzenga.ioi.android.app_003.MonsterDatabaseActivity.java
com.hulzenga.ioi.android.app_003.MonsterEditDialog.java
com.hulzenga.ioi.android.app_003.MonsterGenerator.java
com.hulzenga.ioi.android.app_003.MonsterListAdapter.java
com.hulzenga.ioi.android.app_003.database.MonsterContract.java
com.hulzenga.ioi.android.app_003.database.MonsterDatabaseHelper.java
com.hulzenga.ioi.android.app_003.database.MonsterProvider.java
com.hulzenga.ioi.android.app_004.BouncyBall3dActivity.java
com.hulzenga.ioi.android.app_004.BouncyBall3dGLSurfaceView.java
com.hulzenga.ioi.android.app_004.BouncyBall3dRenderer.java
com.hulzenga.ioi.android.app_004.BouncyBallGame.java
com.hulzenga.ioi.android.app_005.ElementActivity.java
com.hulzenga.ioi.android.app_005.ElementAdapter.java
com.hulzenga.ioi.android.app_005.ElementAnimator.java
com.hulzenga.ioi.android.app_005.ElementSnakeView.java
com.hulzenga.ioi.android.app_005.ElementView.java
com.hulzenga.ioi.android.app_005.Element.java
com.hulzenga.ioi.android.app_006.EmptyFragment.java
com.hulzenga.ioi.android.app_006.ExposureFragment.java
com.hulzenga.ioi.android.app_006.SettingChangeListener.java
com.hulzenga.ioi.android.app_006.SettingIconFragment.java
com.hulzenga.ioi.android.app_006.SettingMenuFragment.java
com.hulzenga.ioi.android.app_006.SettingMenuLvl2Fragment.java
com.hulzenga.ioi.android.app_006.Setting.java
com.hulzenga.ioi.android.app_006.SimpleCameraActivity.java
com.hulzenga.ioi.android.app_006.SimpleCameraPreview.java
com.hulzenga.ioi.android.app_007.ButtonsFragment.java
com.hulzenga.ioi.android.app_007.HighScores.java
com.hulzenga.ioi.android.app_007.LinksFragment.java
com.hulzenga.ioi.android.app_007.Menu.java
com.hulzenga.ioi.android.app_007.Review.java
com.hulzenga.ioi.android.app_007.Score.java
com.hulzenga.ioi.android.app_007.StatusFragment.java
com.hulzenga.ioi.android.app_007.WikiGameActivity.java
com.hulzenga.ioi.android.app_007.Wiki.java
com.hulzenga.ioi.android.app_008.OverheidActivity.java
com.hulzenga.ioi.android.app_008.OverheidFeedAdapter.java
com.hulzenga.ioi.android.app_008.OverheidFeedFragment.java
com.hulzenga.ioi.android.app_008.OverheidFeedItem.java
com.hulzenga.ioi.android.app_008.OverheidFeed.java
com.hulzenga.ioi.android.app_008.OverheidPagerAdapter.java
com.hulzenga.ioi.android.app_009.ThumbsUpActivity.java
com.hulzenga.ioi.android.app_009.ThumbsUpServer.java
com.hulzenga.ioi.android.app_009.ThumbsUpService.java
com.hulzenga.ioi.android.app_010.CompassActivity.java
com.hulzenga.ioi.android.app_010.CompassDetailsView.java
com.hulzenga.ioi.android.app_010.CompassView.java
com.hulzenga.ioi.android.util.Constrain.java
com.hulzenga.ioi.android.util.DeveloperTools.java
com.hulzenga.ioi.android.util.FileManager.java
com.hulzenga.ioi.android.util.ScreenMetrics.java
com.hulzenga.ioi.android.util.open_gl.ColorFunctionFactory.java
com.hulzenga.ioi.android.util.open_gl.ColorFunction.java
com.hulzenga.ioi.android.util.open_gl.ShaderTools.java
com.hulzenga.ioi.android.util.open_gl.engine.NodeController.java
com.hulzenga.ioi.android.util.open_gl.engine.SceneGraph.java
com.hulzenga.ioi.android.util.open_gl.engine.SceneNode.java
com.hulzenga.ioi.android.util.open_gl.geometry.Box.java
com.hulzenga.ioi.android.util.open_gl.geometry.Cylinder.java
com.hulzenga.ioi.android.util.open_gl.geometry.Geometry.java
com.hulzenga.ioi.android.util.open_gl.geometry.Grid.java
com.hulzenga.ioi.android.util.open_gl.geometry.Sphere.java
com.hulzenga.ioi.android.util.open_gl.geometry.Transform.java
com.hulzenga.ioi.android.util.open_gl.vector.Vec3.java
com.hulzenga.ioi.android.util.open_gl.vector.Vec4.java
fi.iki.elonen.NanoHTTPD.java