Slick2D使用FadeOutTransition切换GameState的分块渲染异常问题
问题根源
Slick2D内置的FadeOutTransition实现逻辑是在状态切换的渲染阶段,向当前屏幕绘制一个和窗口等大的半透明黑色覆盖层,通过逐步提升透明度实现淡出效果。当前代码的核心问题是转场渲染时Graphics上下文存在未复位的变换偏移:
- 自定义render方法中执行了相机平移
g.translate(-camera.getX(), -camera.getY()),而转场效果的渲染是在State的render方法执行完成后才触发的,此时残留的平移变换会导致转场的全屏覆盖层被偏移,只能覆盖部分屏幕区域,呈现分块淡出的效果 - 当前使用的
g.translate(camera.getX(), camera.getY())手动复位方式,受浮点精度误差、其他额外变换(如缩放、旋转)的影响,无法100%保证回到初始矩阵状态,会进一步加剧偏移问题
解决方案
方案1:使用Graphics矩阵栈管理相机变换(最稳妥)
将自定义渲染的变换操作包裹在矩阵入栈、出栈逻辑中,渲染完成后直接恢复到初始矩阵状态,完全避免变换残留:
public void render(GameContainer gameContainer, StateBasedGame stateBasedGame, Graphics g) throws SlickException { // 保存当前初始矩阵状态 g.pushTransform(); g.translate(-camera.getX(), -camera.getY()); // 所有自定义游戏内容渲染逻辑放这里 // stuff to render // 直接恢复到之前保存的初始矩阵状态,比手动反向平移更可靠 g.popTransform(); }
该方案同时可以避免UI绘制、调试信息输出等其他依赖全局屏幕坐标的渲染逻辑出现坐标偏移问题。
方案2:转场触发前强制重置变换
如果不想修改现有渲染逻辑,也可以在触发状态切换前,直接重置Graphics上下文的所有变换:
public void update(GameContainer gameContainer, StateBasedGame stateBasedGame, int delta) throws SlickException { if (gameContainer.getInput().isKeyPressed(Input.KEY_ENTER)) { // 重置上下文变换,保证转场效果基于原始屏幕坐标渲染 gameContainer.getGraphics().resetTransform(); stateBasedGame.enterState(1, new FadeOutTransition(), new FadeInTransition()); } }
内容的提问来源于stack exchange,提问作者Cec
相关产品推荐
相关产品推荐

