|
Android example source code file (BallRegion.java)
The BallRegion.java Android example source code/* * Copyright (C) 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.android.divideandconquer; import java.util.List; import java.util.ArrayList; import java.util.Iterator; import java.lang.ref.WeakReference; /** * A ball region is a rectangular region that contains bouncing * balls, and possibly one animating line. In its {@link #update(long)} method, * it will update all of its balls, the moving line. It detects collisions * between the balls and the moving line, and when the line is complete, handles * splitting off a new region. */ public class BallRegion extends Shape2d { private float mLeft; private float mRight; private float mTop; private float mBottom; private List<Ball> mBalls; private AnimatingLine mAnimatingLine; private boolean mShrinkingToFit = false; private long mLastUpdate = 0; private static final float PIXELS_PER_SECOND = 25.0f; private static final float SHRINK_TO_FIT_AREA_THRESH = 10000.0f; private static final float SHRINK_TO_FIT_AREA_THRESH_ONE_BALL = 20000.0f; private static final float SHRINK_TO_FIT_AREA = 1000f; private static final float MIN_EDGE = 30f; private boolean mDoneShrinking = false; private WeakReference<BallEngine.BallEventCallBack> mCallBack; /* * @param left The minimum x component * @param right The maximum x component * @param top The minimum y component * @param bottom The maximum y component * @param balls the balls of the region */ public BallRegion(long now, float left, float right, float top, float bottom, ArrayList<Ball> balls) { mLastUpdate = now; mLeft = left; mRight = right; mTop = top; mBottom = bottom; mBalls = balls; final int numBalls = mBalls.size(); for (int i = 0; i < numBalls; i++) { final Ball ball = mBalls.get(i); ball.setRegion(this); } checkShrinkToFit(); } public void setCallBack(BallEngine.BallEventCallBack callBack) { this.mCallBack = new WeakReference<BallEngine.BallEventCallBack>(callBack); } private void checkShrinkToFit() { final float area = getArea(); if (area < SHRINK_TO_FIT_AREA_THRESH) { mShrinkingToFit = true; } else if (area < SHRINK_TO_FIT_AREA_THRESH_ONE_BALL && mBalls.size() == 1) { mShrinkingToFit = true; } } public float getLeft() { return mLeft; } public float getRight() { return mRight; } public float getTop() { return mTop; } public float getBottom() { return mBottom; } public List<Ball> getBalls() { return mBalls; } public AnimatingLine getAnimatingLine() { return mAnimatingLine; } public boolean consumeDoneShrinking() { if (mDoneShrinking) { mDoneShrinking = false; return true; } return false; } public void setNow(long now) { mLastUpdate = now; // update the balls final int numBalls = mBalls.size(); for (int i = 0; i < numBalls; i++) { final Ball ball = mBalls.get(i); ball.setNow(now); } if (mAnimatingLine != null) { mAnimatingLine.setNow(now); } } /** * Update the balls an (if it exists) the animating line in this region. * @param now in millis * @return A new region if a split has occured because the animating line * finished. */ public BallRegion update(long now) { // update the animating line final boolean newRegion = (mAnimatingLine != null && mAnimatingLine.update(now)); final int numBalls = mBalls.size(); // move balls, check for collision with animating line for (int i = 0; i < numBalls; i++) { final Ball ball = mBalls.get(i); ball.update(now); if (mAnimatingLine != null && ball.isIntersecting(mAnimatingLine)) { mAnimatingLine = null; if (mCallBack != null) mCallBack.get().onBallHitsLine(now, ball, mAnimatingLine); } } // update ball to ball collisions for (int i = 0; i < numBalls; i++) { final Ball ball = mBalls.get(i); for (int j = i + 1; j < numBalls; j++) { Ball other = mBalls.get(j); if (ball.isCircleOverlapping(other)) { Ball.adjustForCollision(ball, other); break; } } } handleShrinkToFit(now); // no collsion, new region means we need to split out the apropriate // balls into a new region if (newRegion && mAnimatingLine != null) { BallRegion otherRegion = splitRegion( now, mAnimatingLine.getDirection(), mAnimatingLine.getPerpAxisOffset()); mAnimatingLine = null; return otherRegion; } else { return null; } } private void handleShrinkToFit(long now) { // update shrinking to fit if (mShrinkingToFit && mAnimatingLine == null) { if (now == mLastUpdate) return; float delta = (now - mLastUpdate) * PIXELS_PER_SECOND; delta = delta / 1000; if (getHeight() > MIN_EDGE) { mTop += delta; mBottom -= delta; } if (getWidth() > MIN_EDGE) { mLeft += delta; mRight -= delta; } final int numBalls = mBalls.size(); for (int i = 0; i < numBalls; i++) { final Ball ball = mBalls.get(i); ball.setRegion(this); } if (getArea() <= SHRINK_TO_FIT_AREA) { mShrinkingToFit = false; mDoneShrinking = true; } } mLastUpdate = now; } /** * Return whether this region can start a line at a certain point. */ public boolean canStartLineAt(float x, float y) { return !mShrinkingToFit && mAnimatingLine == null && isPointWithin(x, y); } /** * Start a horizontal line at a point. * @param now What 'now' is. * @param x The x coordinate. * @param y The y coordinate. */ public void startHorizontalLine(long now, float x, float y) { if (!canStartLineAt(x, y)) { throw new IllegalArgumentException( "can't start line with point (" + x + "," + y + ")"); } mAnimatingLine = new AnimatingLine(Direction.Horizontal, now, y, x, mLeft, mRight); } /** * Start a vertical line at a point. * @param now What 'now' is. * @param x The x coordinate. * @param y The y coordinate. */ public void startVerticalLine(long now, float x, float y) { if (!canStartLineAt(x, y)) { throw new IllegalArgumentException( "can't start line with point (" + x + "," + y + ")"); } mAnimatingLine = new AnimatingLine(Direction.Vertical, now, x, y, mTop, mBottom); } /** * Splits this region at a certain offset, shrinking this one down and returning * the other region that makes up the rest. * @param direction The direction of the line. * @param perpAxisOffset The offset of the perpendicular axis of the line. * @return A new region containing a portion of the balls. */ private BallRegion splitRegion(long now, Direction direction, float perpAxisOffset) { ArrayList<Ball> splitBalls = new ArrayList Other Android examples (source code examples)Here is a short list of links related to this Android BallRegion.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.