libgdx/android: actor 上台后变黑
libgdx/android: actor becomes black after added to stage
在某些特定情况下,演员被添加到舞台后会变成黑色表面,而不是实际纹理。在其他情况下,我可以在开始时加载演员,然后将其设置为不可见,当我需要它时,我可以将其设置为可见。但我不想那样做。
所以这是 render() 的代码:
public void render() {
Gdx.gl.glClearColor(backgroundColour.r, backgroundColour.g, backgroundColour.b,
backgroundColour.a);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
stage.act();
stage.draw();
}
以及我尝试将图像添加到舞台的地方
cardImage.setPosition(x, y);
cardImage.setWidth(ViewConstants.scalingWidthCard * ViewConstants.widthOneSpace);
cardImage.setHeight(ViewConstants.scalingHeightCard * ViewConstants.heightOneSpace);
stage.addActor(cardImage);
其中 cardImage 属于 class ImageWrapper
(ImageWrapper 扩展了 Image 并仅包含更多字段,方法不是 overwritten/changed)。这是我如何加载纹理的代码:
private ImageWrapper loadActorForCardAndSaveInMap(Card card) {
String textureString = loader.getCardTextureName(card);
ImageWrapper textureForCard = loader.getImageForPath("cards/" + textureString + ".png");
// irrelevant for libgdx, but I'll post it, so you see what happens
faceUpCards.put(textureString, textureForCard);
return textureForCard;
}
[...]
private ImageWrapper getImageForPath(String path) {
try {
return new ImageWrapper(new Texture(Gdx.files.internal(path)));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
大多数情况下一切正常,但并非全部。
我还尝试用
重新加载舞台
Group root = stage.getRoot();
stage.clear();
stage.setRoot(root);
如指定的那样here。但这并不能解决问题。
与渲染线程同步
因此,由于 render()
调用实际上与 GL 上下文同步,因此将其用作入口点。
1) 在某处定义一个task-list
private ArrayList<Runnable> synchronizedTasks = new ArrayList<>();
2) 将渲染循环中的同步调用添加到您的任务中
public void render() {
runSyncTasks();
// other draw code
}
private void runSyncTasks(){
synchronized(synchronizedTasks){
for(Runnable r : synchronizedTasks){
r.run();
}
synchronizedTasks.clear();
}
}
3) 当你想加载你的图像时(例如在用户输入时),提交任务如下:
synchronized(synchronizedTasks){
synchronizedTasks.add(new Runnable(){
@Override
public void run(){
... loadActorForCardAndSaveInMap(...)
}
});
}
这会将 Runnable
添加到列表中,它将在 GL 线程的下一个 render()
遍中执行。请记住,您需要在 run(){}
方法中执行涉及创建的 ImageWrapper
对象的任何操作。
编辑
或者实际上,您可以通过 Gdx.app.postRunnable(new Runnable()...);
提交您的 Runnable
而无需自定义同步器。 Gdx 调用做完全相同的事情。
在某些特定情况下,演员被添加到舞台后会变成黑色表面,而不是实际纹理。在其他情况下,我可以在开始时加载演员,然后将其设置为不可见,当我需要它时,我可以将其设置为可见。但我不想那样做。
所以这是 render() 的代码:
public void render() {
Gdx.gl.glClearColor(backgroundColour.r, backgroundColour.g, backgroundColour.b,
backgroundColour.a);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
stage.act();
stage.draw();
}
以及我尝试将图像添加到舞台的地方
cardImage.setPosition(x, y);
cardImage.setWidth(ViewConstants.scalingWidthCard * ViewConstants.widthOneSpace);
cardImage.setHeight(ViewConstants.scalingHeightCard * ViewConstants.heightOneSpace);
stage.addActor(cardImage);
其中 cardImage 属于 class ImageWrapper
(ImageWrapper 扩展了 Image 并仅包含更多字段,方法不是 overwritten/changed)。这是我如何加载纹理的代码:
private ImageWrapper loadActorForCardAndSaveInMap(Card card) {
String textureString = loader.getCardTextureName(card);
ImageWrapper textureForCard = loader.getImageForPath("cards/" + textureString + ".png");
// irrelevant for libgdx, but I'll post it, so you see what happens
faceUpCards.put(textureString, textureForCard);
return textureForCard;
}
[...]
private ImageWrapper getImageForPath(String path) {
try {
return new ImageWrapper(new Texture(Gdx.files.internal(path)));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
大多数情况下一切正常,但并非全部。
我还尝试用
重新加载舞台Group root = stage.getRoot();
stage.clear();
stage.setRoot(root);
如指定的那样here。但这并不能解决问题。
与渲染线程同步
因此,由于 render()
调用实际上与 GL 上下文同步,因此将其用作入口点。
1) 在某处定义一个task-list
private ArrayList<Runnable> synchronizedTasks = new ArrayList<>();
2) 将渲染循环中的同步调用添加到您的任务中
public void render() {
runSyncTasks();
// other draw code
}
private void runSyncTasks(){
synchronized(synchronizedTasks){
for(Runnable r : synchronizedTasks){
r.run();
}
synchronizedTasks.clear();
}
}
3) 当你想加载你的图像时(例如在用户输入时),提交任务如下:
synchronized(synchronizedTasks){
synchronizedTasks.add(new Runnable(){
@Override
public void run(){
... loadActorForCardAndSaveInMap(...)
}
});
}
这会将 Runnable
添加到列表中,它将在 GL 线程的下一个 render()
遍中执行。请记住,您需要在 run(){}
方法中执行涉及创建的 ImageWrapper
对象的任何操作。
编辑
或者实际上,您可以通过 Gdx.app.postRunnable(new Runnable()...);
提交您的 Runnable
而无需自定义同步器。 Gdx 调用做完全相同的事情。