diff --git a/src/ei/engine/LWJGLGameWindow.java b/src/ei/engine/LWJGLGameWindow.java index d308c3e..2f203f5 100644 --- a/src/ei/engine/LWJGLGameWindow.java +++ b/src/ei/engine/LWJGLGameWindow.java @@ -92,6 +92,8 @@ public class LWJGLGameWindow { GL11.glShadeModel(GL11.GL_SMOOTH); // disable the OpenGL depth test since we're rendering 2D graphics GL11.glDisable(GL11.GL_DEPTH_TEST); + //GL11.glEnable(GL11.GL_DEPTH_TEST); // Enables Depth Testing + //GL11.glDepthFunc(GL11.GL_LEQUAL); // The Type Of Depth Testing To Do // disable lights (we do not nead them) GL11.glDisable(GL11.GL_LIGHTING); // Enable Smooth Shading @@ -101,6 +103,7 @@ public class LWJGLGameWindow { // Depth Buffer Setup GL11.glClearDepth(1.0f); + //Select The Projection Matrix GL11.glMatrixMode(GL11.GL_PROJECTION); //Reset The Projection Matrix @@ -114,9 +117,9 @@ public class LWJGLGameWindow { //Enable Blending GL11.glEnable(GL11.GL_BLEND); - GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + //GL11.glBlendFunc(GL11.GL_SRC_ALPHA,GL11.GL_ONE); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - // Enable vsync if we can (due to how OpenGL works, it cannot be guarenteed to always work) Display.setVSyncEnabled(true); diff --git a/src/ei/engine/effects/BitmapText.java b/src/ei/engine/effects/BitmapText.java new file mode 100644 index 0000000..a51675b --- /dev/null +++ b/src/ei/engine/effects/BitmapText.java @@ -0,0 +1,92 @@ +package ei.engine.effects; + +import java.awt.Rectangle; + +import org.lwjgl.opengl.GL11; + +import ei.engine.scene.Entity; +import ei.engine.texture.Texture; +import ei.engine.texture.TextureLoader; + +/** + * Displays text on the screen by a bitmap + * @author Ziver + * + */ + +public class BitmapText extends Entity{ + private static final int CHAR_SIZE = 10; + private Texture texture; + + private String text; + + /** + * Create a Text object + * + * @param name The name of this entity + */ + public BitmapText(String name) { + super(name); + texture = TextureLoader.getTextureLoaderInstance().getTexture("data/font.png"); + } + + /** + * Set the text to be displayed + * + * @param msg The text + */ + public void setText(String msg){ + text = msg; + } + + /** + * Render the text + */ + public void render(){ + if(text != null && !text.isEmpty()){ + // store the current model matrix + GL11.glPushMatrix(); + + //Sets the location + super.setTranslationGL(); + // No rotation enabled + //super.setRotationGL(texture.getImageWidth()/2,texture.getImageHeight()/2); + //Sets the scale of the sprite + super.setScaleGL(); + + texture.bindGL(); + + for(int i=0; i height) ? width * 16 : height * 16; + if(!directionSet) { + if(lineWidth > bitmapSize) { + delta = -2; + } + else { + delta = 2; + } + directionSet = true; + } + if(delta > 0) { + if(lineWidth < bitmapSize) { + fontSize += delta; + } + else { + sizeFound = true; + fontSize -= delta; + } + } + else if(delta < 0) { + if(lineWidth > bitmapSize) { + fontSize += delta; + } + else { + sizeFound = true; + fontSize -= delta; + } + } + } + + /* Now that a font size has been determined, create the final image, set the font and draw the + * standard/extended ASCII character set for that font. + */ + font = new Font(fontName, Font.BOLD, fontSize); // Font Name + // use BufferedImage.TYPE_4BYTE_ABGR to allow alpha blending + fontImage = new BufferedImage(bitmapSize, bitmapSize, BufferedImage.TYPE_4BYTE_ABGR); + Graphics2D g = (Graphics2D)fontImage.getGraphics(); + g.setFont(font); + g.setColor(OPAQUE_WHITE); + g.setBackground(TRANSPARENT_BLACK); + FontMetrics fm = g.getFontMetrics(); + for(int i=0;i<256;i++) { + int x = i % 16; + int y = i / 16; + char ch[] = {(char)i}; + String temp = new String(ch); + g.drawString(temp, (x * 32) + 1, (y * 32) + fm.getAscent()); + } + + /* The following code is taken directly for the LWJGL example code. + * It takes a Java Image and converts it into an OpenGL texture. + * This is a very powerful feature as you can use this to generate textures on the fly out + * of anything. + */ + // Flip Image + AffineTransform tx = AffineTransform.getScaleInstance(1, -1); + tx.translate(0, -fontImage.getHeight(null)); + AffineTransformOp op = + new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR); + fontImage = op.filter(fontImage, null); + + // Put Image In Memory + ByteBuffer scratch = + ByteBuffer.allocateDirect( + 4 * fontImage.getWidth() * fontImage.getHeight()); + + byte data[] = + (byte[])fontImage.getRaster().getDataElements( + 0, + 0, + fontImage.getWidth(), + fontImage.getHeight(), + null); + scratch.clear(); + scratch.put(data); + scratch.rewind(); + + // Create A IntBuffer For Image Address In Memory + IntBuffer buf = + ByteBuffer + .allocateDirect(4) + .order(ByteOrder.nativeOrder()) + .asIntBuffer(); + GL11.glGenTextures(buf); // Create Texture In OpenGL + + GL11.glBindTexture(GL11.GL_TEXTURE_2D, buf.get(0)); + // Typical Texture Generation Using Data From The Image + + // Linear Filtering + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); + // Linear Filtering + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); + // Generate The Texture + GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, fontImage.getWidth(), fontImage.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, scratch); + + + texture = buf.get(0); // Return Image Address In Memory + + base = GL11.glGenLists(256); // Storage For 256 Characters + + /* Generate the display lists. One for each character in the standard/extended ASCII chart. + */ + float textureDelta = 1.0f / 16.0f; + for(int i=0;i<256;i++) { + float u = ((float)(i % 16)) / 16.0f; + float v = 1.f - (((float)(i / 16)) / 16.0f); + GL11.glNewList(base + i, GL11.GL_COMPILE); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture); + GL11.glBegin(GL11.GL_QUADS); + GL11.glTexCoord2f(u, v); + GL11.glVertex3f(-0.0450f, 0.0450f, 0.0f); + GL11.glTexCoord2f((u + textureDelta), v); + GL11.glVertex3f(0.0450f, 0.0450f, 0.0f); + GL11.glTexCoord2f((u + textureDelta), v - textureDelta); + GL11.glVertex3f(0.0450f, -0.0450f, 0.0f); + GL11.glTexCoord2f(u, v - textureDelta); + GL11.glVertex3f(-0.0450f, -0.0450f, 0.0f); + GL11.glEnd(); + GL11.glEndList(); + } + } + + public Rectangle getBound() { + return null; + } +} diff --git a/src/ei/engine/math/Vector3f.java b/src/ei/engine/math/Vector3f.java index e6abb2c..49c1be1 100644 --- a/src/ei/engine/math/Vector3f.java +++ b/src/ei/engine/math/Vector3f.java @@ -58,8 +58,18 @@ public class Vector3f { return z; } + /** + * Set the z value + * + * @param z the z value + */ + public void setZ(float z){ + this.z = z; + } + /** * Add to the vector + * * @param i The amount to add */ public void add(float i){ @@ -70,6 +80,7 @@ public class Vector3f { /** * Add to the vector + * * @param i The amount to add */ public void add(Vector3f i){ @@ -80,6 +91,7 @@ public class Vector3f { /** * Add to the vector + * * @param i The amount to add */ public void add(Vector2f i){ @@ -89,6 +101,7 @@ public class Vector3f { /** * Add to the vector + * * @param x The value to add to the x value * @param y The value to add to the y value * @param z The value to add to the z value @@ -99,7 +112,16 @@ public class Vector3f { this.z += z; } + /** + * Returns a copy of this vector + * + * @return A copy of this vector + */ + public Vector3f getCopy(){ + return new Vector3f(x,y,z); + } + public String toString(){ - return "Vector2f["+x+","+y+"]"; + return "Vector3f["+x+","+y+","+z+"]"; } } diff --git a/src/ei/engine/scene/Node.java b/src/ei/engine/scene/Node.java index f748f79..d65966e 100644 --- a/src/ei/engine/scene/Node.java +++ b/src/ei/engine/scene/Node.java @@ -51,6 +51,14 @@ public class Node extends Sprite { return false; } + public boolean remove(Entity e){ + if(entities.contains(e)){ + entities.remove(e); + return true; + } + return false; + } + /** * Draw all the Entities in the node */ diff --git a/src/ei/engine/test/GameStateTestState.java b/src/ei/engine/test/GameStateTestState.java index 1128b01..0825dd7 100644 --- a/src/ei/engine/test/GameStateTestState.java +++ b/src/ei/engine/test/GameStateTestState.java @@ -3,6 +3,7 @@ package ei.engine.test; import ei.engine.LWJGLGameWindow; import ei.engine.effects.Particles; import ei.engine.math.Vector2f; +import ei.engine.math.Vector3f; import ei.engine.scene.Node; import ei.engine.scene.Sprite; import ei.engine.sound.Sound; @@ -21,11 +22,12 @@ public class GameStateTestState extends GameState{ sprite1 = new Sprite("tank","data/units/tank.png"); //sprite1.setScale(new Vector2f(0.5f,0.5f)); - //sprite1.setLocation(new Vector2f(300,300)); + sprite1.setLocation(new Vector3f(0,0,0.2f)); rootNode.add(sprite1); p = new Particles("particle"); - p.setLocation(sprite1.getLocation()); + p.setLocation(sprite1.getLocation().getCopy()); + p.getLocation().setZ(0.1f); rootNode.add(p); sound1 = new Sound("sound","data/sounds/center.wav"); diff --git a/src/ei/engine/test/TextTest.java b/src/ei/engine/test/TextTest.java new file mode 100644 index 0000000..2a814be --- /dev/null +++ b/src/ei/engine/test/TextTest.java @@ -0,0 +1,39 @@ +package ei.engine.test; + +import ei.engine.LWJGLGameWindow; +import ei.engine.effects.BitmapText; +import ei.engine.effects.Text; +import ei.engine.math.Vector2f; + +public class TextTest extends LWJGLGameWindow{ + private BitmapText text; + private float pos; + + public static void main(String[] args){ + new TextTest(); + } + + public TextTest() { + super("TextTest"); + } + + protected void init(){ + text = new BitmapText("Test text"); + text.setText("LOL THIS IS A TEST!!"); + pos = 0; + } + + protected void update() { + super.update(); + pos += 0.2f; + text.setLocation(new Vector2f(200,200)); + text.update(); + } + + /** + * this method shid be overriden + */ + protected void render(){ + text.render(); + } +} diff --git a/src/ei/engine/test/ex/BasicTest.java b/src/ei/engine/test/ex/BasicSoundTest.java similarity index 95% rename from src/ei/engine/test/ex/BasicTest.java rename to src/ei/engine/test/ex/BasicSoundTest.java index 8e680b8..63ab733 100644 --- a/src/ei/engine/test/ex/BasicTest.java +++ b/src/ei/engine/test/ex/BasicSoundTest.java @@ -46,12 +46,12 @@ import org.lwjgl.opengl.DisplayMode; * @version $Revision$ * $Id$ */ -public abstract class BasicTest { +public abstract class BasicSoundTest { /** * Creates an instance of PlayTest */ - public BasicTest() { + public BasicSoundTest() { try { String[] imps = AL.getImplementations(); if(imps.length > 0) { diff --git a/src/ei/engine/test/ex/FontTest.java b/src/ei/engine/test/ex/FontTest.java new file mode 100644 index 0000000..975aa65 --- /dev/null +++ b/src/ei/engine/test/ex/FontTest.java @@ -0,0 +1,367 @@ +package ei.engine.test.ex; + +/* + * This Code Was Created By Jeff Molofee 2000 + * Modified by Shawn T. to handle (%3.2f, num) parameters. + * A HUGE Thanks To Fredric Echols For Cleaning Up + * And Optimizing The Base Code, Making It More Flexible! + * If You've Found This Code Useful, Please Let Me Know. + * Visit My Site At nehe.gamedev.net + */ +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.IntBuffer; +import java.text.NumberFormat; + +import org.lwjgl.opengl.Display; +import org.lwjgl.opengl.DisplayMode; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.glu.GLU; +import org.lwjgl.input.Keyboard; + +/** + * @author Mark Bernard + * date: 26-May-2004 + * + * Port of NeHe's Lesson 13 to LWJGL + * Title: Bitmap fonts + * Uses version 0.9alpha of LWJGL http://www.lwjgl.org/ + * + * Be sure that the LWJGL libraries are in your classpath + * + * Ported directly from the C++ version + * + * The main point of this tutorial is to get fonts on the screen. The original OpenGL did + * not port directly as it used Windows specific extensions and I could not get some OpenGL + * commands to work. In the end, what you see on the screen is the same, but it is written + * somewhat differently. I have noted the differences in the code with comments. + * + * 2004-10-08: Updated to version 0.92alpha of LWJGL. + * 2004-12-19: Updated to version 0.94alpha of LWJGL + */ +public class FontTest { + private boolean done = false; + private boolean fullscreen = false; + private final String windowTitle = "NeHe's OpenGL Lesson 13 for LWJGL (Bitmap Fonts)"; + private boolean f1 = false; + private DisplayMode displayMode; + + private int texture; + + //build colours for font with alpha transparency + private static final Color OPAQUE_WHITE = new Color(0xFFFFFFFF, true); + private static final Color TRANSPARENT_BLACK = new Color(0x00000000, true); + private NumberFormat numberFormat = NumberFormat.getInstance(); + + private int base; // Base Display List For The Font Set + private float cnt1; // 1st Counter Used To Move Text & For Coloring + private float cnt2; // 2nd Counter Used To Move Text & For Coloring + + public static void main(String args[]) { + boolean fullscreen = false; + if(args.length>0) { + if(args[0].equalsIgnoreCase("fullscreen")) { + fullscreen = true; + } + } + + FontTest l13 = new FontTest(); + l13.run(fullscreen); + } + public void run(boolean fullscreen) { + this.fullscreen = fullscreen; + try { + init(); + while (!done) { + mainloop(); + render(); + Display.update(); + } + cleanup(); + } + catch (Exception e) { + e.printStackTrace(); + System.exit(0); + } + } + private void mainloop() { + if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) { // Exit if Escape is pressed + done = true; + } + if(Display.isCloseRequested()) { // Exit if window is closed + done = true; + } + if(Keyboard.isKeyDown(Keyboard.KEY_F1) && !f1) { // Is F1 Being Pressed? + f1 = true; // Tell Program F1 Is Being Held + switchMode(); // Toggle Fullscreen / Windowed Mode + } + if(!Keyboard.isKeyDown(Keyboard.KEY_F1)) { // Is F1 Being Pressed? + f1 = false; + } + } + + private void switchMode() { + fullscreen = !fullscreen; + try { + Display.setFullscreen(fullscreen); + } + catch(Exception e) { + e.printStackTrace(); + } + } + + private boolean render() { + GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer + GL11.glLoadIdentity(); // Reset The Current Modelview Matrix + + // Position The Text On The Screen + GL11.glTranslatef(-0.9f + 0.05f * ((float)Math.cos(cnt1)), 0.32f * ((float)Math.sin(cnt2)), -2.0f); // Move One Unit Into The Screen + + // Pulsing Colors Based On Text Position + float red = 1.0f * ((float)Math.cos(cnt1)); + float green = 1.0f * ((float)Math.sin(cnt2)); + float blue = 1.0f - 0.5f * ((float)Math.cos(cnt1 + cnt2)); + GL11.glColor3f(red, green, blue); + + //format the floating point number to 2 decimal places + numberFormat.setMaximumFractionDigits(2); + numberFormat.setMinimumFractionDigits(2); + + glPrint("Active OpenGL Text With NeHe - " + numberFormat.format(cnt1)); // Print GL Text To The Screen + cnt1 += 0.051f; // Increase The First Counter + cnt2 += 0.005f; // Increase The Second Counter + + return true; + } + + /* Some liberties had to be taken with this method. I could not get the glCallLists() to work, so + * it is done manually instead. + */ + private void glPrint(String msg) { // Custom GL "Print" Routine + if(msg != null) { + GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture); + for(int i=0;i height) ? width * 16 : height * 16; + if(!directionSet) { + if(lineWidth > bitmapSize) { + delta = -2; + } + else { + delta = 2; + } + directionSet = true; + } + if(delta > 0) { + if(lineWidth < bitmapSize) { + fontSize += delta; + } + else { + sizeFound = true; + fontSize -= delta; + } + } + else if(delta < 0) { + if(lineWidth > bitmapSize) { + fontSize += delta; + } + else { + sizeFound = true; + fontSize -= delta; + } + } + } + + /* Now that a font size has been determined, create the final image, set the font and draw the + * standard/extended ASCII character set for that font. + */ + font = new Font(fontName, Font.BOLD, fontSize); // Font Name + // use BufferedImage.TYPE_4BYTE_ABGR to allow alpha blending + fontImage = new BufferedImage(bitmapSize, bitmapSize, BufferedImage.TYPE_4BYTE_ABGR); + Graphics2D g = (Graphics2D)fontImage.getGraphics(); + g.setFont(font); + g.setColor(OPAQUE_WHITE); + g.setBackground(TRANSPARENT_BLACK); + FontMetrics fm = g.getFontMetrics(); + for(int i=0;i<256;i++) { + int x = i % 16; + int y = i / 16; + char ch[] = {(char)i}; + String temp = new String(ch); + g.drawString(temp, (x * 32) + 1, (y * 32) + fm.getAscent()); + } + + /* The following code is taken directly for the LWJGL example code. + * It takes a Java Image and converts it into an OpenGL texture. + * This is a very powerful feature as you can use this to generate textures on the fly out + * of anything. + */ + // Flip Image + AffineTransform tx = AffineTransform.getScaleInstance(1, -1); + tx.translate(0, -fontImage.getHeight(null)); + AffineTransformOp op = + new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR); + fontImage = op.filter(fontImage, null); + + // Put Image In Memory + ByteBuffer scratch = + ByteBuffer.allocateDirect( + 4 * fontImage.getWidth() * fontImage.getHeight()); + + byte data[] = + (byte[])fontImage.getRaster().getDataElements( + 0, + 0, + fontImage.getWidth(), + fontImage.getHeight(), + null); + scratch.clear(); + scratch.put(data); + scratch.rewind(); + + // Create A IntBuffer For Image Address In Memory + IntBuffer buf = + ByteBuffer + .allocateDirect(4) + .order(ByteOrder.nativeOrder()) + .asIntBuffer(); + GL11.glGenTextures(buf); // Create Texture In OpenGL + + GL11.glBindTexture(GL11.GL_TEXTURE_2D, buf.get(0)); + // Typical Texture Generation Using Data From The Image + + // Linear Filtering + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); + // Linear Filtering + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); + // Generate The Texture + GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, fontImage.getWidth(), fontImage.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, scratch); + + + texture = buf.get(0); // Return Image Address In Memory + + base = GL11.glGenLists(256); // Storage For 256 Characters + + /* Generate the display lists. One for each character in the standard/extended ASCII chart. + */ + float textureDelta = 1.0f / 16.0f; + for(int i=0;i<256;i++) { + float u = ((float)(i % 16)) / 16.0f; + float v = 1.f - (((float)(i / 16)) / 16.0f); + GL11.glNewList(base + i, GL11.GL_COMPILE); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture); + GL11.glBegin(GL11.GL_QUADS); + GL11.glTexCoord2f(u, v); + GL11.glVertex3f(-0.0450f, 0.0450f, 0.0f); + GL11.glTexCoord2f((u + textureDelta), v); + GL11.glVertex3f(0.0450f, 0.0450f, 0.0f); + GL11.glTexCoord2f((u + textureDelta), v - textureDelta); + GL11.glVertex3f(0.0450f, -0.0450f, 0.0f); + GL11.glTexCoord2f(u, v - textureDelta); + GL11.glVertex3f(-0.0450f, -0.0450f, 0.0f); + GL11.glEnd(); + GL11.glEndList(); + } + } +} \ No newline at end of file diff --git a/src/ei/engine/test/ex/Lesson19.java b/src/ei/engine/test/ex/ParticleTest.java similarity index 97% rename from src/ei/engine/test/ex/Lesson19.java rename to src/ei/engine/test/ex/ParticleTest.java index 1fbf147..e435a78 100644 --- a/src/ei/engine/test/ex/Lesson19.java +++ b/src/ei/engine/test/ex/ParticleTest.java @@ -33,7 +33,7 @@ import ei.engine.util.MultiPrintStream; * 2004-12-19: Updated to version 0.94alpha of LWJGL and to use * DevIL for image loading. */ -public class Lesson19 { +public class ParticleTest { private boolean done = false; private boolean fullscreen = false; private final String windowTitle = "NeHe's OpenGL Lesson 19 for LWJGL (Particle Engine Using Triangle Strips)"; @@ -71,7 +71,7 @@ public class Lesson19 { } } - Lesson19 l19 = new Lesson19(); + ParticleTest l19 = new ParticleTest(); l19.run(fullscreen); } public void run(boolean fullscreen) { diff --git a/src/ei/engine/test/ex/SoundPositionTest.java b/src/ei/engine/test/ex/SoundPositionTest.java index 839fb91..c7d24e6 100644 --- a/src/ei/engine/test/ex/SoundPositionTest.java +++ b/src/ei/engine/test/ex/SoundPositionTest.java @@ -55,7 +55,7 @@ import org.lwjgl.util.WaveData; * @version $Revision$ * $Id$ */ -public class SoundPositionTest extends BasicTest { +public class SoundPositionTest extends BasicSoundTest { /** *Small* glut implementation :) */ private GLUT glut;