【问题标题】:libgdx non continous renderinglibgdx 非连续渲染
【发布时间】:2019-06-28 09:30:31
【问题描述】:

根据文档 (https://github.com/libgdx/libgdx/wiki/Continuous-&-non-continuous-rendering),应该可以限制进行的渲染调用。但是,每次我移动鼠标时,仍然会调用渲染方法。我想知道是否可以将渲染限制为仅在发生某些 action 时才进行(或按需添加必要的 requestRendering )。

在下面的示例中,我将连续渲染设置为 false,并在舞台上调用 setActionsRequestRendering 将其设置为 false。


public class TestApp extends ApplicationAdapter {

    private Stage stage;

    private Drawable createDrawable(Color color) {

        Pixmap labelColor = new Pixmap(100, 100, Pixmap.Format.RGB888);
        labelColor.setColor(color);
        labelColor.fill();

        return new TextureRegionDrawable(new Texture(labelColor));
    }

    @Override
    public void create() {      

        Gdx.graphics.setContinuousRendering(false);

        stage = new Stage();
        stage.setActionsRequestRendering(false);

        Gdx.input.setInputProcessor(stage);

        Drawable imageUp = createDrawable(Color.WHITE);
        Drawable imageOver = createDrawable(Color.RED);

        ImageButtonStyle style = new ImageButtonStyle();
        style.imageUp = imageUp;
        style.imageOver = imageOver;

        ImageButton button = new ImageButton(style);
        button.setSize(100, 100);
        button.setPosition(50, 50);

        stage.addActor(button);
    }

    @Override
    public void render() {

        System.out.println("render");

        Gdx.gl.glClearColor(0f, 0f, 0f, 1.f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);

        stage.act();
        stage.draw();
    }

    @Override
    public void dispose () {
        stage.dispose();
    }

    public static void main (String[] arg) {

        LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();

        config.fullscreen = false;
        config.width = 200;
        config.height = 200;

        new LwjglApplication(new TestApp(), config);
    }
}

根据文档:

如果连续渲染设置为 false,render() 方法将 仅在以下情况发生时调用。

  • 触发了输入事件
  • Gdx.graphics.requestRendering() 被调用
  • Gdx.app.postRunnable() 被调用

我假设移动鼠标算作输入事件。


我希望仅在按钮实际需要更改其渲染状态(按钮向上/按钮上方)时才调用渲染方法。如果那不可能,至少当鼠标位置不是hitting 按钮时不应该调用渲染。

【问题讨论】:

  • Gdx.input.setInputProcessor(stage); 应该在 create() 方法中而不是在 render() 方法中。 super.render() 没用,因为 ApplicationAdapter.render() 什么都不做
  • @Morchul:感谢您的提示,我根据您的建议清理了示例。
  • 我认为这不可能是你想要的。因为每次移动鼠标时如果不调用 render() 就无法检测到悬停
  • 是的,如果没有获得鼠标位置输入事件,它无法计算箭头何时在按钮上方。

标签: java libgdx


【解决方案1】:

我认为这不可能是你想要的。因为每次移动鼠标时如果不调用 render() 方法,就无法检测到悬停。

如果你看到按钮没有点击,你可以做的是在渲染之前退出 render() 方法:

@Override
public void render() {
    stage.act();

    if(!button.isOver()){
        return;
    }

    System.out.println("Render");

    Gdx.gl.glClearColor(0f, 0f, 0f, 1.f);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);


    stage.draw();
}

【讨论】:

  • 仅使用 button.isOver() 是不够的。但是您要说的是,我需要记住所有changable(受鼠标位置影响)组件及其状态。如果其中一个发生变化(由于 stage.act() 调用而起作用,如果我理解正确的话),那么我会重新绘制舞台。我曾希望有一个内置机制可以让我这样做......
  • @second 是的,您必须记住所有可更改(受鼠标位置影响)的组件及其状态,因此如果您有五个按钮,则必须检查所有这些按钮,如果有一个悬停或击中,则重新绘制舞台.这可能不是最好的方式,但目前我看不到其他方式
  • 请记住,这仍然使用 GPU 作为框架。 LibGDX 是双缓冲的,所以如果你什么都不画,它会将一个帧缓冲区的内容复制到另一个帧缓冲区。不过,在大多数情况下,这在 GPU 上要比绘制一堆三角形要容易得多。
  • 我用一个例子更新了我的问题,以便在按钮状态发生变化时收到通知,但是即使没有调用 stage#draw,似乎仍然有一些正在进行的显示重绘?跨度>
  • @Tenfour04 .. 我添加了一个counter 来对抗双缓冲。看起来有点难看,但有效。我会暂时搁置这个问题,也许有人有更好的主意。
【解决方案2】:

根据@Morchul的建议,我试试记忆状态。
感谢@Tenfour04 指出双缓冲。

我在create方法中添加了一个InputListener:
(更改为新的全局变量/默认值:true)
(count 是另一个全局变量/默认值:0)

button.addListener(new InputListener() {

    public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
        changed = true;
        count = 0;
    }

    public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
        changed = true;
        count = 0;
    }
});

并改变了draw方法的开始

stage.act();

if (changed == false) {
    return;
} else if (++count == 2) {
    changed = false;
}

【讨论】: