2

我对 libgdx 有很大的问题。我写了一个小小的 CHIP8 模拟器来学习如何使用 libgdx,但我仍在试图弄清楚如何让它运行得更快。我使用 Pixmap 更新屏幕,然后将其渲染为纹理,但这似乎不是最好的解决方案,因为它运行非常缓慢。这是代码:

package com.eud0x.chip8gdx;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.TextureData;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class Chip8 extends ApplicationAdapter implements InputProcessor {
    SpriteBatch batch;
    Pixmap screen;
    Texture surface;
    C8Emulator chip8;

    @Override
    public void create () {
        batch = new SpriteBatch();
        chip8 = new C8Emulator();
        screen = new Pixmap(512, 256, Format.RGB888);
        chip8.initEmulator();
        try {
            chip8.loadGame("/home/antonio/PONG");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        surface = new Texture(screen);
        Gdx.input.setInputProcessor(this);
    }

    @Override
    public void render () {
        chip8.emulateCycle();
        if ( chip8.drawflag != 0 ) {
            updateTexture();
            chip8.drawflag = 0;
        }
        batch.begin();
        batch.draw(surface, 0, 0);
        batch.end();
    }
    @Override
    public void dispose() {
        batch.dispose();
        screen.dispose();
        surface.dispose();
    }
    public void updateTexture() {
        screen.setColor(0,0,0,0);
        screen.fill();
        for ( int y = 0; y < 32; y++) {
            for ( int x = 0; x < 64; x++ ) {
                if (chip8.display[y][x] != 0) {
                    for (int cx = x*8; cx < x*8 + 8; cx++) {
                        for ( int cy = y*8; cy < y*8 + 8; cy++) {
                            screen.drawPixel(cx, cy, Color.WHITE.toIntBits());
                        }
                    }
                } 
            }
        }
        surface.draw(screen, 0, 0);
    }
@Override
    public boolean keyDown(int keycode) {
        switch (keycode) {
        case Keys.NUM_1:
            chip8.keyDown(0x1);
            break;
        case Keys.NUM_2:
            chip8.keyDown(0x2);
            break;
        case Keys.NUM_3:
            chip8.keyDown(0x3);
            break;
        case Keys.NUM_4:
            chip8.keyDown(0xC);
            break;
        case Keys.Q:
            chip8.keyDown(0x4);
            break;
        case Keys.W:
            chip8.keyDown(0x5);
            break;
        case Keys.E:
            chip8.keyDown(0x6);
            break;
        case Keys.R:
            chip8.keyDown(0xD);
            break;
        case Keys.A:
            chip8.keyDown(0x7);
            break;
        case Keys.S:
            chip8.keyDown(0x8);
            break;
        case Keys.D:
            chip8.keyDown(0x9);
            break;
        case Keys.F:
            chip8.keyDown(0xE);
            break;
        case Keys.Z:
            chip8.keyDown(0xA);
            break;
        case Keys.X:
            chip8.keyDown(0x0);
            break;
        case Keys.C:
            chip8.keyDown(0xB);
            break;
        case Keys.V:
            chip8.keyDown(0xF);
            break;
        default:
            break;  
        }
        return true;
    }

    @Override
    public boolean keyUp(int keycode) {
        switch (keycode) {
        case Keys.NUM_1:
            chip8.keyUp(0x1);
            break;
        case Keys.NUM_2:
            chip8.keyUp(0x2);
            break;
        case Keys.NUM_3:
            chip8.keyUp(0x3);
            break;
        case Keys.NUM_4:
            chip8.keyUp(0xC);
            break;
        case Keys.Q:
            chip8.keyUp(0x4);
            break;
        case Keys.W:
            chip8.keyUp(0x5);
            break;
        case Keys.E:
            chip8.keyUp(0x6);
            break;
        case Keys.R:
            chip8.keyUp(0xD);
            break;
        case Keys.A:
            chip8.keyUp(0x7);
            break;
        case Keys.S:
            chip8.keyUp(0x8);
            break;
        case Keys.D:
            chip8.keyUp(0x9);
            break;
        case Keys.F:
            chip8.keyUp(0xE);
            break;
        case Keys.Z:
            chip8.keyUp(0xA);
            break;
        case Keys.X:
            chip8.keyUp(0x0);
            break;
        case Keys.C:
            chip8.keyUp(0xB);
            break;
        case Keys.V:
            chip8.keyUp(0xF);
            break;
        default:
            break;  
        }
        return true;
    }

    @Override
    public boolean keyTyped(char character) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean touchUp(int screenX, int screenY, int pointer, int button) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean touchDragged(int screenX, int screenY, int pointer) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean mouseMoved(int screenX, int screenY) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean scrolled(int amount) {
        // TODO Auto-generated method stub
        return false;
    }
}

有谁知道如何使它更快?

4

1 回答 1

0

使用 SpriteBatch 将单个像素作为精灵直接绘制到屏幕上会更快。您一次最多可以绘制 2048 个像素,而且通常要少得多。每帧 2048 个精灵对于台式电脑来说是没有问题的,但对于旧手机来说可能是个问题,但除非加载的游戏绘制了很多白色,否则我认为它会没事的。

SpriteBatch batch;
Texture pixelSprite;
C8Emulator chip8;

@Override
public void create () {
    batch = new SpriteBatch();
    chip8 = new C8Emulator();

    Pixmap textureSource = new Pixmap(1, 1, Format.RGB8888);
    textureSource.setColor(1, 1, 1, 1);
    textureSource.fill();
    pixelSprite = new Texture(textureSource);
    textureSource.dispose();

    chip8.initEmulator();
    try {
        chip8.loadGame("/home/antonio/PONG");
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    Gdx.input.setInputProcessor(this);
}

@Override
public void render () {
    chip8.emulateCycle();

    //don't use draw flags. OpenGL redraws everything every frame
    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    batch.begin();
    for ( int y = 0; y < 32; y++) {
        for ( int x = 0; x < 64; x++ ) {
            if (chip8.display[y][x] != 0) {
                spriteBatch.draw(pixelSprite, x*8, y*8, 8, 8);
            } 
        }
    }
    batch.end();
}

如果你想真正优化它,你可以直接操纵一个 Mesh 对象来绘制点而不是精灵。这会将精灵顶点数据的大小减少 80-90%,这样即使在旧手机上绘制纯白屏幕也会非常快。但这可能不是必需的。相反,您可能需要限制您的模拟以减慢它的速度。

于 2016-06-02T15:46:04.117 回答