【问题标题】:LWJGL and Texture Loading - Seems to create a new object at every frameLWJGL 和纹理加载 - 似乎在每一帧创建一个新对象
【发布时间】:2013-11-07 19:27:57
【问题描述】:

所以我刚刚开始使用 LWJGL,我正在尝试创建一个简单的 2D 平台游戏。我目前争论的问题是纹理加载。问题是,只要我将所有与纹理加载相关的方法都保留在 main 方法的类中,一切都可以正常工作。

只要我将它移到一个单独的类 TextureHandler 中,它就不会工作,除非我将 loadTexture() 方法添加到 drawTexture() 方法中。那么问题是,据我所知,它每帧都会不断地制作新对象。我已经用 Google 搜索了几个小时,但终生无法找到解决方案。

主类:

public class Main {
    String playerPath = "res/PlayerNeutral.png";

    public void render() {
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
    }

    public void initGL() {
        try {
            Display.setDisplayMode(new DisplayMode(800, 600));
            Display.create();
            Display.setVSyncEnabled(true);
        }
        catch (LWJGLException e) {
            e.printStackTrace();

            System.exit(0);
        }

        // Initiating OpenGL
        GL11.glViewport(0, 0, 800, 600);
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glEnable(GL11.GL_TEXTURE_2D);

        GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

        // Enables the Alpha Blending
        GL11.glEnable(GL11.GL_BLEND);
        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

        GL11.glMatrixMode(GL11.GL_MODELVIEW);

        GL11.glOrtho(0, 800, 0, 600, 1, -1);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
    }

    public void start() {
        initGL();

        TextureHandler.loadTexture(Player.playerText, playerPath);

        while (!Display.isCloseRequested()) {
            render();
            TextureHandler.drawTexture(Player.playerText, playerPath);          
            Display.update();
        }

        Display.destroy();      
    }

    public static void main(String[] args) {
        Main test = new Main();
        test.start();
    }

TextureHandler 类:

public class TextureHandler {
    public static void textRelease(Texture text){
        text.release();
    }

    public static void loadTexture(Texture texture, String path){
        try {
            texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream(path));

            System.out.println("Texture loaded: "+texture);
            System.out.println(">> Image width: "+texture.getImageWidth());
            System.out.println(">> Image height: "+texture.getImageHeight());
            System.out.println(">> Texture width: "+texture.getTextureWidth());
            System.out.println(">> Texture height: "+texture.getTextureHeight());
            System.out.println(">> Texture ID: "+texture.getTextureID());

            TextureImpl.unbind();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void drawTexture(Texture texture, String path) {
        try {
            texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream(path));

            System.out.println("Texture loaded: "+texture);
            System.out.println(">> Image width: "+texture.getImageWidth());
            System.out.println(">> Image height: "+texture.getImageHeight());
            System.out.println(">> Texture width: "+texture.getTextureWidth());
            System.out.println(">> Texture height: "+texture.getTextureHeight());
            System.out.println(">> Texture ID: "+texture.getTextureID());
        } catch (IOException e) {
            e.printStackTrace();
        }

        Color.white.bind();
        texture.bind();

        GL11.glBegin(GL11.GL_QUADS);
            GL11.glTexCoord2f(0, 1);
            GL11.glVertex2f(100, 100);
            GL11.glTexCoord2f(1, 1);
            GL11.glVertex2f(100+texture.getTextureWidth(), 100);
            GL11.glTexCoord2f(1, 0);
            GL11.glVertex2f(100+texture.getTextureWidth(), 100+texture.getTextureHeight());
            GL11.glTexCoord2f(0, 0);
            GL11.glVertex2f(100, 100 + texture.getTextureHeight());
        GL11.glEnd();

        texture.release();
    }
}

播放器类:

public class Player {
    private int x;//x pos on screen
    private int y;//y pos on screen
    public static Texture playerText;

    // method for moving the player object around
    public void move() {
        if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT))
            x++;
        if (Keyboard.isKeyDown(Keyboard.KEY_LEFT))
            x--;
        if (Keyboard.isKeyDown(Keyboard.KEY_UP))
            y++;
        if (Keyboard.isKeyDown(Keyboard.KEY_DOWN))
            y--;
    }
}

【问题讨论】:

    标签: textures lwjgl


    【解决方案1】:

    那是因为在您的 drawTexture() 方法中,您执行以下操作。

    try {
        texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream(path));
    
        System.out.println("Texture loaded: "+texture);
        System.out.println(">> Image width: "+texture.getImageWidth());
        System.out.println(">> Image height: "+texture.getImageHeight());
        System.out.println(">> Texture width: "+texture.getTextureWidth());
        System.out.println(">> Texture height: "+texture.getTextureHeight());
        System.out.println(">> Texture ID: "+texture.getTextureID());
    } catch (IOException e) {
        e.printStackTrace();
    }
    

    只需从您的 drawTexture() 方法中删除上述代码即可。

    纹理仍然会被加载,因为在进入渲染循环之前,您已经通过调用 loadTexture() 方法完成了一次。

    编辑

    我很确定我已经尝试过了。我确实想记住我把它放在那里因为没有它它就无法工作,如果你愿意的话,这是一个“快速修复”。

    正如你所说,我刚刚意识到一些事情。您的 loadTexture() 方法已经过时了。那可能是因为你不知道你不能做那样的事情。

    在 Java 中,引用是按值传递的。这意味着,当您通过方法传递变量时,该变量就是该方法的局部变量。从而改变方法内部的变量不会改变原来的变量。

    示例

    我希望你能理解下面的例子。如果你想给一个变量分配一些新的东西,你不能使用通过方法传递的变量来做到这一点。您需要返回它然后分配它。

    public class PassingVariables {
        public static void main(String[] args) {
            String s = "Hello World!";
    
            System.out.println(s); // Prints | Hello World!
    
            test1(s);
    
            System.out.println(s); // Prints | Hello World!
    
            s = test2(s);
    
            System.out.println(s); // Prints | Testing...
    
            s = test3(s);
    
            System.out.println(s); // Prints | Hello World!
        }
    
        private static String test1(String s) {
            System.out.println(s); // Prints | Hello World!
    
            s = "Testing...";
    
            System.out.println(s); // Prints | Testing...
        }
    
        private static String test2(String s) {
            System.out.println(s); // Prints | Hello World!
    
            return "Testing...";
        }
    
        private static String test3(String s) {
            System.out.println(s); // Prints | Testing...
    
            return "Hello World!";
        }
    }
    

    新代码

    这是您的代码,我在其中更改了一些内容,因此当我们考虑到上述内容时它会起作用。

    public static Texture loadTexture(String path) {
        Texture texture = null;
    
        try {
            texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream(path));
    
            /* Removed all your println to spare some lines in the answer */
    
            TextureImpl.unbind();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    
        return texture;
    }
    
    public static void drawTexture(Texture texture) {
        Color.white.bind();
        texture.bind();
    
        GL11.glBegin(GL11.GL_QUADS);
            GL11.glTexCoord2f(0, 1);
            GL11.glVertex2f(100, 100);
            GL11.glTexCoord2f(1, 1);
            GL11.glVertex2f(100+texture.getTextureWidth(), 100);
            GL11.glTexCoord2f(1, 0);
            GL11.glVertex2f(100+texture.getTextureWidth(), 100+texture.getTextureHeight());
            GL11.glTexCoord2f(0, 0);
            GL11.glVertex2f(100, 100 + texture.getTextureHeight());
        GL11.glEnd();
    
        /* 
         * I don't recognize the release() method, but if it deletes the texture
         * then remove if. If it simply unbinds the texture then keep it. If it
         * does remove it, then change it to something like unbind(), if such
         * method exist.
         */
        texture.release();
    }
    
    public void start() {
        initGL();
    
        Player.playerText = TextureHandler.loadTexture(playerPath);
    
        while (!Display.isCloseRequested()) {
            render();
            TextureHandler.drawTexture(Player.playerText, playerPath);          
            Display.update();
        }
    
        Display.destroy();      
    }
    

    【讨论】:

    • 我回家后会试试这个,但我很确定我已经尝试过了。我确实想记住我把它放在那里因为没有它它就无法工作,如果你愿意的话,这是一个“快速修复”:)
    • @user2966263 当你这么说的时候我才意识到一些事情,我看了你的代码,发现你在说什么,看看我编辑的答案。 :)
    • 哇,我不敢相信我实际上已经在 J​​ava 中错过了这一点……非常感谢!非常清晰的描述,很高兴在没有解释的情况下不被交给“复制->粘贴”,实际上理解出了什么问题。如果可以的话,我会投票(新成员..)!
    • @Bambuh 您可以随时标记自己问题的正确答案,如果您认为我的答案回答了您的问题,那么您可以随时将我的答案标记为正确答案。但无论如何,欢迎你,伙计! :)
    • 啊,正如我所提到的。新成员 :) 固定和排序
    猜你喜欢
    • 1970-01-01
    • 2017-09-27
    • 2021-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多