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:
https://www.youtube.com/user/CodeNMore/videos
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 and two profile screenshots from Netbeans, one with the game code running with the spritesheet from the video tutorial and one with the spritesheet from the site I was using.
Gameloop:
@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();
}
ImageLoader 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;
}
}
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/monsters.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);
}
}
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]);
}
}
}
}
Tiles 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;
}
}
These are using the tutorial based spritesheet
[attachment=26334:Workspace 1_008.png]
[attachment=26333:Workspace 1_009.png]
These are using the non-tutorial based spritesheet
[attachment=26332:Workspace 1_010.png]
[attachment=26331:Workspace 1_011.png]