How can I detect a click on a rotated image in Slick2D?
Asked Answered
L

1

6

I have an image that I rotate before I draw. The image is rotated by the angles of a hexagon. In other words, the image basically "highlights" the individual edges of a hexagon. I need to detect if the mouse was clicked inside of this rotated image. Detecting a mouse click inside of an unrotated image is pretty simple, but I have no idea about how to detect clicks within rotated points. Is there a way to get the points of the image's corners after rotation so I can place an invisible polygon on top of the image and use Polygon.contains()?

                    Image highlightEdge = new Image("assets/img/highlightEdge.png");
                    if(angle == 90){
                        highlightEdge.setCenterOfRotation(highlightEdge.getWidth(), 0);
                        highlightEdge.rotate(new Float(angle));
                        highlightEdge.draw(testPoint.x - 56, testPoint.y);
                    } else if(angle == 210) {
                        highlightEdge.setCenterOfRotation(0, 0);
                        highlightEdge.rotate(new Float(angle));
                        highlightEdge.draw(lastSettlement.x - 72, lastSettlement.y - 32);
                    } else if( angle == 330){
                        highlightEdge.setCenterOfRotation(0, 0);
                        highlightEdge.rotate(new Float(angle));
                        highlightEdge.draw(lastSettlement.x - 8, lastSettlement.y - 32);
                    } else if(angle == 30){
                        highlightEdge.setCenterOfRotation(0, 0);
                        highlightEdge.rotate(new Float(angle));
                        highlightEdge.draw(lastSettlement.x-8, lastSettlement.y);
                    } else if(angle == 150){
                        highlightEdge.setCenterOfRotation(0, 0);
                        highlightEdge.rotate(new Float(angle));
                        highlightEdge.draw(lastSettlement.x-72, lastSettlement.y);
                    } else {
                        highlightEdge.setCenterOfRotation(0, 0);
                        highlightEdge.rotate(new Float(angle));
                        highlightEdge.draw(lastSettlement.x-40, lastSettlement.y - 48);
                    }
Lorenzoloresz answered 5/3, 2017 at 16:13 Comment(0)
G
0

You could create a Shape to exactly match the shape of the Image, and then use its method contains to detect if the mouse was clicked inside.

To take in consideration the rotation of the Image you could apply a corresponding rotation Transform to the Shape.

I created the method shapeFromImage that does this; it receives an Image and its position and returns the corresponding Shape:

/**
 * Returns the Shape of an Image considering its rotation
 * @param image
 * @param x the x position of the Image
 * @param y the y position of the Image
 */
public static Shape shapeFromImage(Image image, float x, float y) {

    // create a rectangle with same position and size of the image
    Shape imageShape = new Rectangle(x, y, image.getWidth(), image.getHeight());

    // get the rotation angle of the image
    float angle = image.getRotation();

    // if the image is rotated, we also need to rotate our shape 
    if (angle != 0.f) {

        // convert the rotation angle in radians to use in Transform 
        float angleInRadians = (float) Math.toRadians(angle);

        // get the point of rotation to use in Transform.
        // image.getCenterOfRotation returns a point relative to the image.
        // for Transform we need an absolute point, so we add the image position to it
        float rotationX = image.getCenterOfRotationX() + x;
        float rotationY = image.getCenterOfRotationY() + y;

        // create the rotation Transform to match the image rotation
        Transform rotationTransform = Transform.createRotateTransform(angleInRadians, rotationX, rotationY);

        // apply the rotation Transform to our shape
        imageShape = imageShape.transform(rotationTransform);

    }

    return imageShape;
}

In your example you could use it like this:

float positionX;
float positionY;

if (angle == 90) {
    highlightEdge.setCenterOfRotation(highlightEdge.getWidth(), 0);
    highlightEdge.rotate(new Float(angle));

    positionX = testPoint.x - 56;
    positionY = testPoint.y;

    highlightEdge.draw(positionX, positionY);
} 

...

// you can now use this Shape to use its method "contains"
imageShape = shapeFromImage(highlightEdge, positionX, positionY);
Gensmer answered 9/3, 2017 at 19:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.