我终于找到了做到这一点的方法。
我的游戏是如何设置的,每个项目都会自己绘制。他们得到了一个 spritebatch,可以用它做一些事情。我这样做是出于各种原因。有一个包含项目列表的项目管理器。每个项目都有不同的属性。每个项目都有自己的渲染方法以及其他独立的方法。这是最终奏效的方法:
不使用任何 alpha 掩码的普通项目的渲染方法:
public void render(SpriteBatch batch, int renderLayer) {
if(renderLayer == Integer.parseInt(render_layer)){ // be in the correct render layer
batch.draw(item.region,
item.position.x, // position.x
item.position.y, // position.y
0, //origin x
0, //origin y
item.region.getRegionWidth() , //w
item.region.getRegionHeight(), //h
item.t_scale, //scale x
item.t_scale, //scale y
item.manager.radiansToDegrees(item.rotation)); //angle
}
}
因此,它会收到一个 spritebatch,它使用正确的图像、位置、比例和旋转来绘制它,就是这样。
在玩了我在这里找到的东西之后:https ://gist.github.com/mattdesl/6076846一段时间,这终于适用于需要使用 alpha 遮罩的项目:
public void render(SpriteBatch batch, int renderLayer) {
if(renderLayer == Integer.parseInt(render_layer)){
batch.enableBlending();
//draw the alpha mask
drawAlphaMask(batch, item.position.x, item.position.y, item.region.getRegionWidth(), item.region.getRegionHeight());
//draw our foreground elements
drawForeground(batch, item.position.x, item.position.y, item.region.getRegionWidth(), item.region.getRegionHeight());
batch.disableBlending();
}
}
有一个名为 alphaMask 的 TextureRegion 包含一个黑色形状。它可以是任何图像,但在这种情况下,假设它的形状/图像:
这是上面调用的使用该图像的函数:
private void drawAlphaMask(SpriteBatch batch, float x, float y, float width, float height) {
//disable RGB color, only enable ALPHA to the frame buffer
Gdx.gl.glColorMask(false, false, false, true);
// Get these values so I can be sure I set them back to how it was
dst = batch.getBlendDstFunc();
src = batch.getBlendSrcFunc();
//change the blending function for our alpha map
batch.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ZERO);
//draw alpha mask sprite
batch.draw(alphaRegion,
x, // position.x
y, // position.y
0, // origin x
0, // origin y
alphaRegion.getRegionWidth(), // w
alphaRegion.getRegionHeight(), // h
item.t_scale, // scale x
item.t_scale, // scale y
item.manager.radiansToDegrees(item.rotation)); // angle
//flush the batch to the GPU
batch.flush();
}
有多种“材料”适用于任何形状。在任何情况下,其中之一都分配给 spriteRegion 变量。假设现在是这样的:
所以上面调用的 drawForeground 方法使用这样的图像:
private void drawForeground(SpriteBatch batch, float clipX, float clipY, float clipWidth, float clipHeight) {
//now that the buffer has our alpha, we simply draw the sprite with the mask applied
Gdx.gl.glColorMask(true, true, true, true);
batch.setBlendFunction(GL10.GL_DST_ALPHA, GL10.GL_ONE_MINUS_DST_ALPHA);
batch.draw(spriteRegion,
clipX, // corrected center position.x
clipY, // corrected center position.y
0, //origin x
0, //origin y
spriteRegion.getRegionWidth() , //w
spriteRegion.getRegionHeight(), //h
item.t_scale, //scale x
item.t_scale, //scale y
item.manager.radiansToDegrees(item.rotation)); //angle
//remember to flush before changing GL states again
batch.flush();
// set it back to however it was before
batch.setBlendFunction(src, dst);
}
这一切都在桌面构建中立即起作用,并且可以在游戏中很好地产生“砖梁”(或其他):
然而,在 Android 和 GWT 构建中(因为毕竟,我使用的是 libgdx),它没有包含 alpha 掩码,而是呈现了完整的砖方块。
经过大量环顾后,我发现了这一点:https ://github.com/libgdx/libgdx/wiki/Integrating-libgdx-and-the-device-camera
因此,为了在 Android 中解决这个问题,我修改了 MainActivity.java onCreate 方法,如下所示:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
cfg.useGL20 = false;
cfg.r = 8;
cfg.g = 8;
cfg.b = 8;
cfg.a = 8;
initialize(new SuperContraption("android"), cfg);
if (graphics.getView() instanceof SurfaceView) {
SurfaceView glView = (SurfaceView) graphics.getView();
// force alpha channel - I'm not sure we need this as the GL surface
// is already using alpha channel
glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
}
}
这为Android修复了它。
我仍然无法弄清楚如何让它在 gwt 中正常工作,因为我无法弄清楚如何告诉 libgdx 告诉 GWT 告诉 webGl 继续并注意 alpha 通道。我对如何以更简单或更便宜的方式做这样的事情很感兴趣(尽管这似乎工作正常)。
如果有人知道如何使用 GWT 进行这项工作,请作为另一个答案发布。
如果您想查看纹理问题,这里是非工作 GWT 构建:
https://supercontraption.com/assets/play/index.html