I am attempting to create the functionality for a basic security camera in my game. The camera sits in the top right corner of the canvas, and displays a beam of light which rotates similar to a security camera (moves 90° in one direction, then 90° back). The functionality I am aiming for is that when the mouse is touching the beam, the console outputs "touching".
So far, I have the camera beam rotating using g2d.rotate, however the hit-detection does not move with the rotated canvas. I have tried a multitude of solutions, including the theorem used to move points of a polygon around one point, but the triangle kept decreasing in size with each rotation.
Here is my code so far:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Camera {
private BufferedImage img;
private int x;
private int y;
private boolean moving = false;
private double angle;
private boolean up;
private Graphics2D graphicsTemp;
private AffineTransform at;
private Polygon beam;
private Point p1;
private Point p2;
private Point p3;
private int[] xArray;
private int[] yArray;
public Camera(int x, int y, Point p1, Point p2, Point p3) {
try {
img = ImageIO.read(getClass().getResource("Camera.png"));
} catch (IOException e) {
System.out.println("NO IMAGE");
}
this.x = x;
this.y = y;
this.p1 = p1;
this.p2 = p2;
this.p3 = p3;
angle = 0;
up = true;
}
public void update() {
xArray = new int[] { p1.x, p2.x, p3.x };
yArray = new int[] { p1.y, p2.y, p3.y };
beam = new Polygon(xArray, yArray, 3);
}
public void paint(Graphics2D g2d) {
if (up) {
angle += 0.2;
} else {
angle -= 0.2;
}
if (angle >= 90.0 || angle <= 0.0) {
up = !up;
}
g2d.rotate(Math.toRadians(angle), p1.x, p1.y);
g2d.setColor(color);
g2d.fillPolygon(beam);
g2d.setColor(Color.BLACK);
g2d.drawPolygon(beam);
g2d.rotate(-Math.toRadians(angle), p1.x, p1.y);
}
public void testTouch(int mouseX, int mouseY) {
if (beam.contains(mouseX, mouseY)) {
System.out.println("INSIDE");
} else {
System.out.println("OUTSIDE");
}
}
You haven't rotated the Polygon that you're doing hit testing on, so it will use the original unrotated beam for hit testing.
As a simple solution, you can rotate the polygon before you use it for hit testing. Graphics2D
uses the AffineTransform class to do its rotations, and so can you:
public void testTouch(int mouseX, int mouseY) {
AffineTransform transform = AffineTransform.getRotateInstance(Math.toRadians(angle), p1.x, p1.y);
Shape rotatedBeam = transform.createTransformedShape(beam);
if (rotatedBeam.contains(mouseX, mouseY)) {
However you can also draw that rotated polygon directly in your paint
method; it's better to rotate it once and use the rotated shape both for hit-testing and your paint method.
Note that it's also not a good idea to update your angle in the paint
method since you don't know when and how often it is called. If your window was overlapped and then uncovered, your paint method will also be called.