Search code examples
javaopenglpositionlwjgl

LWJGL Player Health bar not positioning properly


I'm making a game in Java using LWJGL and slick_util recently I'm trying to implement a health bar that will hover on top of the player's head. Problem is, it is not positioning correctly. The health bar's bottom left corner(from where OpenGL starts drawing) always appears at the top right corner of the player's rectangle, and when the player moves in either x or y or both, the health bar moves away from the player in the same direction. I think it might be a problem with the glTranslatef or perhaps something silly that I missed.

Render method of Player:

protected void render() {
        Draw.rect(x, y, 32, 32, tex); //Player texture drawn
        Draw.rect(x, y + 33, 32, 15, 1, 0, 0); //Health bar drawn. x is the same as player's, but y is +33 because I want it to hover on top
    }

Draw class:

package rpgmain;
import static org.lwjgl.opengl.GL11.*;
import org.newdawn.slick.opengl.*;
/**
 *
 * @author Samsung
 */
public class Draw {

    public static void rect(float x, float y, float width, float height, Texture tex) {
        glEnable(GL_TEXTURE_2D);
        glTranslatef(x, y, 0);        
        glColor4f(1f, 1f, 1f, 1f);
        tex.bind();
        glBegin(GL_QUADS); //Specifies to the program where the drawing code begins. just to keep stuff neat. GL_QUADS specifies the type of shape you're going to be drawing.
        {
            //PNG format for images
            glTexCoord2f(0,1); glVertex2f(0, 0);  //Specify the vertices. 0, 0 is on BOTTOM LEFT CORNER OF SCREEN.
            glTexCoord2f(0,0); glVertex2f(0, height); //2f specifies the number of args we're taking(2) and the type (float)
            glTexCoord2f(1,0); glVertex2f(width, height); 
            glTexCoord2f(1,1); glVertex2f(width, 0);
        }
        glEnd();
        glDisable(GL_TEXTURE_2D);
    }

    public static void rect(float x, float y, float width, float height, float r, float g, float b) {
        glDisable(GL_TEXTURE_2D);
        glTranslatef(x, y, 0);
        glColor3f(r, g, b); 

        glBegin(GL_QUADS); //Specifies to the program where the drawing code begins. just to keep stuff neat. GL_QUADS specifies the type of shape you're going to be drawing.
        {                 
            glVertex2f(0, 0);  //Specify the vertices. 0, 0 is on BOTTOM LEFT CORNER OF SCREEN.
            glVertex2f(0, height); //2f specifies the number of args we're taking(2) and the type (float)
            glVertex2f(width, height);
            glVertex2f(width, 0); 
        }
        glEnd();
        glEnable(GL_TEXTURE_2D);
    }
}

Solution

  • I think your problem is with matrices. When you call glTranslatef, you are transforming the OpenGL ModelView matrix. However, since OpenGL is a state-based machine, this transformation is preserved for further drawing events. The second rectangle will be translated twice. What you want to do is use the OpenGL matrix stack. I'll rewrite one of the draw methods here:

    public static void rect(float x, float y, float width, float height, Texture tex) {
        glEnable(GL_TEXTURE_2D);
        glPushMatrix();
        glTranslatef(x, y, 0);        
        glColor4f(1f, 1f, 1f, 1f);
        tex.bind();
        glBegin(GL_QUADS);
        {
            glTexCoord2f(0,1); glVertex2f(0, 0);
            glTexCoord2f(0,0); glVertex2f(0, height);
            glTexCoord2f(1,0); glVertex2f(width, height); 
            glTexCoord2f(1,1); glVertex2f(width, 0);
        }
        glEnd();
        glPopMatrix();
        glDisable(GL_TEXTURE_2D);
    }
    

    The line glPushMatrix() will add a new matrix to the top of the stack. All transformations from this point on will be applied to the newly added matrix. Then, when you call glPopMatrix(), the matrix is discarded and the stack is returned to it's previous state.