Problem
While beginning to learn some LWJGL (Light weight java gaming library) I found that detecting if an object is leaving the screen more difficult than I expected.
Steps Taken
Added printlns to debug variable names and created an SSCCE
Simple Self-Contained Complete Example
Complete Problem Descriptionpackage me.timothy; import java.awt.geom.Point2D; import java.awt.geom.Point2D.Float; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.lwjgl.LWJGLException; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.DisplayMode; import org.lwjgl.opengl.GL11; /** * This is an application to show a seemingly * logical way of checking if a square is out * of bounds does not work as expected * * @author Timothy */ public class BoundaryDetectionApp { private static final int SQUARE_SIZE = 10; private static final int NUM_BOUNCES = 3; private static final int MAX_SQUARES = 100; public BoundaryDetectionApp() { } public static void main(String[] args) throws LWJGLException { BoundaryDetectionApp app = new BoundaryDetectionApp(); app.showExample(); } /** * Shows the example. The logic is tied to the framerate to * increase simplicity of the example. * * @throws LWJGLException if an lwjgl exception occurs */ public void showExample() throws LWJGLException { DisplayMode mode = new DisplayMode(640, 480); Display.setDisplayMode(mode); Display.create(); // init OpenGL GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glLoadIdentity(); GL11.glOrtho(0, 800, 0, 600, 1, -1); GL11.glMatrixMode(GL11.GL_MODELVIEW); GL11.glColor3f(0.5f, 0.05f, 0.05f); List<Point2D.Float> squares = new ArrayList<Point2D.Float>(); List<Point2D.Float> velocity = new ArrayList<Point2D.Float>(); List<Long> bounces = new ArrayList<Long>(); Random rnd = new Random(); while(!Display.isCloseRequested()) { GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); if(squares.size() < MAX_SQUARES && rnd.nextFloat() < 0.05) { // Always starts on the left of the screen going right squares.add(getRandomFloatPair(rnd, 0f, 480f, 0f, 10f)); velocity.add(getRandomFloatPair(rnd, 0.5f, 1f, 0.5f, 1f)); bounces.add(0l); } for(int i = 0; i < squares.size(); i++) { if(shouldBounceX(squares.get(i).x)) { bounces.set(i, bounces.get(i) + 1); velocity.get(i).x *= -1; } if(shouldBounceY(squares.get(i).y)) { bounces.set(i, bounces.get(i) + 1); velocity.get(i).y *= -1; } if(bounces.get(i) >= NUM_BOUNCES) { squares.remove(i); velocity.remove(i); bounces.remove(i); i--; continue; } squares.get(i).x += velocity.get(i).x; squares.get(i).y += velocity.get(i).y; // Draw the square GL11.glBegin(GL11.GL_QUADS); GL11.glVertex2f(squares.get(i).x, squares.get(i).y); GL11.glVertex2f(squares.get(i).x + SQUARE_SIZE, squares.get(i).y); GL11.glVertex2f(squares.get(i).x + SQUARE_SIZE, squares.get(i).y + SQUARE_SIZE); GL11.glVertex2f(squares.get(i).x, squares.get(i).y + SQUARE_SIZE); GL11.glEnd(); } Display.update(); Display.sync(60); } System.out.println("Closing..."); System.exit(0); } /** * Decides if the specified location is at the left/right * edge of the screen * * @param x the location * @return if it is on the edge of the screen and thus should bounce */ private boolean shouldBounceX(float x) { if(x <= 0 || x >= Display.getWidth() - SQUARE_SIZE) return true; return false; } /** * Decides if the specified location is at the top/bottom edge * of the screen * * @param y the location * @return if it is on the edge of the screen and thus should bounce */ private boolean shouldBounceY(float y) { if(y <= 0 || y >= Display.getHeight() - SQUARE_SIZE) return true; return false; } /** * Generates a random pair of floats between the specified * limits * @param gen the pseudo-random generator to use * @param minX the minimum x in the pair * @param maxX the maximum x in the pair * @param minY the minimum y in the pair * @param maxY the maximum y in the pair * @return a random pair of floats */ private Point2D.Float getRandomFloatPair(Random gen, float minX, float maxX, float minY, float maxY) { float x = minX + (gen.nextFloat() * (maxX - minX)); float y = minY + (gen.nextFloat() * (maxY - minY)); Point2D.Float res = new Point2D.Float(x, y); return res; } }
This should have been a simple application similiar to my first application in general java, however I can't get the collision detection for the 'walls' to work, even when the walls are as consistent as the edges of the screen. The result of getWidth and getHeight seem accurate, but the pixels do not fall under where they would be expected to. The methods in question are shouldBounceX and shouldBounceY.
Actual Output
Several squares 'bouncing' a few inches from the wall and ceiling on the top and the right. [Left and bottom are fine]
Expected Output
Squares bouncing off the actual edges of the screen.
Note on location: There isn't anything 'wrong' with the code, more like a theory / question in how to calculate the boundaries of the application, and as such is posted under Java Theory & Questions
~~~~Made with PostFactory by tjstretchalot