2

I am making a 2d platformer game I am using a grid of 16px by 16px for blocks. I am trying to load these with 5 for loops all 10000px wide example below The problem is, Every block loads his own texture out of a sprite sheet. I am not sure what to do about this. The problem is I went from 4000 fps to 200/300. I need to load alot more blocks later on with a random terrain generator.

I found you can cache all tiles together but I have no idea how to do this, How do prevent my FPS dropping when loading spritesheet in java?

I found a post saying I should only load textures which are vissible on the screen. Is this perhaps the better option, Still I do not see how I will be able to do this. One reason for that is since I want the map to be random generated it has to be load in atleast once I asume?

Game Class

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());
}

}

Handler class

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));
        }
    }
}

Texture Class

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
    }   
}

Block Class

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 class The problem should be here I asume since all images get their own texture

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;
    }   
}
Community
  • 1
  • 1
bloxxyyy
  • 33
  • 1
  • 8
  • That's quite a lot of code, and things like the implementation of `grabImage` are still missing. It's hard to point out where the performance is lost here. However, a **very** wild guess: Try converting the lines involving `grabImage` to something `player[0] = convertToARGB(ps.grabImage(1, 1, 32, 64));` with the `convertToARGB` method that is described in http://stackoverflow.com/a/24686205/3182664 and see whether this helps (the linked question is related in general) – Marco13 Oct 25 '15 at 16:43
  • Ha, there's this `grabImage` method again: http://stackoverflow.com/questions/22230866/java-game-images-loading-very-slowly/22231370#22231370 ... This seems to be from some YouTube tutorial...?! – Marco13 Oct 25 '15 at 16:46
  • It is from a tutorial I followed one on how to add textures to your game but what he did was add all the textures at the moment the game loads in the init(). The problem is he only use arround 100 textures or so so for a small platformer game it would work, but I am trying to load arround a million of blocks and textures since I want to make something like *minecraft / terraria*. the texture loading slows down the fps but I don't know how to fix this I shall take a look at the links you send me. thanks in advance – bloxxyyy Oct 25 '15 at 17:02
  • I shall add the rest of the texture classes it might help aswell – bloxxyyy Oct 25 '15 at 17:18
  • I also dont use convertToARGB since the guy in the tutorial used paint to make a map, while I want my own generated map. – bloxxyyy Oct 25 '15 at 17:24
  • The `convertToARGB` is unrelated of how you *create* the map. The point is that you should wrap such a call around the `grabImage` call, to avoid using the sub-images directly. *They are unmanaged, and painting them is slow!* – Marco13 Oct 25 '15 at 22:52

0 Answers0