package org.open2jam.render.lwjgl;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.nio.ByteBuffer;
import org.lwjgl.opengl.GL11;
import org.open2jam.GameOptions;
import org.open2jam.render.Sprite;
public class LWJGLSprite implements Sprite {
/** The texture that stores the image for this sprite */
private final Texture texture;
/** the position inside the texture of the sprite */
private final int x, y;
/** The width and height in pixels of this sprite */
private final int width, height;
private final int list_id = GL11.glGenLists(1);
/** the scale of the image */
private float scale_x = 1f, scale_y = 1f;
/** the alpha */
private float alpha = 1f;
/** do blend alpha */
private boolean blend_alpha = false;
/**
* Create a new sprite from a specified image.
*
* @param window The window in which the sprite will be displayed
* @param ref A reference to the image on which this sprite should be based
*/
public LWJGLSprite(LWJGLGameWindow window,URL ref, Rectangle slice) throws IOException
{
texture = window.getTextureLoader().getTexture(ref);
if(slice == null){
x = 0;
y = 0;
width = texture.getWidth();
height = texture.getHeight();
}else{
x = slice.x;
y = slice.y;
width = slice.width;
height = slice.height;
}
init(x,y,width,height);
}
public LWJGLSprite(LWJGLGameWindow window, BufferedImage image)
{
texture = window.getTextureLoader().createTexture(image);
x = 0; y = 0;
width = texture.getWidth();
height = texture.getHeight();
init(x,y,width,height);
}
public LWJGLSprite(int w, int h, GameOptions.VisibilityMod type)
{
texture = null;
x = 0; y = 0;
this.width = w;
this.height = h;
createRectangle(width, height, type);
}
private void init(int x, int y, int width, int height)
{
float u = ((float)x/texture.getWidth()); // top-left x
float v = ((float)y/texture.getHeight()); // top-left y
float w = ((float)(x+width)/texture.getWidth()); // bottom-right x
float z = ((float)(y+height)/texture.getHeight()); // bottom-right y
GL11.glNewList(list_id, GL11.GL_COMPILE);
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(u, v);
GL11.glVertex2f(0, 0);
GL11.glTexCoord2f(u, z);
GL11.glVertex2f(0, height);
GL11.glTexCoord2f(w, z);
GL11.glVertex2f(width,height);
GL11.glTexCoord2f(w, v);
GL11.glVertex2f(width,0);
GL11.glEnd();
GL11.glEndList();
}
private void createRectangle(int width, int height, GameOptions.VisibilityMod type)
{
float split = height/4f;
GL11.glNewList(list_id, GL11.GL_COMPILE);
GL11.glBegin(GL11.GL_QUAD_STRIP);
switch(type)
{
case Hidden: //hidden (hidden lower part)
GL11.glColor4f(0f,0f,0f,0f); // middle alpha
GL11.glVertex2f(0,split*1.9f);
GL11.glVertex2f(width, split*1.9f);
GL11.glColor3f(0f,0f,0f); // second black rec
GL11.glVertex2f(0,split*2f);
GL11.glVertex2f(width, split*2f);
GL11.glVertex2f(0,height);
GL11.glVertex2f(width, height);
break;
case Sudden: //sudden (only shows the lower part)
GL11.glColor3f(0f,0f,0f); // first black rec
GL11.glVertex2f(0, 0);
GL11.glVertex2f(width,0);
GL11.glVertex2f(0,split*1.9f);
GL11.glVertex2f(width, split*1.9f);
GL11.glColor4f(0f,0f,0f,0f); // middle alpha
GL11.glVertex2f(0,split*2f);
GL11.glVertex2f(width, split*2f);
break;
case Dark: //dark (only shows the middle part)
GL11.glColor3f(0f,0f,0f); // first black rec
GL11.glVertex2f(0, 0);
GL11.glVertex2f(width,0);
GL11.glVertex2f(0,split*1.3f);
GL11.glVertex2f(width, split*1.3f);
GL11.glColor4f(0f,0f,0f,0f); // 1st middle alpha
GL11.glVertex2f(0,split*1.5f);
GL11.glVertex2f(width, split*1.5f);
GL11.glColor4f(0f,0f,0f,0f); // 2nd middle alpha
GL11.glVertex2f(0,split*2.5f);
GL11.glVertex2f(width, split*2.5f);
GL11.glColor3f(0.0f,0.0f,0.0f); // second black rec
GL11.glVertex2f(0,split*2.7f);
GL11.glVertex2f(width, split*2.7f);
GL11.glVertex2f(0,height);
GL11.glVertex2f(width, height);
break;
default: //none
break;
}
GL11.glEnd();
GL11.glEndList();
}
/**
* Get the width of this sprite in pixels
*
* @return The width of this sprite in pixels
*/
public double getWidth() {
return width * scale_x;
}
/**
* Get the height of this sprite in pixels
*
* @return The height of this sprite in pixels
*/
public double getHeight() {
return height * scale_y;
}
public Texture getTexture() {
return texture;
}
/** set the width and height percentage
* to be draw of the sprite
*/
public void setSlice(float sx, float sy)
{
int px = x;
int py = y;
if(sx < 0) px += width;
if(sy < 0) py += height;
init(px,py,Math.round(sx*width),Math.round(sy*height));
}
public void setAlpha(float alpha)
{
this.alpha = alpha;
}
/**
* Draw the sprite at the specified location
*
* @param px The x location at which to draw this sprite
* @param py The y location at which to draw this sprite
* @param sx the scale of the image width
* @param sy the scale of the image height
*/
void draw(float px, float py, float sx, float sy, int w, int h, ByteBuffer buffer)
{
// store the current model matrix
GL11.glPushMatrix();
// set to blend if necessary
if(blend_alpha)GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_DST_ALPHA);
// bind to the appropriate texture for this sprite
if(texture != null)texture.bind();
else GL11.glDisable(GL11.GL_TEXTURE_2D);
// translate to the right location and prepare to draw
GL11.glTranslatef(px, py, 0);
GL11.glColor4f(1,1,1,this.alpha);
if(buffer != null) {
GL11.glTexSubImage2D(
texture.target, 0, 0, 0,
w, h,
GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE,
buffer);
}
GL11.glScalef(sx, sy, 1);
// draw a quad textured to match the sprite
GL11.glCallList(list_id);
// undo the blend
if(blend_alpha)GL11.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
if(texture == null)GL11.glEnable(GL11.GL_TEXTURE_2D);
// restore the model view matrix to prevent contamination
GL11.glPopMatrix();
}
public void draw(float x, float y, float scale_x, float scale_y)
{
this.draw(x, y, scale_x, scale_y, 0, 0, null);
}
public void draw(double x, double y, float scale_x, float scale_y)
{
this.draw((float)x,(float)y, scale_x, scale_y);
}
public void draw(double x, double y)
{
this.draw((float)x,(float)y, scale_x, scale_y);
}
public void setScale(float x, float y) {
this.scale_x = x;
this.scale_y = y;
}
public float getScaleX() {
return scale_x;
}
public float getScaleY() {
return scale_y;
}
@Override
public void draw(double x, double y, int w, int h, ByteBuffer buffer) {
this.draw((float)x, (float)y, scale_x, scale_y, w, h, buffer);
}
@Override
public void draw(double x, double y, float scale_x, float scale_y, int w, int h, ByteBuffer buffer) {
this.draw((float)x, (float)y, scale_x, scale_y, w, h, buffer);
}
@Override
public void setBlendAlpha(boolean b) {
blend_alpha = b;
}
}