Game rendering issue

Hello,

This is my first post here. I’m very new to game programming. I’m trying to learn it using Java. I have been following this tutorial series on youtube for a little while, just fyi:

My issue is with a section of code with the tutorials provided. I did attempt to get an answer, but could not get enough information to solve it.

Basically the game loads tiles from a spritesheet made by this person for the player and the background. It is 128x128 and when I use the code from the tutorial and his spritesheet, it works flawlessly. The FPS is set to 60 and consistently stays at 60 during runtime.

The issue happens when I chose to try a different spritesheet. I used a few from this particular site just to test with. http://www.realmofdarkness.net/dq/games/nes/dw4/sprites. Some of the sheets work. All of the monsters spritesheets I have tried cause a severe slowdown in the game and cut the FPS literally in half. I have reviewed the image properties of both the spritesheet used in the tutorial and the one from this site and they seem the same to me.

I don’t know what could be causing this issue. Below I will post what I believe to be the relevant sections of code.

Worlds class:


package dev.codenmore.tilegame.worlds;

import java.awt.Graphics;

import dev.codenmore.tilegame.Game;
import dev.codenmore.tilegame.tiles.Tile;
import dev.codenmore.tilegame.utils.Utils;

public class World {

	private Game game;
	private int width, height;
	private int spawnX, spawnY;
	private int[][] tiles;
	
	public World(Game game, String path){
		this.game = game;
		loadWorld(path);
	}
	
	public void tick(){
		
	}
	
	public void render(Graphics g){
		for(int y = 0;y < height;y++){
			for(int x = 0;x < width;x++){
				getTile(x, y).render(g, (int) (x * Tile.TILEWIDTH - game.getGameCamera().getxOffset()),
						(int) (y * Tile.TILEHEIGHT - game.getGameCamera().getyOffset()));
			}
		}
	}
	
	public Tile getTile(int x, int y){
		Tile t = Tile.tiles[tiles[x][y]];
		if(t == null)
			return Tile.dirtTile;
		return t;
	}
	
	private void loadWorld(String path){
		String file = Utils.loadFileAsString(path);
		String[] tokens = file.split("\\s+");
		width = Utils.parseInt(tokens[0]);
		height = Utils.parseInt(tokens[1]);
		spawnX = Utils.parseInt(tokens[2]);
		spawnY = Utils.parseInt(tokens[3]);
		
		tiles = new int[width][height];
		for(int y = 0;y < height;y++){
			for(int x = 0;x < width;x++){
				tiles[x][y] = Utils.parseInt(tokens[(x + y * width) + 4]);
			}
		}
	}
	
}


Tile class:


package dev.codenmore.tilegame.tiles;

import java.awt.Graphics;
import java.awt.image.BufferedImage;

public class Tile {
	
	//STATIC STUFF HERE
	
	public static Tile[] tiles = new Tile[256];
	public static Tile grassTile = new GrassTile(0);
	public static Tile dirtTile = new DirtTile(1);
	public static Tile rockTile = new RockTile(2);
	
	//CLASS
	
	public static final int TILEWIDTH = 64, TILEHEIGHT = 64;
	
	protected BufferedImage texture;
	protected final int id;
	
	public Tile(BufferedImage texture, int id){
		this.texture = texture;
		this.id = id;
		
		tiles[id] = this;
	}
	
	public void tick(){
		
	}
	
	public void render(Graphics g, int x, int y){
		g.drawImage(texture, x, y, TILEWIDTH, TILEHEIGHT, null);
	}
	
	public boolean isSolid(){
		return false;
	}
	
	public int getId(){
		return id;
	}
	
}


Assets class:


package dev.codenmore.tilegame.gfx;

import java.awt.image.BufferedImage;

public class Assets {
private static final int width = 32, height = 32;
    private static final int WIDTH = 48, HEIGHT = 48;	
	public static BufferedImage player, dirt, grass, stone, tree;

	public static void init(){
		//SpriteSheet sheet = new SpriteSheet(ImageLoader.loadImage("/textures/sheet2.png"));
                SpriteSheet sheet = new SpriteSheet(ImageLoader.loadImage("/textures/sheet.png"));
		
		player = sheet.crop(0, 0, width, height);
		dirt = sheet.crop(width, 0, width, height);
		grass = sheet.crop(width * 2, 0, width, height);
		stone = sheet.crop(width * 3, 0, width, height);
		tree = sheet.crop(0, height, width, height);
                
//                player = sheet.crop(200, 200, width, height);
//                dirt = sheet.crop(WIDTH * 3, 16, WIDTH, HEIGHT);
//                tree = sheet.crop(144, 128, WIDTH, HEIGHT);
//                grass = sheet.crop(0, 128, WIDTH, HEIGHT);
//                stone = sheet.crop(144, 80, WIDTH, HEIGHT);
	}	
            
}


Spritesheet class:


package dev.codenmore.tilegame.gfx;

import java.awt.image.BufferedImage;

public class SpriteSheet {

	private BufferedImage sheet;
	
	public SpriteSheet(BufferedImage sheet){
		this.sheet = sheet;
	}
	
	public BufferedImage crop(int x, int y, int width, int height){
		return sheet.getSubimage(x, y, width, height);
	}
	
}


Image Loader class:


package dev.codenmore.tilegame.gfx;

import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;

public class ImageLoader {

	public static BufferedImage loadImage(String path){
		try {
			return ImageIO.read(ImageLoader.class.getResource(path));
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(1);
		}
		return null;
	}
	
}


Game loop



@Override
	public void run(){
	
		init();
		
		int fps = 60;
                // 1 billion nanoseconds is 1 second
		double timePerTick = 1000000000 / fps;
		double delta = 0;
		long now;
		long lastTime = System.nanoTime();
		long timer = 0;
		int ticks = 0;
		
                /* 
                    This game loop runs 60 times per second to achieve 60 FPS
                    Each loop is a frame
                    VARIABLE FRAME RATE 
                
                */
		while(running){
			now = System.nanoTime();
                        // delta is how much time that is required to pass until the loop runs tick and render
                        // In mathematics, the term Delta is used to describe a change in something.
			delta += (now - lastTime) / timePerTick;
                        // timer is for the display of FPS
			timer += now - lastTime;
                        // since delta updated, set lastTime to now for next check
			lastTime = now;
			
			if(delta >= 1){
				tick();
				render();
//                                if(delta >= 2){
//                                    render();   
//                                }
				ticks++;
				delta--;
			}
                        
                        
			
			if(timer >= 1000000000){
				System.out.println("Ticks and Frames: " + ticks);
				ticks = 0; // resets tick
				timer = 0; // resets timer to dislay again
			}
		}
		
		stop();
		
	}