Search code examples
androidlibgdxclone

New object type render on render() method?


I am looking for creating new objects everytime while touching screen or clicking mouse, or every time user inputs. I had some ideas just like cloning, creating new, or adding in ArrayList. Something like:

if (Gdx.input.JustTouched){ shapeRenderer.circle(Gdx.input.getX(),Gdx.input.getY(),10); }

But everytime when is touched, draws a new circle. I have tried with:

private Object[] appendValue(Object[] obj, Object newObj) {

    ArrayList<Object> temp = new ArrayList<Object>(Arrays.asList(obj));
    temp.add(newObj);
    return temp.toArray();

But I cannot assign a void method (shapeRenderer.circle) to an object, so didn't work for me. other way was doing the draw outside the if, passing the coordinates, but keeps in the render loop and then gets lost the coordinates. Is it possible to clone methods and get new draws? If this was answered, please tell me and I'll delete this question, I'm really lost


Solution

  • The method shapeRenderer.circle(float x, float y, float radius) draws a circle on the canvas. It does not create an object, it creates a bunch of pixels on the canvas, which are lost as soon as the canvas is redrawn.

    You need to store the data that you would pass into the circle method, so that you can redraw your old circles, and add more on touch events. A good way to do that would be to define a class Circle:

    public class Circle {
        public float x;
        public float y;
        public float radius;
    
        public Circle(float x, float y, float radius) {
            this.x = x;
            this.y = y;
            this.radius = radius;
        }
    }
    

    Then you can create a list of these circles, and add a new one every time you detect a touch event:

    if (Gdx.input.JustTouched)
        circles.add(new Circle(Gdx.input.getX(),Gdx.input.getY(),10));
    

    And whenever you need to redraw the screen, draw all the circles:

    for (Circle circle : circles)
        shapeRenderer.circle(circle.x, circle.y, circle.radius);
    

    EDIT

    Your code was crashing, because your collection of Circles was null, and you call circles.add. That will throw a null pointer exception unless you instantiate circles properly.

    public class MyGdxGame implements ApplicationListener
    {
        ShapeRenderer shapeRenderer;
        OrthographicCamera camera;
    
        // It's a collection specifically of Circles. Also, there's one per game, so don't make it static.
        Collection<Circle> circles;
    
        @Override
        public void create()
        {       
            camera = new OrthographicCamera();
            configureCamera();
            shapeRenderer = new ShapeRenderer();
    
            // Make it an empty collection to begin with
            circles = new ArrayList<Circle>();
        }
    
        @Override
        public void render()
        {       
            Gdx.gl.glClearColor(1, 1, 1, 1);
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    
            camera.update();
            shapeRenderer.setProjectionMatrix(camera.combined);
            shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
    
            shapeRenderer.setColor(0, 0.5f, 0, 1);
            shapeRenderer.circle(50, 50, 40);
    
            shapeRenderer.setColor(0.5f, 0, 0, 1);
            shapeRenderer.rect(10, 100, 80, 80);
    
            shapeRenderer.setColor(0, 0, 0.5f, 1);
            shapeRenderer.triangle(10, 200, 90, 200, 50, 270);
    
            // Check for input, and add the new circle, *before* drawing all the circles
            if (Gdx.input.justTouched())
                circles.add(new Circle(Gdx.input.getX(),Gdx.input.getY(),10));
    
            for (Circle circle : circles)
                shapeRenderer.circle(circle.x, circle.y, circle.radius);
    
            shapeRenderer.end();
        }
    
        // *static* - Google the difference between inner vs nested classes
        public static class Circle {
            public float x;
            public float y;
            public float radius;
    
            public Circle(float x, float y, float radius) {
                this.x = x;
                this.y = y;
                this.radius = radius;
            }
        }
    }