繁体   English   中英

Java游戏2D重叠阴影与Swing

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM