[LWJGL] Having trouble cropping from texture

Hello. I have recently been trying to create a simple program to display an animated image as practice with getting used to using textures in LWJGL (I only have experience using the animation functions in Allegro). I cannot successfully crop my image correctly. I understand that I load the texture once and crop from that, but my code does not crop the actual image. Instead, it copies and tiles the image. Also, I wish to crop from a specific location on the image, but I cannot figure out how to do that either, as my method does not seem to work.

Here is my code for drawing the sprite:

public void draw(){
		texture.bind();
		glBegin(GL_QUADS);
			glTexCoord2f(frameX/imageWidth,frameY/imageHeight);				
				glVertex2i(x, y);
			glTexCoord2f((float)(frameX + spriteWidth)/imageWidth,frameY/imageHeight);	
				glVertex2i(x + width, y);
			glTexCoord2f((float)(frameX + spriteWidth)/imageWidth,(float)(frameY + spriteHeight)/imageHeight); 
				glVertex2i(x + width, y + height);
			glTexCoord2f(frameX/imageWidth,(float)(frameY + spriteHeight)/imageHeight);	
				glVertex2i(x, y + height);
		glEnd();
	}

I have read that you can use pixel coordinates by dividing the location by the Image’s width or height where applicable. As I said, it can display the full image, but if I attempt to change the initial coordinate, it either squishes or stretches the image.

Here is where I create the image:

icon = new Sprite(25<<1, 25<<1, 40, 40, 40, 40, "res/smile2.png")

and the constructor:

public Sprite(int x, int y, int h, int w, int spriteX, int spriteY, String path) {
		super(x, y, h, w); 
		this.texture = null;
		sprites.add(this);
		this.path = path;
		this.frame = 0;
		this.key = 0;
		this.spriteWidth = spriteX;
		this.spriteHeight = spriteY;
		loadSprites();
	}

finally, the animation call and the animate() method:

public void animate(int x_pos, int y_pos, int frame_start, int frame_end, int timeStep, boolean loop){
		if(loop){
			if(frame == frame_end) 
				frame = frame_start;
		}
		
		if(frame > frame_end){
			frame = 0;
		}
		
		frameX = x_pos * frame;
		frameY = y_pos;
		
		if(key == timeStep){
			frame++;
			key = 0;
		}
	}
icon.animate(20, 20, 0, 2, 3, false);

There may be simpler way to do these things, but I really want to get the fundamentals of keying and animating things, specifically using LWJGL. Please help.

When sending tex coords, instead of sprite_x/texture.width, put this: 1f*(sprite_x/texture.width)

That help me remember to cast everything as float, but it does not change the output whatsoever. The problem is this:

On the first frame, the image should bind from the top left(upper left) to the center(bottom right) of the icon, then on the second frame, it should bind from the top center(upper left) to the center right(bottom right) of the icon. Simply put, it should just cut the top half of my image in half and flicker between the two halves. However it does not do that. Instead, it just shrinks and stretches the entire image.

Take here:

icon = new Sprite(25<<1, 25<<1, 40, 40, 40, 40, "res/smile2.png")

here, I create Entity ‘icon’ with a 40 x 40 bounding box, and image size of 40 x 40 pixels, using the image “smile2.jpg”. Then, in the animate call:

icon.animate(20, 20, 0, 2, 3, false);

I specify that each sprite in this image is 20 pixels x 20 pixels, and I tell it to start from frame 0 and animate to frame 2 with a timestep of 3. Essentially, what this should do is take the top left part of my image, then switch to the top right part of my image. Instead, it takes the entire image and multiplies it by 4. It flickers between this:

and this:

which is completely wrong. I simply want to crop the image, but I cannot figure out a way to do that, no matter what I try.

What you want to achieve is called spritesheet or texture atlas or whatever you wanna call it.

I think I messed something up, because *1 doesn’t do anything :smiley:

You said “I want to get the basics of animating”
Here is the path I would take: draw a quad, draw a colored quad, load a texture, draw quad with full texture, draw a quad with part of the texture, change the place of the texture you are rendering (animate)

As you can see animating is at the end of the line for me at least.
I can just dump some of my code if you really are lazy to figure it out on your own now.

I have already done all of that, lol. That is why I am trying to get the animation to work properly. I made Breakout last week, and it only took me about a half hour, but I am now stuck on this because the image won’t anime correctly

If you have animation code that works, I would very much like to see it and compare with my own, please.

Animation is the last step… Get the spritesheet rendering working first, then think about animation.

I hope this code helps.


public class SpriteSheet {
	public int width, height;

	// ................

	public void bind() {
		// .......
	}

	// ........

}

public class Sprite {

	public SpriteSheet sheet;
	public int x, y, width, height;
	public float x0, y0, x1, y1;

	public Sprite(SpriteSheet sheet, int x, int y, int width, int height) {
		this.sheet = sheet;
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;

		x0 = (float) x / sheet.width;
		y0 = (float) y / sheet.height;

		x1 = (float) (x + width) / sheet.width;
		y1 = (float) (y + height) / sheet.height;
	}

	
	/*
	 * Renders this sprite to specified location.
	 */
	public void render(float x, float y, float width, float height) {
		
		sheet.bind();
		
		GL11.glBegin(GL11.GL_QUAD);

		GL11.glTexCoord2f(x0, y0);
		GL11.glVertex2f(x, y);

		GL11.glTexCoord2f(x1, y0);
		GL11.glVertex2f(x + width, y);

		GL11.glTexCoord2f(x1, y1);
		GL11.glVertex2f(x + width, y + height);

		GL11.glTexCoord2f(x0, y1);
		GL11.glVertex2f(x, y + height);

		GL11.glEnd();
	}

}

Alright, after looking through my code, I seem to figured out the problem? For some reason, when I try to render the image, it is much smaller than the intended 40 pixels, and wraps the Quad with black borders. So I have it fully working now, just have to understand where the black border is coming from.

Thank you for your help, trollwarrior1!