samedi 30 mai 2015

Collision Detection Between Circles - OnTouch (Android)

I got this working class that creates a DarkHole object in the screen. Its a filled circle with random color, position and radius. When screen is touched, it is supposed to draw a ball avoiding the other ones that have already been drawn.

I used this method: Colision by Radius


public class DarkHole extends View {

    public static final int maxDiameter = 250;

    public static final int minDiameter = 240;

    /**
    * This class log tag.
    */
    private static final String LOG_TAG = DarkHole.class.getSimpleName();

    private static List<ShapeDrawable> mHoles;

    private int mWindowWidth;

    private int mWindowHeight;

    private Random random;

    /**
    * The constructor;
    *
    * @param context application context.
    */
    public DarkHole(Context context) {
        super(context);
        mHoles = new ArrayList<ShapeDrawable>();
        random = new Random();

        //Get Screen Size
        Point point = new Point();
        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        display.getSize(point);

        // Get screen max x and y.
        mWindowWidth = point.x;
        mWindowHeight = point.y;
    }

    /**
    * Draw random hole.
    */
    private void generateRandomHole() {
        while(true) {
            ShapeDrawable hole = new ShapeDrawable(new OvalShape());

            // Generate random color.

            int r = random.nextInt(255);
            int g = random.nextInt(255);
            int b = random.nextInt(255);
            int randomColor = Color.rgb(r, g, b);

            // Generate random position.
            int diameter = random.nextInt(maxDiameter - minDiameter + 1) + minDiameter;
            int x = random.nextInt((mWindowWidth - diameter) + 1);
            int y = random.nextInt((mWindowHeight - diameter) + 1);

            hole.getPaint().setColor(randomColor);
            hole.setBounds(x, y, x + diameter, y + diameter);

            if (checkDrawContains(hole)) {
                Log.d(LOG_TAG, "[generateRandomHole] contains!");
                hole = null;
                random = null;
            } else {
                Log.d(LOG_TAG, "[generateRandomHole] not contains!");
                mHoles.add(hole);
                break;
            }
        }
    }

    /**
    * Draw informative text.
    *
    * @param canvas canvas object.
    */
    private void generateText(Canvas canvas) {
        Paint color = new Paint();
        color.setColor(Color.BLACK);
        color.setTextSize(70);
        color.setAntiAlias(true);
        color.setDither(true);
        canvas.drawText("Bolas: " + mHoles.size(), 10, 50, color);
    }


    private boolean checkDrawContains(ShapeDrawable newHole) {
        long newCenterX = newHole.getBounds().left + (newHole.getBounds().width()/2);
        long newCenterY = newHole.getBounds().top + (newHole.getBounds().height()/2);

        Log.d(LOG_TAG, "[checkDrawContains] newCenterX: " + newCenterX);
        for(ShapeDrawable hole: mHoles) {
            long centerX = hole.getBounds().left + (hole.getBounds().width()/2);
            long centerY = hole.getBounds().top + (hole.getBounds().height()/2);
            long x = centerX - newCenterX;
            long y = centerY - newCenterY;
            long aux = (long) ((Math.pow(Math.abs(x),2)) + (Math.pow(Math.abs(y),2)));
            long distance = (long) Math.sqrt(aux);
            Log.d(LOG_TAG, "[checkDrawContains] x: " + x);
            Log.d(LOG_TAG, "[checkDrawContains] y: " + y);
            Log.d(LOG_TAG, "[checkDrawContains] distance: " + distance);
            Log.d(LOG_TAG, "[checkDrawContains] sum radius: " + (newCenterX + centerX));
            long sRads = (newHole.getBounds().width()/2) + (hole.getBounds().width()/2);

            if(distance <=  sRads ) {
                return true;
            }
        }
        return false;
    }

    /** {@inheritDoc} */
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        generateText(canvas);
        for (ShapeDrawable hole : mHoles) {
            hole.draw(canvas);
        }

        invalidate();
    }

    /** {@inheritDoc} */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            generateRandomHole();
            return true;
        }
        return super.onTouchEvent(event);
    }
}


It should work, but It crashes when the recursion starts to recalculate all the random parameters. Is it a stack overflow? Why is that happening? How it should be solved?




Aucun commentaire:

Enregistrer un commentaire