Search code examples
javalibgdx

LibGDX: Sprite.setBounds doesn't work correctly with volatile coordinates and InputAdapter


Faced a problem while trying to handle clicking on a moving image.

I used InputAdapter.touchDown() to handle the click and created Sprite for the image. Then I set the borders through Sprite.setBounds(). Further, in fact, the problem: if the coordinates in setBounds() are unchanged - the click is handled correctly. But if you change them (position.x++, for example) - the object comes into motion, but clicks are not read.

I can’t understand where the reason.

I tried to make a alterable variable outside the method, but this also didn't bring any result. I tried using batch.draw(img) instead of img.draw(batch) - the effect is the same. I tried to relocate Gdx.input.setInputProcessor() to the render() method, after img.setBounds() - nothing changed.

I even compared the coordinates of the Img and the Bounds area online, in motion - they are the same, as it should be.

Img and handler in constructor:

    img = new Sprite(new Texture(finSize));
    centerX = Gdx.graphics.getWidth()/2-img.getWidth()/2;
    centerY = Gdx.graphics.getHeight()/2-img.getHeight()/2;
    startPosition = new Vector2(centerX, centerY);

    Gdx.input.setInputProcessor(new InputAdapter(){
        @Override
        public boolean touchDown(int screenX, int screenY, int pointer, int button) {
            if(img.getBoundingRectangle().contains(screenX, screenY))
                System.out.println("Image Clicked");
            return true;
        }
    });

Render:

public void render(SpriteBatch batch, float radius, float boost) {
    speed+=boost;
    nextX = radius * (float) Math.cos(speed); // Offset step X
    nextY = radius * (float) Math.sin(speed); // Offset step Y

    // Img is moving, but clicks is not handling
    img.setBounds(startPosition.x+ nextX, startPosition.y + nextY, 100, 100);
    // Handling clicks fine, but img is motionless
    img.setBounds(startPosition.x, startPosition.y, 100, 100);

    img.draw(batch);

    // Checking coordinates - all's fine
    System.out.println(img.getBoundingRectangle().getX());
    System.out.println(startPosition.x + nextX);
    System.out.println(img.getBoundingRectangle().getY());
    System.out.println(startPosition.y + nextY);
}

Solution

  • So, I sequentially compared the XY coordinates of the image and the mouse click point and came to the conclusion that InputAdaper and Sprite consider Y differently - from above and from below. Therefore, X always coincided, and Y had a big difference in values.

    As a result, I entered two corrected coordinates xPos \ yPos (Y subtracted from the total field height) for the center of the pic and in the touchDown() method, instead of comparing with BoundRectangle, simply compared the difference in the coordinates of the pic and the click modulo. If the result into the image size range - everything is ok.

    Now clicks on the moving image works correctly.

       public void render(SpriteBatch batch, float radius, float boost) {
        speed+=boost; // rotational speed
        nextX = radius * (float) Math.cos(speed); // Offset step X
        nextY = radius * (float) Math.sin(speed); // Offset step Y
    
        // set image size and position
        img.setBounds(startPosition.x+nextX, startPosition.y+nextY, 100, 100);
        img.draw(batch);
    
        // Corrected coordinates of the image for InputAdapter coordinate system
        xPos = img.getX()+img.getWidth()/2;
        yPos = Gdx.graphics.getHeight()-img.getY()- img.getHeight()/2;
    
        // Check the coincidence of the coordinates of the image area and the click point
        Gdx.input.setInputProcessor(new InputAdapter(){
            @Override
            public boolean touchDown(int screenX, int screenY, int pointer, int button) {
                if((Math.abs(xPos-screenX)<=img.getWidth()) && (Math.abs(yPos-screenY)<=img.getHeight()))
                {System.out.println("Image Clicked");}
                return true;
            }
        });
    }