I’ve been messing with LWJGL For a few weeks, And I’ve decided to make my first game, Which just so happens to be tilebased. I’ve gotten a decent amount of the work done, However Loading the tiles has been a bit of a challenge. I’ve made my own spritesheet class, that loads the correct amount of sprites based on the size of the sprites. I’m just stuck on the “Displaying” the sprite part. Please don’t link me to the Slick utils or anything; I want to see what can be done with LWJGL by itself.
Heres my Spritesheet class:
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.nio.ByteBuffer;
import javax.imageio.ImageIO;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import test.Test;
public class Spritesheet
{
protected BufferedImage spritesheetImages;
protected int spriteSize;
protected int texturesIndex;
protected int textureID;
public int[] textures;
public Spritesheet(InputStream input, int size)
{
this.spritesheetImages = getImageFromStream(input);
if (spritesheetImages.getWidth() % 2 == 0 & spritesheetImages.getHeight() % 2 == 0){
System.out.println("Loaded a spritesheet that is a multiple of two. Continuing.");
this.spriteSize = size;
this.texturesIndex = ((spritesheetImages.getWidth() / spriteSize) * (spritesheetImages.getHeight() / spriteSize));//Returns the amount of possible images in the sheet.
this.textureID = convertBufferedImageToID(spritesheetImages); //Gets ID of the spritesheet as a whole.
this.textures = new int[texturesIndex]; //Creates an int index the size of the possible sprites in the image.
this.loadAllPossibleImages();
}else{
System.err.println("Tried to load a spritesheet that is not a multiple of two!");
}
}
public void loadAllPossibleImages()
{
int currentIndex = 0;
/** Starts loading at the bottom left sprite. */
for(int i = spriteSize; i < spritesheetImages.getHeight(); i += spriteSize)
{
for(int j = 0; j < spritesheetImages.getWidth(); j += spriteSize)
{
textures[currentIndex] = convertBufferedImageToID(spritesheetImages.getSubimage(j, i, spriteSize, spriteSize));
System.out.println("Loaded sprite @ " + j + " & " + i + " & Width: " + spriteSize);
currentIndex++;
}
}
/** Ends loading at the top right sprite. */
}
public void drawSprite(float x, float y, int index)
{
GL11.glPushMatrix();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textures[index]);
GL11.glTranslatef(x, y, 0);
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(0, 0);
GL11.glTexCoord2f(1.0f, 0);
GL11.glVertex2f(spriteSize, 0);
GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex2f(spriteSize, spriteSize);
GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex2f(0, spriteSize);
GL11.glPopMatrix();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, -1);
}
private int convertBufferedImageToID(BufferedImage image)
{
int[] pixels = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * 4); //4 for RGBA, 3 for RGB
for(int y = 0; y < image.getHeight(); y++){
for(int x = 0; x < image.getWidth(); x++){
int pixel = pixels[y * image.getWidth() + x];
buffer.put((byte) ((pixel >> 16) & 0xFF));
buffer.put((byte) ((pixel >> 8) & 0xFF));
buffer.put((byte) (pixel & 0xFF));
buffer.put((byte) ((pixel >> 24) & 0xFF));
}
}
buffer.flip();
int textureID = GL11.glGenTextures();
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);
return textureID;
}
private BufferedImage getImageFromStream(InputStream input)
{
try{
return ImageIO.read(input);
}catch(Exception ex){
System.out.println("Unable to load spritesheet from stream.");
return null;
}
}
}
Also, Heres the init of my OpenGL just in case theres anything wrong in there (Which I don’t think there is…)
/**
* The default OpenGL Settings. Used if too lazy to make configs by him/her self.
*/
public void initDefaultGL()
{
GL11.glEnable(GL11.GL_COLOR_MATERIAL);
GL11.glEnable(GL11.GL_TEXTURE_2D); // Enable Texture Mapping
GL11.glClearColor(backgroundColors[0], backgroundColors[1], backgroundColors[2], backgroundColors[3]); // Black Background
GL11.glDisable(GL11.GL_DITHER); //Disable dither.
GL11.glDepthFunc(GL11.GL_LESS); // Depth function less or equal
GL11.glEnable(GL11.GL_NORMALIZE); // calculated normals when scaling
GL11.glEnable(GL11.GL_CULL_FACE); // prevent render of back surface
GL11.glEnable(GL11.GL_BLEND); // Enabled blending
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); // selects blending method
GL11.glEnable(GL11.GL_ALPHA_TEST); // allows alpha channels or transperancy
GL11.glAlphaFunc(GL11.GL_GREATER, 0.1f); // sets alpha function
GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST); // High quality visuals
GL11.glHint(GL11.GL_POLYGON_SMOOTH_HINT, GL11.GL_NICEST); // Really Nice Perspective Calculations
GL11.glShadeModel(GL11.GL_SMOOTH); // Enable Smooth Shading
GL11.glViewport(0, 0, Display.getWidth(), Display.getHeight());
GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
GL11.glLoadIdentity(); // Reset The Projection Matrix
GLU.gluPerspective(30, Display.getWidth()/(float)Display.getHeight(), 1f, 300f); //Aspect Ratio Of The Window
GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix
GL11.glDepthMask(true); // Enable Depth Mask
}
/**
* Sets the 2D Mode for loading 2D Objects on the screen.
*/
public static void set2DMode(float x, float width, float y, float height) {
//GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
GL11.glPushMatrix(); // Store The Projection Matrix
GL11.glLoadIdentity(); // Reset The Projection Matrix
GL11.glOrtho(x, width, y, height, -1, 1); // Set Up An Ortho Screen
GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix
GL11.glPushMatrix(); // Store The Modelview Matrix
GL11.glLoadIdentity(); // Reset The Modelview Matrix
}