Java 将BuffereImage中的球形区域有效地设置为特定的不透明度

Java 将BuffereImage中的球形区域有效地设置为特定的不透明度,java,bufferedimage,isometric,Java,Bufferedimage,Isometric,首先,我搜索了谷歌,因此找到了这个答案,只找到了如何将实际像素更改为某个alpha值,这将是非常缓慢的,或者通过使用lwg2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR))使buffereImage的一部分完全透明。这正是我所需要的功能,但是,我需要使值小于1f,这是使用AlphaComposite.CLEAR的特定实例无法做到的 我希望此实现的目的是,当玩家走到2.5d游戏的后面时,使其内部的墙变得透明,如下所示:

首先,我搜索了谷歌,因此找到了这个答案,只找到了如何将实际像素更改为某个alpha值,这将是非常缓慢的,或者通过使用
lwg2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR))使
buffereImage
的一部分完全透明
。这正是我所需要的功能,但是,我需要使值小于
1f
,这是使用
AlphaComposite.CLEAR的特定实例无法做到的

我希望此实现的目的是,当玩家走到2.5d游戏的后面时,使其内部的墙变得透明,如下所示:

我的游戏背后的逻辑是,地形是一个
BufferedImage
,仅在调用时更新,然后将其余的墙等绘制到另一个
BufferedImage
上,其中也绘制了实体,因此不透明度变换只会影响树(或墙)

这是我使用atm的代码,但正如我所说的,我不希望我所画的圆圈使图像的一部分完全透明,但只是略微透明(大约50%):

(在
AlphaComposite
构造函数中的
0.5f
不起任何作用)


我之所以需要这样做是因为我每秒更新此图像30次,因此效率>质量。

因此,我最终解决了这个问题,没有通过使图像的一部分半透明来直接操纵图像,而是操纵正在绘制的图像的不透明度。正如@user343760和@nespowerglood所提到的,当玩家在我使用的资产后面时,我可以使其半透明。因为我使用了一个底层网格数组来支持我的游戏,所以我可以通过计算
tile.x-1==(int)player.x
tile.y-1==(int)player.y
来实现这一点。在等轴测中,这意味着在我们的视角中,玩家就在它正上方的瓷砖上。然后,如果墙.z大于0或1,我必须解决这个问题,因此出现了这样一个问题:如果墙在瓷砖上方延伸z=5,则玩家可能会阻止瓷砖5“咆哮”。针对此问题,我实施了以下解决方案:

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);                                            
    }
}
for(int i=0;i
这也确保了图像是透明的,即使玩家在墙所在的瓷砖“上方”瓷砖“上方”,就图像延伸超过该限制而言。我已经通过使用for循环解决了这个问题,该循环在上方查看
I
次数,具体取决于
image.height/tile\u height
,这是一个通用常量

如果您需要使图像的一部分透明,除了在
BufferedImage
的低级别中操作像素外,我还没有找到无故障的解决方案。如果您还想直接擦除图像的一部分,请使用code
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR))并按正常方式绘制。请记住通过
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER))切换回普通的组合

您还可以首先使用
Composite
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,opacity))以一定的不透明度进行绘制
,其中
opacity
是一个
float
,其值从
0f
1f
0f
是完全透明的,
1f
是完全不透明的

我希望这对任何人都有帮助。如果你找到更好的方法,请留下评论给未来的读者

我的解决方案是这样的:):


仅查找如何将实际像素更改为某个alpha值,这将非常缓慢
。也许您可以在启动时使用此方法来存储游戏中绘制的每个精灵的半透明版本,这样您就不会承受每帧的开销。@NESPowerGlove是的,我想过这样做,但假设我有一个瓷砖,其墙壁在坐标处延伸到z=10范围(player.x,player.y-10)?这意味着我必须在y轴上检查播放器下方的所有瓷砖,然后在特定的z轴上设置半透明图像(没有那么难,但仍然没有那么有效,因为考虑到每面墙都有自己的对象,我必须迭代很多瓷砖和墙)。这是一个很好的方法,但有它的限制,因为游戏有一个无限的z轴,因为它是等距的。谢谢。你可以为图形定义形状(球形)和设置剪辑(仅重新绘制所需区域),并用半透明颜色(例如白色)填充它。因为你有一个网格系统,所以实现起来更容易。使用栅格确定角色的“正面”平铺。使这些平铺上的BuffereImage半透明。当角色移动到某些瓷砖后面时,仅重新绘制这些瓷砖并使其半透明。当角色移出时,将其重新绘制为正常。通过在单缓冲区上设置alpha值来设置半透明图像的成本不会太高。@user3437460我最终就是这么做的,尽管由于对NESPowerGlove的评论回复中提到的原因,我不得不四处闯荡。我的fps确实受到了攻击,但我再次在rPi上运行它;)。
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);                                            
    }
}