How to make 2 intersecting rectangles go transparent - java

My goal is to fill the screen with a black rect with an alpha of 128 so the screen looks dark, then make it so I can render rects to the screen and the place they are rendered to turns fully transparent so you can see right through that rect. I have made the screen get filled partially black but I cannot make it go transparent when I draw a rect on top of that. I have never used AlphaComposites but I assumed that I'm gonna have to use one of those to make this work. Anyone know how I could get this done?
private Color darknessColor = new Color(0,0,0,128), flashlightColor = new Color(255,255,255,128);
public void render(Graphics g) {
// Draws the darkness part of the screen.
Graphics2D g2 = (Graphics2D) g;
g2.setColor(darknessColor);
g2.fillRect(0, 0, handler.getWidth(), handler.getHeight());
g2.setColor(flashlightColor);
g2.setComposite(AlphaComposite.DstOut);
g2.fillRect(200, 200, 300, 200);
g2.dispose();
}

There is no way to "undraw" a rectangle which has already been drawn; if you've already painted over the scene behind the rectangle, then it's gone. The solution is to only draw the black shape where you want it; this means it is not simply a rectangle, but if the part you want to "cut out" is a rectangle, then you could achieve the effect you want by drawing four black rectangles, like so:
Hopefully it's straightforward how to compute the coordinates that these four rectangles should have.

Related

How to Rotate AWT rectangle in JAVA?

I am creating a small java 2D game and i want to know if there is any way to rotate AWT rectangle
AffineTransform origXform = g2d.getTransform();
AffineTransform newXform = (AffineTransform) origXform.clone();
newXform.rotate(angle, pivotX, pivotY); // pivotX ,pivotY is the starting
point of the hand image
g2d.setTransform(newXform);
Rectangle arm = new Rectangle(bowX + 5, bowY + 55, 60, 5);
g2d.drawImage(playerBowReadyImg, bowX, bowY, null); //hand image
on the above code i simply draw the hand image which rotates based on the mouse position, i also set the rectangle on the hand but the problem is rectangle is not rotating along with the hand image.
also i am not using rectangle for any drawing purpose but to detect the collision.
however using g2d.draw(arm); draws the rotated rectangle but it not actually rotate the rectangle it just draws the rotated one.
any suggestion is appreciated.
Ok my question is marked as duplicate so i tried the answers i find there but the code i get only rotate my rectangle for the draw purpose only.
Image to depict the problem
now to be more specific the arrow in the image can only detect the collision for the blue rectangle (the original position) instead of the red one (rotated rectangle).
again i don't want to actually draw the rectangle but want to detect the collision when the arrow collide with the rectangle.
See AffineTransform.createTransformedShape(Shape) which:
Returns a new Shape object defined by the geometry of the specified Shape after it has been transformed by this transform.

Drawing images to 4 different points

I have a quadrilateral drawn in Path2D, and I would like for there to be an image on it. More specifically, I am trying to draw an image of my choice to 4 different points on a quadrilateral. In my case, it is a parallelogram. I do not want the image to go over the paralellogram. A better way to see what I am trying to say is to see the screenshot below.
I would like the image to be transformed to fit the green area. Not clipped.
I want the image to be pinned over the green paralellogram. However. I do not want the image to go over into the blue paralellogram, or the white space foe that matter.
So far I have tried
Researching for a way to place images directly onto Path2D.Double() objects. No answer
Rotating the image to fit the paralellogram. Didnt work.
Using AffineTransform in java. Dont get it ;-;
Thanks. I am new to java so do try to be lenient?
One way is to:
create a separate BufferedImage.
Apply a transform to the new image.
Draw your image to that new image.
Use the Shape object for the green area as a clip on the main drawing area
Draw the transformed image onto the main drawing area.
It's been a while since I have done transformations. You may have to set the transformation first and then draw the image after. Transformation has to come first.
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.transform(AffineTransform.getShearInstance(1.0, 0));
g2.drawImage(image, 0, 0, this);
}
Here is a simple example of how transforms work. You will have to spend some time on figuring out what values you need to make it work or if you might need to manually create a transformation matrix yourself.

How to thicken a border of a shape

When I click on a shape, in order to show "selection", I want to call a method drawSelected that will repaint the shape to show that it's selected. Something like this: https://gyazo.com/6e115bdca55aaecd70ebada7e046475d with how the square portion gets thicker.
In order to do that I need a border which I was able to figure out how to do by doing this:
// Set paint to the random color
g2.setPaint(getColor());
g2.fill(rectangle);
// Set the border of shape to black
g2.setPaint(Color.black);
g2.draw(rectangle);
But now when I click on a rectangle, the method that shows selection uses translate still and I get this: https://gyazo.com/07857f6782c3a32dc90946e79736374d where only the top and left get thicker.
I know the bottom and right are being draws as well, its just since they are filled with another color they overlap the previous rectangle so you don't see it.
My question is, how do I change the thickness of a border to where instead of translating a shape, I can just redraw the shape with a thicker border to show selection?
As you stated, the best way is to redraw with a thicker border :
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(10));
g2.setPaint(Color.black);
g2.draw(rectangle);

Rotate rectangle on an Image Swing

I have an Image on a JPanel. I'm then drawing a rectangle on top of the image like this:
Graphics2D image = (Graphics2D) g;
image.drawRect(......);
//create image code here.
image.rotate(1.5);
image.drawImage(....);
Problem is that when I rotate the image image.rotate(1.5), the rectangles stay in the same place.
I've tried creating the rectangle before rotating the image and after rotating the image, but both times it fails.
Is there an easy way to make the rectangles also rotate along with the image?
Thanks.
One approach is to rotate the graphics context's affine transform, as shown in this example. In that way, all drawing will be rotated by the same amount.
You might want to try using Rectangle, an implementation of the Rectangle2D class, then use g2d.draw(rectangle). This might be able to get the rotation state from the Graphics2D object better.

paintComponent() leaving behind previously drawn images after repaint()

I have a JPanel which draws .png images. each image has 2 copies to signify whether or not it has been selected. One image is normal and one has a colored border to signify the selection has been made. (You can think of these images as simple shapes for the sake of argument)
Which version of the image is drawn is determined via MouseListeners. If the user selects image1, then image1 will display its highlighted version.
In general this is working, however upon repaint() the highlighted version of the image is left behind. Since the highlighted version is slightly larger than the normal version, you can see it sticking out behind the newly drawn normal image (overlapping).
I thought repaint() was supposed to completely dispose of the current drawings and start from scratch, this doesn't seem to be the case here. Below is the general idea, blackClicked is toggled inside a MouseListener.
So my question is how do I make repaint() get rid of its currently drawn images and start from scratch.
Also, if there is a simpler way to achieve all of this please let me know, making 2 copies of images is tedious work.
#Override
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
if(blackClicked)
g2.drawImage(blackSelected,0, 0, null);
else
g2.drawImage(black,0, 0, null);
g2.drawImage(green,0, 0, null);
}
how do I make repaint() get rid of its currently drawn images and start from scratch.
You mean, how to make repaint fill the component with it's background color before painting? How about adding
g2.setColor(getBackground());
g2.fillRect(0, 0, getWidth(), getHeight());
in top of paintComponent()?

Categories