[英]Java game 2D overlapping shadows with Swing
我目前正在使用Swing作为我的主要绘图组件开发2D Java游戏。 每个对象都有一个阴影(BufferedImage),但每个阴影都与其他阴影重叠。 是否可以只让阴影不相互重叠? 因为如果对象在它下面,我仍然希望阴影在玩家上方绘制,而不是如果对象在玩家之上。 为清晰起见,这是一张图片:
我看过alpha合成,我想我需要Source Out? 我还想过让所有阴影(没有透明度)在一个图层上绘制,然后用透明度绘制它,然后它不会像以前那样在玩家和其他对象上绘制。
我有一个Draw对象,它是一个JPanel并覆盖paintComponent方法。 在这个方法中,我绘制当前房间的地板,然后迭代属于当前房间的对象列表,并调用每个对象的绘制方法来绘制所有内容。
对象绘制方法:
public void draw(Graphics g) {
if (visible && checkInScreen()) {
// The required drawing location
int drawLocationX = getX() - globalCameraX;
int drawLocationY = getY() - globalCameraY;
if (shadow) {
g.drawImage(shadowImages.get(imageIndex),
drawLocationX + shadowOffset.x + (getImageWidth()/2),
drawLocationY + shadowOffset.y, null);
}
g.drawImage(images.get(imageIndex), drawLocationX, drawLocationY, null);
//Collisionbox
if (SHOW_COLLISION_BOXES){
g.setColor(Color.WHITE);
g.drawRect(drawLocationX + getCollBoxX(), drawLocationY + getCollBoxY(), getCollBoxW() - getCollBoxX(), getCollBoxH() - getCollBoxY());
}
}
}
如果这个问题已被提出,我很抱歉,但我找不到类似的东西。
我要做的就是有一个阴影层位图。 我的意思是:将阴影纹理保存为布尔值的二维数组(表示阴影像素的位置)。
你可以用它来做逻辑或阴影贴图一起创建一个单独的图层,可以在树纹理后面分层以创建阴影。
您可能希望将布尔值更改为浮点数以表示阴影的颜色/强度,然后使用更大的计算将阴影合并在一起。
下面的ShadowMap类用于存储每个阴影的数据:
class ShadowMap {
public int xPos, yPos;
public boolean[][] array;
public ShadowMap(int xPos, int yPos, boolean[][] array) {
this.xPos = xPos;
this.yPos = yPos;
this.array = array;
}
}
ShadowLayer类为整个屏幕创建一个2D数组,包含每个像素是否存在阴影:
class ShadowLayer {
public static boolean[][] array = new boolean[SCREEN_WIDTH][SCREEN_HEIGHT];
public static makeNew(ShadowMap[] shadows) {
for (int x = 0; x < SCREEN_WIDTH; x++) {
for (int y = 0; y < SCREEN_HEIGHT; y++) {
array[x][y] = false;
}
}
for (ShadowMap map : shadows) {
for (int i = 0; i < SCREEN_WIDTH; i++) {
for (int j = 0; j < SCREEN_HEIGHT; j++) {
// Logical or such that the pixel at (x, y) has a shadow
// if any shadow map also has a shadow at pixel (x, y)
array[i + map.xPos][j + map.yPos] |= map.array[i][j];
}
}
}
}
}
使用此ShadowLayer类,如果ShadowMap在同一像素上有阴影,则只需要使屏幕上的每个像素变暗:
public static Color ajustPixelForShadows(int x, int y, Color pixel) {
return ShadowMap.array[x][y] ? pixel.darken() : pixel;
}
我承认我不熟悉Swing所以我不确定这个特定界面是否可行,但下面的解决方案可以用于各种2D图形引擎。
你需要一个离屏的“阴影层”来绘制,以匹配屏幕尺寸。 将阴影层初始化为纯白色。
对于从后向前绘制的每个对象(y排序),按顺序执行以下阴影图层:
将对象的阴影形状以单一实心深灰色绘制到阴影层
将对象本身绘制为阴影图层作为纯白色精灵(即对象位图中的所有非透明像素均为白色)
当然,也将对象本身绘制到屏幕上。
然后,一旦所有对象都被绘制到屏幕和阴影层,使用多重混合将阴影层绘制到屏幕。 多重混合可确保阴影会使绘制的任何内容变暗(与alpha混合不同,非常轻的阴影可能会实际上减轻它们被绘制的颜色)。 它还会使图层的纯白色部分无效,这就是你想要的。
上述步骤意味着在每个对象绘制阴影之后,它会在最终场景中将其自身绘制为阴影层时擦除其下方的任何阴影。 因此,它不会在自身上投射阴影,并且对象不会将阴影投射到技术上位于其前面的其他对象上。
对象仍然可以根据需要将阴影投射到其后面的其他对象上,因为尚未被重叠对象擦除的阴影的任何部分仍将应用(或者如果它们被擦除,则可能会被重新绘制后来的对象)。 并且,由于您将阴影作为单个非半透明颜色绘制到阴影层,因此多个阴影重叠也不会相互影响,这当然是主要观点。
您可以根据可用的内容修改此技术。 例如,最初可以使用完全透明的阴影图层而不是白色,并使用“擦除”混合模式[(src * 0)+(dst *(1 - srcAlpha))]来绘制擦除阴影下方的阴影的对象。 如果您希望将阴影图层绘制到屏幕,则可以使用alpha而不是乘法混合。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.