hjuste
hjuste

Reputation: 175

Draw Multiple Objects - Android

So I got this working class that creates a DarkHole object in the screen. Its a filled circle with random color, position and radius.

public class DarkHole extends View
{
    private ShapeDrawable mDarkHole;

    // instance variables
    private int x, y, Xt, Yt;        // position
    private double forca;        // velocity
    private int raio;  // radius

    private int minRaio = 30;
    private int maxRaio = 200;

    private WindowManager wm;
    private Display display;
    private int width;
    private int height;

    int r,g,b ;
    int randomColor;

    Point size;

    private Random rand;

    // constructor
    public DarkHole(Context context)
    {
        super(context);

        mDarkHole = new ShapeDrawable(new OvalShape());

        rand = new Random();

        //Get Screen Size
        size = new Point();
        wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
        display = wm.getDefaultDisplay();
        display.getSize(size);
        width = (size.x);
        height = (size.y);

        //Set a random color
        r = rand.nextInt(255);
        g = rand.nextInt(255);
        b = rand.nextInt(255);
        randomColor = Color.rgb(r, g, b);

        CriarDarkHole();
    }
    public void CriarDarkHole()
    {
        x = rand.nextInt(width + 1);
        y = rand.nextInt(height + 1);

        raio = rand.nextInt(maxRaio - minRaio + 1) + minRaio;

        mDarkHole.getPaint().setColor(randomColor);
        mDarkHole.setBounds(x, y, x + raio, y + raio);
    }

    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        //mDarkHole.draw(canvas);
        //for(int i = 0; i <100; i++)
        // {
        mDarkHole.draw(canvas);
        //}
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        Xt = (int) event.getX();
        Yt = (int) event.getY();

        int evento = event.getAction();

        switch (evento)
        {
        case MotionEvent.ACTION_DOWN:
            CriarDarkHole();
            //isTouch = true;
            break;

        case MotionEvent.ACTION_MOVE:
            //coords.setText("X: " + X + ", Y: " + Y);
            break;

        case MotionEvent.ACTION_UP:
            //Toast.makeText(this, "Saiu da tela em: X: " + X + ", Y: " + Y, Toast.LENGTH_SHORT);
            //isTouch = false;
            break;
        }
        return true;
    }

}

My problem is:

  1. CriarDarkHole() is only triggered once. It should create another darkhole every time its called, adding balls on the screen. In the case, every time the screen is touched.

    Why it's not working? How it should be done?


EDIT 1 - Tried to add a ShapeDrawable array an draw it

    public class DarkHole extends View
{

    private ShapeDrawable mDarkHole;

    // instance variables
    private int x, y, Xt, Yt;        // position
    private double forca;        // velocity
    private int raio;  // radius

    private int minRaio = 30;
    private int maxRaio = 200;

    List<ShapeDrawable> holescreated;

    private WindowManager wm;
    private Display display;
    private int width;
    private int height;

    int r,g,b ;
    int randomColor;

    Point size;

    private Random rand;

    // constructor
    public DarkHole(Context context)
    {
        super(context);

        rand = new Random();
        holescreated = new ArrayList<ShapeDrawable>();

        //Get Screen Size
        size = new Point();
        wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
        display = wm.getDefaultDisplay();
        display.getSize(size);
        width = (size.x);
        height = (size.y);



        CriarDarkHole();

    }
    public void CriarDarkHole()
    {
        //mDarkHole = new ShapeDrawable(new OvalShape());
        holescreated.add(new ShapeDrawable(new OvalShape()));

        //Set a random color
        r = rand.nextInt(255);
        g = rand.nextInt(255);
        b = rand.nextInt(255);
        randomColor = Color.rgb(r, g, b);

        x = rand.nextInt(width + 1);
        y = rand.nextInt(height + 1);

        raio = rand.nextInt(maxRaio - minRaio + 1) + minRaio;

        for(ShapeDrawable m: holescreated)
        {
            m.getPaint().setColor(randomColor);
            m.setBounds(x, y, x + raio, y + raio);
        }

    }

    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        //mDarkHole.draw(canvas);
        for(ShapeDrawable m: holescreated)
        {
            m.draw(canvas);
        }
        invalidate();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        Xt = (int) event.getX();
        Yt = (int) event.getY();

        int evento = event.getAction();

        switch (evento)
        {
        case MotionEvent.ACTION_DOWN:
            CriarDarkHole();
            //isTouch = true;
            break;

        case MotionEvent.ACTION_MOVE:
            //coords.setText("X: " + X + ", Y: " + Y);
            break;

        case MotionEvent.ACTION_UP:
            //Toast.makeText(this, "Saiu da tela em: X: " + X + ", Y: " + Y, Toast.LENGTH_SHORT);
            //isTouch = false;
            break;
        }
        return true;
    }



}

Now when i Tap the display it draws a new ball but erasing the old one. How draw all the balls ? Where am I missing?


EDIT 2 - Now it's working but doesn't feel the right way to code

public class DarkHole extends View
{

    private ShapeDrawable mDarkHole;

    // instance variables
    private int x, y, Xt, Yt;        // position
    private double forca;        // velocity
    private int raio;  // radius

    private int minRaio = 30;
    private int maxRaio = 100;

    List<ShapeDrawable> holescreated;

    private WindowManager wm;
    private Display display;
    private int width;
    private int height;

    int r,g,b ,cont;
    int randomColor;
    Paint cor;;

    Point size;

    private Random rand;

    // constructor
    public DarkHole(Context context)
    {
        super(context);

        cor = new Paint();

        rand = new Random();
        holescreated = new ArrayList<ShapeDrawable>();
        cont = 0;
        //Get Screen Size
        size = new Point();
        wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
        display = wm.getDefaultDisplay();
        display.getSize(size);
        width = (size.x);
        height = (size.y);



        CriarDarkHole();

    }
    public void CriarDarkHole()
    {
        cor.setColor(Color.BLACK);
        cor.setTextSize(70);
        cor.setAntiAlias(true);
        cor.setDither(true);
        //mDarkHole = new ShapeDrawable(new OvalShape());
        holescreated.add(new ShapeDrawable(new OvalShape()));

        //Set a random color
        r = rand.nextInt(255);
        g = rand.nextInt(255);
        b = rand.nextInt(255);
        randomColor = Color.rgb(r, g, b);


        raio = rand.nextInt(maxRaio - minRaio + 1) + minRaio;

        x = rand.nextInt((width-raio)  + 1) ;
        y = rand.nextInt((height-raio)  + 1) ;



        for(ShapeDrawable m: holescreated)
        {
            holescreated.get(cont).getPaint().setColor(randomColor);
            holescreated.get(cont).setBounds(x, y, x + raio, y + raio);
        }
        cont++;
    }

    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        //mDarkHole.draw(canvas);
        for(ShapeDrawable m: holescreated)
        {
            m.draw(canvas);
            canvas.drawText("Bolas: " + holescreated.size(),10,50, cor);
        }
        invalidate();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        Xt = (int) event.getX();
        Yt = (int) event.getY();

        int evento = event.getAction();

        switch (evento)
        {
        case MotionEvent.ACTION_DOWN:
            CriarDarkHole();
            //isTouch = true;
            break;

        case MotionEvent.ACTION_MOVE:
            CriarDarkHole();
            //coords.setText("X: " + X + ", Y: " + Y);
            break;

        case MotionEvent.ACTION_UP:
            //Toast.makeText(this, "Saiu da tela em: X: " + X + ", Y: " + Y, Toast.LENGTH_SHORT);
            //isTouch = false;
            break;
        }
        return true;
    }
}

App Image

https://i.sstatic.net/erg5z.jpg


Even now that it working, it doesn't feel the right way to do it. I mean in an OOP way... Is it re-drawing all the balls every time?! Any tips, critics or suggestions?

Upvotes: 0

Views: 1694

Answers (1)

hjuste
hjuste

Reputation: 175

WORKING LIKE A CHARM!

Now I draw multiple balls on touch and I can even test their collisions

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)) {
                hole = null;
            } else {
                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);

        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);
            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);
    }
}

The ideia is:

  1. Generate a circle with random diameter, color, and position

  2. Test if that circle is colliding with any other circle already drawn

  3. If it is colliding, re-generate random stuff, if not add that circle to the arraylist

Upvotes: 1

Related Questions