java - 如何使用 Slick2D 渲染最后一个字符字形的一部分

标签 java opengl lwjgl slick2d

我目前正在使用 Slick 在游戏中呈现自定义聊天。

我想要做的是,我希望能够为聊天创建自定义的“淡入淡出”效果,顺利从右向左逐渐消失。我不太擅长用文字解释事物,所以我将展示一个我想要的例子。

例子:

我想渲染文本 bernhardkiv: hello world! ,运行我的常规字体渲染器,结果如下:

enter image description here

而我希望能够做到的,就是将文字平滑的截断,如下;

enter image description here

我不知道该怎么做!我相信使用 glScissoring 可以做到这一点,但我一直在尝试使用它,但似乎没有任何效果(根本没有任何 react ,一切都保持不变)。

我会感谢任何人的帮助,我基本上希望能够,而不是在 x,y 处渲染,我希望能够在 x,y 处渲染,宽度为 string_width - smooth_cut,以便能够产生一点褪色效果。

最佳答案

免责声明:

  • 这对我来说是一个新领域,但由于似乎没有其他人在回答,我会尝试一下,因为这个问题对我来说似乎有点有趣。我还没有彻底测试这些代码修改,所以可能存在我不知道的错误/副作用。使用风险自负。 :-)
  • org.newdawn.slick.Font Slick2D 库中的实现类(和支持类)似乎不是扩展友好的(私有(private)成员和方法)。据我所知,为了达到预期的效果,需要对其中一些内部 Slick2D 类进行更改。 (替代方法是复制整个类和包。)据我从提问者的评论中了解到,Slick2D 源代码包含在提问者的项目中,因此在这种情况下对内部 Slick2D 类进行更改应该是可行的。
  • 可以说,出于某种原因,上述类不是对扩展友好的,并且可能有更好的方法来进行必要的更改以使其可扩展。如果有一个实际的项目和更多的时间,我什至可能会以不同的方式去做。 然而,这个答案的目的是向提问者展示我如何通过对内部 Slick2D 类的最小代码更改来达到预期效果的本质。 提问者可以自行决定如何将这些更改应用于他/她的项目的细节。

  • 此代码使用 Slick build 237。

    您可以在 github repo 查看完整的代码更改.下面我只展示了与实现所需淡入淡出效果最相关的代码更改。

    将每个字符想象成一个 GL_QUAD 中的四个角,每个角都有一个 RGBA 值(如 here 所述,这张图片来自哪里):
     (x,x,x,1)       (x,x,x,0)
         -----------------
         |               |
         |               |
         |               |
         |               |
         |               |
         |               |
         -----------------
      (x,x,x,1)      (x,x,x,0)
    

    我们正在做的是保持左上角和左下角的颜色不变,并将右上角和右下角的颜色更改为 alpha 为 0(透明)。 OpenGL会逐渐为我们淡化透明度。为此,我们扩展 org.newdawn.slick.Image创建 FadableImage使用以下方法(与 ImagedrawEmbedded 方法非常相似,但不会覆盖它):
    public class FadableImage extends Image {
    
       //.....
    
        public void drawEmbeddedFaded(float x,float y,float width,float height, Color color, float fadePercentWidth) {
            init();
    
            //if percent width is set to an invalid amount, default it to 1.
            if(fadePercentWidth < 0.0f || fadePercentWidth > 1.0f)
                fadePercentWidth = 1.0f;
    
            if (corners == null) {
                GL.glTexCoord2f(textureOffsetX, textureOffsetY);
                GL.glVertex3f(x, y, 0);
                GL.glTexCoord2f(textureOffsetX, textureOffsetY + textureHeight);
                GL.glVertex3f(x, y + height, 0);
    
                //set the color of x2 and y2 of the quad to 0 alpha
                GL.glColor4f(color.r, color.g, color.b, 0.0f);
                GL.glTexCoord2f(textureOffsetX + textureWidth*fadePercentWidth, textureOffsetY
                        + textureHeight);
                GL.glVertex3f(x + width*fadePercentWidth, y + height, 0);
                GL.glTexCoord2f(textureOffsetX + textureWidth*fadePercentWidth, textureOffsetY);
                GL.glVertex3f(x + width*fadePercentWidth, y, 0);
                //reset the color
                GL.glColor4f(color.r, color.g, color.b, color.a);
            } else {
                corners[TOP_LEFT].bind();
                GL.glTexCoord2f(textureOffsetX, textureOffsetY);
                GL.glVertex3f(x, y, 0);
                corners[BOTTOM_LEFT].bind();
                GL.glTexCoord2f(textureOffsetX, textureOffsetY + textureHeight);
                GL.glVertex3f(x, y + height, 0);
                //set the color of x2 and y2 of the quad to 0 alpha
                GL.glColor4f(color.r, color.g, color.b, 0.0f);
                //corners[BOTTOM_RIGHT].bind();
                GL.glTexCoord2f(textureOffsetX + textureWidth*fadePercentWidth, textureOffsetY
                        + textureHeight);
                GL.glVertex3f(x + width*fadePercentWidth, y + height, 0);
                //corners[TOP_RIGHT].bind();
                GL.glTexCoord2f(textureOffsetX + textureWidth*fadePercentWidth, textureOffsetY);
                GL.glVertex3f(x + width*fadePercentWidth, y, 0);
                //reset the color
                GL.glColor4f(color.r, color.g, color.b, color.a);
            }
        }
    
    }
    

    你可以看到diff我将要描述的内容。

    为了使用 FadableImage ,我们还需要扩展org.newdawn.slick.font.GlyphPage创建FadableGlyphPage .支持FadableGlyphPage我们需要修改org.newdawn.slick.font.GlyphPage的构造函数并添加一个新的。

    然后我们需要修改org.newdawn.slick.UnicodeFont使用我们的FadableGlyphPageUnicodeFont加载 loadGlyphs 中的字形.

    我们改UnicodeFontdrawDisplayList(...)方法来调用我们的FadableImage的特辑 drawEmbeddedFaded(...)给定字符串的指定结束索引处的字符的方法。我们还必须进行修改,以便 DisplayList缓存将被正确处理。

    我们在 UnicodeFont 中添加了一个方便的方法绘制一个字符串,其中 endIndex-1 处的字符褪色并绘制到由 fadePercentWidth 指定的宽度百分比:
    public void drawString(float x, float y, String text, int endIndex, float fadePercentWidth) {
        drawDisplayList(x, y, text, Color.white, 0, endIndex, fadePercentWidth);
    }
    

    所以这个想法是最后呈现的字符将是 endIndex-1 处的字符。渐变宽度百分比是将要绘制的包含 endIndex-1 字符的四边形的宽度百分比。因此,您可以使用该参数来微调您想要的效果( 0.0f1.0f )。渐变宽度百分比设置为 0.5f ,将绘制四边形总宽度的 50%。并且淡入淡出将达到 50% 的宽度:
     (x,x,x,1)       (x,x,x,0)
    
         ------------|------------
         |           |            |
         | drawn     | not        |
         |           |  drawn     |
         |           |            |
         |           |            |
         |           |            |
         ------------|------------
    
      (x,x,x,1)      (x,x,x,0)
    

    现在让我们用这段代码来测试它:
    import java.awt.Font;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    import org.newdawn.slick.AppGameContainer;
    import org.newdawn.slick.BasicGame;
    import org.newdawn.slick.Color;
    import org.newdawn.slick.GameContainer;
    import org.newdawn.slick.Graphics;
    import org.newdawn.slick.SlickException;
    import org.newdawn.slick.UnicodeFont;
    import org.newdawn.slick.font.effects.ColorEffect;
    
    public class TextFadeTest extends BasicGame {
    
        private final int Y_OFFSET = 50;
        private final org.newdawn.slick.Color bgColor =  new org.newdawn.slick.Color(126, 166, 240);
    
        private UnicodeFont unicodeFont;
    
        public TextFadeTest(String gamename) {
            super(gamename);
        }
    
        @Override
        public void init(GameContainer gc) throws SlickException {
            gc.setShowFPS(false);
            gc.getGraphics().setBackground(bgColor);
    
            Font awtFont = new Font(Font.SERIF, Font.PLAIN, 36);
            unicodeFont = new UnicodeFont(awtFont);
            unicodeFont.getEffects().add(new ColorEffect(java.awt.Color.WHITE));
            unicodeFont.addAsciiGlyphs();
            unicodeFont.loadGlyphs();
        }
    
        @Override
        public void update(GameContainer gc, int i) throws SlickException {}
    
        @Override
        public void render(GameContainer gc, Graphics g) throws SlickException {
    
            String str = "bernhardkiv: hello world!";
            int y = 0;
            unicodeFont.drawString(10, y, str);
            unicodeFont.drawString(10, y+=Y_OFFSET, str, Color.white, 0, 22);
            unicodeFont.drawString(10, y+=Y_OFFSET, str, 22, 0f);
            unicodeFont.drawString(10, y+=Y_OFFSET, str, 22, 0.10f);
            unicodeFont.drawString(10, y+=Y_OFFSET, str, 22, 0.25f);
            unicodeFont.drawString(10, y+=Y_OFFSET, str, 22, 0.50f);
            unicodeFont.drawString(10, y+=Y_OFFSET, str, 22, 0.75f);
            unicodeFont.drawString(10, y+=Y_OFFSET, str, 22, 0.90f);
            unicodeFont.drawString(10, y+=Y_OFFSET, str, 22, 1.0f);
    
        }
    
        public static void main(String[] args) {
            try {
                AppGameContainer appgc;
                appgc = new AppGameContainer(new TextFadeTest("TextFadeTest"));
                appgc.setDisplayMode(640, 480, false);
                appgc.start();
            }
            catch(SlickException ex) {
                Logger.getLogger(TextFadeTest.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    
    }
    

    这给出了这个结果:

    result

    关于java - 如何使用 Slick2D 渲染最后一个字符字形的一部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29200102/

    相关文章:

    java - Infinispan事务-无法从Spring4获取TransactionManager

    java - 针对异常的 Java 接口(interface)的正确设计

    c++ - 如何在 MacOS 上的 NodeJS native 插件上创建 OpenGL 上下文?

    OpenGL 转换(glScale、glTranslate 等)

    java - 如何绘制纹理并使用VBO?

    java - 避免在对 JButton 执行操作后卡住

    Java长时间运行程序递归导致的StackOverflowError

    java - JOGL 2.0 和过剩

    java - 使用 lwjgl 启用抗锯齿

    java - appgc.setResizable(true);错误