Рендеринг изображения Java приводит к падению fps

Я делаю 2d платформерную игру, я использую сетку 16 на 16 пикселей для блоков. Я пытаюсь загрузить их 5 петлями для всех шириной 10000 пикселей, пример ниже. Проблема в том, что каждый блок загружает свою собственную текстуру из листа спрайта. Я не уверен, что с этим делать. Проблема в том, что я пошел с 4000 кадров в секунду до 200/300. Мне нужно загрузить больше блоков позже случайным генератором местности.

Я обнаружил, что вы можете кэшировать все тайлы вместе, но я понятия не имею, как это сделать. Как предотвратить падение FPS при загрузке таблицы спрайтов в Java?

Я нашел сообщение о том, что я должен загружать только текстуры, которые видны на экране. Возможно, это лучший вариант, но я не понимаю, как я смогу это сделать. Одна из причин этого заключается в том, что, поскольку я хочу, чтобы карта генерировалась случайным образом, ее нужно загружать как минимум, как только я это выдумал?

Игровой класс

public class Game extends Canvas implements Runnable{

private boolean running = false;
private Thread thread;

// Object
Handler handler;
Camera cam;

private void init() {   
    tex = new Texture();

    handler = new Handler();

    handler.createTerrain();

    handler.addObject(new Player(0, 300, handler, ObjectId.Player));

    this.addKeyListener(new KeyInput(handler));
}

public synchronized void start() {  
    if(running)
        return;

    running = true;
    thread = new Thread(this);
    thread.start();
    }

// runs the main loop
public void run() {
    // get all game objects into the game
    init();
    this.requestFocus();

    // very fun math to calculate frame and tick :/ * leave it as it is *
    long lastTime = System.nanoTime();
    double amountOfTicks = 60.0;
    double ns = 1000000000 / amountOfTicks;
    double delta = 0;
    long timer = System.currentTimeMillis();
    int updates = 0;
    int frames = 0;

    while(running){
        long now = System.nanoTime();
        delta += (now - lastTime) / ns;
        lastTime = now;
        while(delta >= 1){
            tick();
            updates++;
            delta--;
        }
        render();
        frames++;

        if(System.currentTimeMillis() - timer > 1000){
            timer += 1000;
            System.out.println("FPS: " + frames + " TICKS: " + updates);
            frames = 0;
            updates = 0;
        }
    }
}

private void tick() {
    handler.tick();
}

private void render() {
    BufferStrategy bs = this.getBufferStrategy();
    if(bs == null) {
        this.createBufferStrategy(3);
        return;
    }

    Graphics g = bs.getDrawGraphics();
    Graphics2D g2d = (Graphics2D) g;

    g.setColor(Color.black);
    g.fillRect(0, 0, getWidth(), getHeight());

    handler.render(g);

    g.dispose();
    bs.show();
}

public static Texture getInstance() {
    return tex;

}

public static void main(String args[]) {
    new Window(800, 600, "#", new Game());
}

}

Класс обработчика

public class Handler {

    public ArrayList<GameObject> object = new ArrayList<GameObject>();

    public void tick() {
        // get a item out the array list
        for(GameObject o: object) {

            o.tick(object);
        }
    }

    public void render(Graphics g) {
        // get a item out the array list
        for(GameObject o: object) {

            o.render(g);
        }
    }

    public void createTerrain() {       
        //floor grass
        for(int xx = -10000; xx < Game.WIDTH * 2; xx += 16) {
            addObject(new Block(xx, Game.HEIGHT - 32, 0,ObjectId.Block));
        }
        //floor dirt
        for(int xx = -10000; xx < Game.WIDTH * 2; xx += 16) {
            addObject(new Block(xx, Game.HEIGHT - 16, 1,ObjectId.Block));
        }
        //floor stone
        for(int xx = -10000; xx < Game.WIDTH * 2; xx += 16) {
            addObject(new Block(xx, Game.HEIGHT - 0, 2,ObjectId.Block));
        }
        // sand
        for(int xx = -10000; xx < Game.WIDTH * 2; xx += 16) {
            addObject(new Block(xx, Game.HEIGHT + 16, 3,ObjectId.Block));
        }
        //floor water
        for(int xx = -10000; xx < Game.WIDTH * 2; xx += 16) {
            addObject(new Block(xx, Game.HEIGHT + 32, 4,ObjectId.Block));
        }
    }
}

Класс текстуры

public class Texture {

    SpriteSheet bs, ps;
    private BufferedImage block_sheet = null;
    private BufferedImage player_sheet = null;

    public BufferedImage[] block = new BufferedImage[5];
    public BufferedImage[] player = new BufferedImage[9];
    public BufferedImage[] player_jump = new BufferedImage[1];

    public Texture() {

        BufferedImageLoader loader = new BufferedImageLoader();

        try {
            block_sheet = loader.loadImage("/Block.png");
            player_sheet = loader.loadImage("/Player.png");
        }catch(Exception e) {
            e.printStackTrace();
        }

        bs = new SpriteSheet(block_sheet);
        ps = new SpriteSheet(player_sheet);

        getTextures();
    }

    private void getTextures() {
        block[0] = bs.grabImage(1, 1, 16, 16); // grass not broken
        block[1] = bs.grabImage(1, 2, 16, 16); // dirt not broken
        block[2] = bs.grabImage(1, 3, 16, 16); // stone not broken
        block[3] = bs.grabImage(1, 4, 16, 16); // sand not broken
        block[4] = bs.grabImage(1, 5, 16, 16); // water

        // right
        player[0] = ps.grabImage(1, 1, 32, 64); // player standing
        player[1] = ps.grabImage(2, 1, 32, 64); // player move right
        player[2] = ps.grabImage(3, 1, 32, 64); // player move right
        player[3] = ps.grabImage(4, 1, 32, 64); // player move right

        // left
        player[4] = ps.grabImage(1, 2, 32, 64); // player standing
        player[5] = ps.grabImage(2, 2, 32, 64); // player move left
        player[6] = ps.grabImage(3, 2, 32, 64); // player move left
        player[7] = ps.grabImage(4, 2, 32, 64); // player move left

        // jump
        player_jump[0] = ps.grabImage(1, 3, 32, 64); // player jumps
    }   
}

Блок Класс

public class Block extends GameObject{

    Texture tex = Game.getInstance();
    private int type;

    public Block(float x, float y, int type ,ObjectId id) {
        super(x, y, id);
        this.type = type;
    }

    public void tick(ArrayList<GameObject> object) {

    }

    public void render(Graphics g) {

        if(type == 0) /* grass */ {
            g.drawImage(tex.block[type], (int)x, (int)y, null);
        }

        if(type == 1) /* dirt */ {
            g.drawImage(tex.block[type], (int)x, (int)y, null);
        }

        if(type == 2) /* stone */ {
            g.drawImage(tex.block[type], (int)x, (int)y, null);
        }

        if(type == 3) /* sand */ {
            g.drawImage(tex.block[type], (int)x, (int)y, null);
        }

        if(type == 4) /* water */ {
            g.drawImage(tex.block[type], (int)x, (int)y, null);
        }

    }

    public Rectangle getBounds() {
        return new Rectangle((int)x, (int)y, 16, 16);
    }
}

Класс SpriteSheet Проблема должна быть здесь, я полагаю, так как все изображения получают свою собственную текстуру

public class SpriteSheet {

    private BufferedImage image;

    public SpriteSheet(BufferedImage image) {
        this.image = image;
    }

    public BufferedImage grabImage(int col, int row, int width, int height) {
        BufferedImage img = image.getSubimage((col * width) - width, (row * height) - height, width, height);
        return img;
    }   
}

0 ответов

Другие вопросы по тегам