为啥 LWJGL 仅在 Windows 上在以前和当前的游戏状态之间闪烁?

Posted

技术标签:

【中文标题】为啥 LWJGL 仅在 Windows 上在以前和当前的游戏状态之间闪烁?【英文标题】:Why is LWJGL is flickering between previous and current gameState on Windows only?为什么 LWJGL 仅在 Windows 上在以前和当前的游戏状态之间闪烁? 【发布时间】:2013-10-04 14:50:23 【问题描述】:

此问题仅发生在 Windows 中。在 Linux 中运行良好。

我有一个基于堆栈的状态管理系统。当我从一种状态切换到另一种状态时,显示屏会在前一个状态和当前状态之间闪烁。它几乎就像一个缓冲区仍在显示先前的状态并与当前状态交替。

这是我的第一个状态初始化、绘制和退出代码:

init 在状态首次加载时被调用

draw 在每个循环中被调用

pause 在新状态放入栈顶之前被调用。

    private void init()
    
    glEnable(GL_TEXTURE_2D);
    glShadeModel(GL_SMOOTH);       
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);                   

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);               
    glClearDepth(1);                                      


    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


    glViewport(0,0,Game.getGameConfig().getDisplayWidth(),Game.getGameConfig().getDisplayHeight());
    glMatrixMode(GL_MODELVIEW);


    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0,Game.getGameConfig().getDisplayWidth(), Game.getGameConfig().getDisplayHeight(), 0, 1, -1);
    glMatrixMode(GL_MODELVIEW);

public void draw() 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    titleFont.drawString((Game.getGameConfig().getDisplayWidth()/2)-(titleFont.getWidth(titleText)/2),
            (Game.getGameConfig().getDisplayHeight()/2) - (titleFont.getHeight()/2) ,
            titleText,Color.orange);

    if(showStartText)
    
        pressStartFont.drawString((Game.getGameConfig().getDisplayWidth()/2)-(pressStartFont.getWidth(pressStartText)/2),
                (Game.getGameConfig().getDisplayHeight()/2) - (titleFont.getHeight() - 100),
                pressStartText, Color.orange);
    


public void pause() 
    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);

这是下一个游戏状态代码:

private void init()

    glEnable(GL_TEXTURE_2D);
    glShadeModel(GL_SMOOTH);       
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);                   

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);               
    glClearDepth(1);                                      


    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
glViewport(0,0,Game.getGameConfig().getDisplayWidth(),Game.getGameConfig().getDisplayHeight    ());
        glMatrixMode(GL_MODELVIEW);


        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0,Game.getGameConfig().getDisplayWidth(),     Game.getGameConfig().getDisplayHeight(), 0, 1, -1);
        glMatrixMode(GL_MODELVIEW);

public void draw() 
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
    mainMenu.draw();
    Display.update();

    public void pause() 
    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);


这就是新状态的加载方式。

第一个状态调用:

super.sm.push(new MainMenu(super.sm));

这是 StateManager (sm) 代码:

public void push(GameState state)

    if(!states.empty())
    
        states.peek().pause();
    
    states.push(state);
    state.enter();

主游戏循环在 StateManager 上调用此方法:

public void draw()

    if(!states.empty())
    
        states.peek().draw();
    
    Display.update();

是什么导致在 Windows 上发生状态之间的闪烁?

【问题讨论】:

我怀疑我可能需要在交换状态时清除缓冲区。有没有办法做到这一点? 第一次切换状态后,可能每帧都会调用两个绘图函数? 我不这么认为。状态管理器非常可靠,我认为这不能解释为什么它在 Linux 上运行良好。 我的想法是在 Windows 上它同时调用两者,但只是以随机顺序。无论如何,我认为这里没有足够的信息来调试您的问题。 我添加了一些在切换期间被调用的状态管理器代码。 【参考方案1】:

在 StateManager Draw 方法和 gameState Draw 方法中都有一个 Display.update();。移除处于游戏状态的那个。

【讨论】:

以上是关于为啥 LWJGL 仅在 Windows 上在以前和当前的游戏状态之间闪烁?的主要内容,如果未能解决你的问题,请参考以下文章

仅在 Windows 10 中,Java Keyevent 不起作用..在 Windows 7 和 8 中它运行良好..我不知道为啥

为啥 gRPC 仅在 Windows 上每秒抛出“已建立的连接被主机中的软件中止”?

为啥 iframe 仅在 iOS 中为空白?

使用 OpenGL / LWJGL 绘制纹理四边形使用旧纹理

java 和 libGDX / LWJGL 游戏全屏尺寸错误,适用于 Ubuntu 上的多个显示器

csharp 在Windows 8.1和10上在cef中输入中文字符的解决方法