Setting a spherical area in a BufferedImage to a specific opacity

first of all, I counted Google and SO for this answer, only finding how to change actual pixels with a specific alpha value, which would be incredibly slow, or actually make a part BufferedImage

completely transparent through use lwg2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR))

. This is the exact functionality I need, however I need the value to be less 1f

, which you cannot do with this particular instance AlphaComposite.CLEAR

.

I want this implementation to make the wall inside my 2.5d game transparent when the player walks behind it, like so: example

The logic of my game is that the terrain is one BufferedImage

that only updates when called, and then contains the rest of the walls, etc., is drawn onto another BufferedImage

where objects are drawn as well, so the opacity transformation will only affect trees (or walls) ...

This is the code I'm using atm, but as I said, I don't need the circle that I draw to make part of the image completely transparent, but only slightly (about 50%):

g2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.5f));
g2.fillOval(x - (int) (TILE_WIDTH * 1), y - (int) (TILE_HEIGHT * 1.5), TILE_WIDTH * 2, TILE_HEIGHT * 3);

      

( does nothing 0.5f

in the constructor AlphaComposite

).

The reason I need this to be efficient is because I am updating this image 30 times per second, so efficiency> quality.

+3


source to share


1 answer


So, I solved the problem by not manipulating the image directly, making part of the image semi-transparent, but manipulating the opacity of the images I'm drawing with. As @ user343760 and @NESPowerGlove mentioned, I could just make the assets I use semi-transparent when the player is behind it. Since I am using a base lattice array to support my game, I could do this by working if tile.x - 1 == (int) player.x

and tile.y - 1== (int) player.y

. In isometric view, this meant that the player was on the tile directly above him in our perspective. Then I had to solve the problem if wall.z is greater than 0 or 1, so there is a problem when tile 5 blocks "below", the player can hide it if the walls increased by z = 5 above the slab. For this problem, I have implemented the following solution:

for(int i = 0; i < wall.getAsset(1f).getHeight()/TILE_HEIGHT; i++) {
    if((tile.x - i - wall.z == (int) world.player.getX() && tile.y - i -wall.z == (int) world.player.getY())) {
        lwg2.drawImage(wall.getAsset(0.5f), x, y, this);                                            
    }
}

      

This also ensures that the image is transparent even if the player is "above" the tile "above" the tile where the wall is, in terms of the image extending above that limit. I fixed this with a for loop that looks like above for the i

number of times, depending on image.height/tile_height

, which is a generic constant.

If you need to make part of an image transparent, I have not found a solution that works without glitches, other than manipulating pixels at low levels BufferedImage

. If you also want to remove part of the image directly, use the code g2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));

and draw as usual. Don't forget to return to your normal composition in g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));

.



You can also paint with a certain opacity, using Composite

g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity));

, where opacity

- is float

with values of 0f

up to 1f

, 0f

completely transparent and 1f

is completely opaque.

I hope this has helped anyone. If you find a better way to do this, please leave a comment for future readers.

This is my solution looks like this :):

working example

0


source







All Articles