How does LibGDX FitViewport keep aspect ratio after resizing? - libgdx
I am a little bit confused why my FitViewport is not keeping the aspect ratio when resizing the window.
I thought that it should always keep the aspect ratio and then fill up the screen with black bars for areas which are not used.
However for me it is not keeping the aspect ratio and circles become ellipsis f.e. (see screenshots).
Code when creating my game renderer (32 and 18 are my world units)
viewport = new FitViewport(32, 18);
camera = viewport.getCamera();
visibleArea = new Rectangle(0, 0, viewport.getScreenWidth(), viewport.getScreenHeight());
scissors = new Rectangle();
Code when resizing the window
public void resize(int width, int height) {
Gdx.app.debug(TAG, "Resizing to " + width + " x " + height);
viewport.update(width, height);
visibleArea.set(0, 0, viewport.getScreenWidth(), viewport.getScreenHeight());
Render method
public void render(float alpha) {
viewport.calculateScissors(batch.getTransformMatrix(), visibleArea, scissors);
ScissorStack.pushScissors(scissors);
viewport.apply();
setView(camera.combined, visibleArea.x, visibleArea.y, visibleArea.width, visibleArea.height);
batch.begin();
// ...
batch.end();
ScissorStack.popScissors();
}
correct aspect ratio on startup
wrong aspect ratio on resize
Okay the problem actually was with my framebuffer light method (prepareLightFrameBuffer) which also had a call to batch.begin(); and batch.end().
It seems like this messes up the view (or resets it to something?). To solve the issue I just applied the viewport again and set the view again in the render method (Note: I also have a stage so I think that viewport.apply() has to be called here and also in the stage.render() method).
Here is the complete code of the GameRenderer if anyone is interested. I guess somehow it could be simplified but I am no OpenGL/Matrix expert so I have no idea how to do it :)
package com.lok.game;
import java.util.Comparator;
import com.badlogic.ashley.core.ComponentMapper;
import com.badlogic.ashley.core.Entity;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
import com.badlogic.gdx.maps.MapLayer;
import com.badlogic.gdx.maps.tiled.TiledMapImageLayer;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
import com.badlogic.gdx.maps.tiled.tiles.AnimatedTiledMapTile;
import com.badlogic.gdx.math.Intersector;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.lok.game.ecs.components.AnimationComponent;
import com.lok.game.ecs.components.CollisionComponent;
import com.lok.game.ecs.components.MapRevelationComponent;
import com.lok.game.ecs.components.SizeComponent;
import com.lok.game.map.Map;
import com.lok.game.map.Map.Portal;
import com.lok.game.map.MapManager;
public class GameRenderer extends OrthogonalTiledMapRenderer {
private final static String TAG = GameRenderer.class.getName();
private static class yPositionComparator implements Comparator<Entity> {
private final ComponentMapper<SizeComponent> sizeComponentMapper;
private yPositionComparator(ComponentMapper<SizeComponent> sizeComponentMapper) {
this.sizeComponentMapper = sizeComponentMapper;
}
#Override
public int compare(Entity o1, Entity o2) {
if (o1 == o2) {
return 0;
} else if (o1 == null) {
return -1;
} else if (o2 == null) {
return 1;
}
return sizeComponentMapper.get(o1).boundingRectangle.y > sizeComponentMapper.get(o2).boundingRectangle.y ? -1 : 1;
}
}
private SizeComponent cameraLockEntitySizeComponent;
private MapRevelationComponent cameraLockEntityRevelationComponent;
private Map map;
private TiledMapTileLayer groundLayer;
private final Array<TiledMapTileLayer> backgroundLayers;
private final Array<TiledMapTileLayer> foregroundLayers;
private TiledMapImageLayer lightMapLayer;
private final yPositionComparator entityComparator;
private final ComponentMapper<SizeComponent> sizeComponentMapper;
private final ComponentMapper<AnimationComponent> animationComponentMapper;
private final Camera camera;
private final Viewport viewport;
private final Rectangle visibleArea;
private final Rectangle scissors;
private final ShapeRenderer shapeRenderer;
private FrameBuffer frameBuffer;
private final AtlasRegion lightTexture;
private final AtlasRegion shadowTexture;
public GameRenderer() {
super(null, MapManager.WORLD_UNITS_PER_PIXEL);
if (Gdx.app.getLogLevel() == Application.LOG_DEBUG) {
Gdx.app.debug(TAG, "Creating in debug mode");
shapeRenderer = new ShapeRenderer();
} else {
Gdx.app.debug(TAG, "Creating in non-debug mode");
shapeRenderer = null;
}
viewport = new FitViewport(32, 18);
camera = viewport.getCamera();
visibleArea = new Rectangle();
scissors = new Rectangle();
this.backgroundLayers = new Array<TiledMapTileLayer>();
this.foregroundLayers = new Array<TiledMapTileLayer>();
this.sizeComponentMapper = ComponentMapper.getFor(SizeComponent.class);
this.animationComponentMapper = ComponentMapper.getFor(AnimationComponent.class);
this.entityComparator = new yPositionComparator(sizeComponentMapper);
final TextureAtlas textureAtlas = AssetManager.getManager().getAsset("lights/lights.atlas", TextureAtlas.class);
lightTexture = textureAtlas.findRegion("light");
shadowTexture = textureAtlas.findRegion("shadow");
frameBuffer = null;
}
public void setMap(Map map) {
this.map = map;
super.setMap(map.getTiledMap());
this.backgroundLayers.clear();
this.foregroundLayers.clear();
this.lightMapLayer = null;
for (MapLayer mapLayer : map.getTiledMap().getLayers()) {
if (mapLayer instanceof TiledMapTileLayer) {
if ("ground".equals(mapLayer.getName())) {
groundLayer = (TiledMapTileLayer) mapLayer;
} else if (mapLayer.getName().startsWith("background")) {
backgroundLayers.add((TiledMapTileLayer) mapLayer);
} else {
foregroundLayers.add((TiledMapTileLayer) mapLayer);
}
} else if (mapLayer instanceof TiledMapImageLayer) {
lightMapLayer = (TiledMapImageLayer) mapLayer;
}
}
}
public void resize(int width, int height) {
Gdx.app.debug(TAG, "Resizing with " + width + "x" + height + " from viewport " + viewport.getScreenWidth() + "x" + viewport.getScreenHeight());
viewport.update(width, height, false);
visibleArea.set(0, 0, viewport.getWorldWidth(), viewport.getWorldHeight());
Gdx.app.debug(TAG, "To viewport " + viewport.getScreenWidth() + "x" + viewport.getScreenHeight());
if (frameBuffer != null) {
frameBuffer.dispose();
}
try {
frameBuffer = FrameBuffer.createFrameBuffer(Pixmap.Format.RGBA8888, viewport.getScreenWidth(), viewport.getScreenHeight(), false);
} catch (GdxRuntimeException e) {
frameBuffer = FrameBuffer.createFrameBuffer(Pixmap.Format.RGB565, viewport.getScreenWidth(), viewport.getScreenHeight(), false);
}
}
public void lockCameraToEntity(Entity entity) {
if (entity == null) {
cameraLockEntitySizeComponent = null;
cameraLockEntityRevelationComponent = null;
} else {
cameraLockEntityRevelationComponent = entity.getComponent(MapRevelationComponent.class);
cameraLockEntitySizeComponent = entity.getComponent(SizeComponent.class);
if (cameraLockEntitySizeComponent == null) {
throw new GdxRuntimeException("Trying to lock camera to an entity without size component: " + entity);
}
}
}
private void interpolateEntities(float alpha) {
for (Entity entity : map.getEntities()) {
final SizeComponent sizeComp = sizeComponentMapper.get(entity);
final float invAlpha = 1.0f - alpha;
sizeComp.interpolatedPosition.x = sizeComp.interpolatedPosition.x * invAlpha + sizeComp.boundingRectangle.x * alpha;
sizeComp.interpolatedPosition.y = sizeComp.interpolatedPosition.y * invAlpha + sizeComp.boundingRectangle.y * alpha;
}
}
public void render(float alpha) {
AnimatedTiledMapTile.updateAnimationBaseTime();
interpolateEntities(alpha);
map.getEntities().sort(entityComparator);
if (cameraLockEntitySizeComponent != null) {
camera.position.set(cameraLockEntitySizeComponent.interpolatedPosition, 0);
visibleArea.setCenter(cameraLockEntitySizeComponent.interpolatedPosition);
}
prepareLightFrameBuffer();
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
viewport.apply();
setView(camera.combined, visibleArea.x, visibleArea.y, visibleArea.width, visibleArea.height);
batch.begin();
viewport.calculateScissors(batch.getTransformMatrix(), visibleArea, scissors);
ScissorStack.pushScissors(scissors);
if (groundLayer != null) {
renderTileLayer(groundLayer);
}
for (Entity entity : map.getEntities()) {
renderEntityShadow(entity);
}
for (TiledMapTileLayer layer : backgroundLayers) {
renderTileLayer(layer);
}
for (Entity entity : map.getEntities()) {
renderEntity(entity);
}
for (TiledMapTileLayer layer : foregroundLayers) {
renderTileLayer(layer);
}
batch.end();
applyLightFrameBuffer();
if (Gdx.app.getLogLevel() == Application.LOG_DEBUG) {
renderDebugInformation();
}
ScissorStack.popScissors();
}
private void renderEntityShadow(Entity entity) {
final AnimationComponent animationComp = animationComponentMapper.get(entity);
if (animationComp.animation != null) {
final SizeComponent sizeComp = sizeComponentMapper.get(entity);
if (!viewBounds.overlaps(sizeComp.boundingRectangle)) {
return;
}
if (cameraLockEntityRevelationComponent != null && !Intersector.overlaps(cameraLockEntityRevelationComponent.revelationCircle, sizeComp.boundingRectangle)) {
return;
}
batch.draw(shadowTexture, sizeComp.interpolatedPosition.x, sizeComp.interpolatedPosition.y - sizeComp.boundingRectangle.height * 0.2f, sizeComp.boundingRectangle.width,
sizeComp.boundingRectangle.height * 0.5f);
}
}
private void renderEntity(Entity entity) {
final AnimationComponent animationComp = animationComponentMapper.get(entity);
if (animationComp.animation != null) {
final SizeComponent sizeComp = sizeComponentMapper.get(entity);
if (!viewBounds.overlaps(sizeComp.boundingRectangle)) {
return;
}
if (cameraLockEntityRevelationComponent != null && !Intersector.overlaps(cameraLockEntityRevelationComponent.revelationCircle, sizeComp.boundingRectangle)) {
return;
}
final TextureRegion keyFrame = animationComp.animation.getKeyFrame(animationComp.animationTime, true);
batch.draw(keyFrame, sizeComp.interpolatedPosition.x, sizeComp.interpolatedPosition.y, sizeComp.boundingRectangle.width, sizeComp.boundingRectangle.height);
}
}
private void prepareLightFrameBuffer() {
if (cameraLockEntityRevelationComponent != null) {
frameBuffer.begin();
final Color mapBackgroundColor = map.getBackgroundColor();
Gdx.gl.glClearColor(mapBackgroundColor.r, mapBackgroundColor.g, mapBackgroundColor.b, mapBackgroundColor.a);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
setView(camera.combined, visibleArea.x, visibleArea.y, visibleArea.width, visibleArea.height);
batch.begin();
if (lightMapLayer != null) {
batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE);
renderImageLayer(lightMapLayer);
}
batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE);
final Rectangle boundingRectangle = cameraLockEntitySizeComponent.boundingRectangle;
batch.draw(lightTexture, cameraLockEntitySizeComponent.interpolatedPosition.x + boundingRectangle.width * 0.5f - cameraLockEntityRevelationComponent.revelationRadius, // x
cameraLockEntitySizeComponent.interpolatedPosition.y + boundingRectangle.height * 0.5f - cameraLockEntityRevelationComponent.revelationRadius, // y
cameraLockEntityRevelationComponent.revelationRadius * 2f, cameraLockEntityRevelationComponent.revelationRadius * 2f);
batch.end();
frameBuffer.end();
}
}
private void applyLightFrameBuffer() {
if (cameraLockEntityRevelationComponent != null) {
batch.setProjectionMatrix(batch.getProjectionMatrix().idt());
batch.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_COLOR);
batch.begin();
batch.draw(frameBuffer.getColorBufferTexture(), -1, 1, 2, -2);
batch.end();
}
}
private void renderDebugInformation() {
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeType.Line);
shapeRenderer.setColor(Color.RED);
for (Rectangle rect : map.getCollisionAreas()) {
shapeRenderer.rect(rect.x, rect.y, rect.width, rect.height);
}
for (Entity entity : map.getEntities()) {
final CollisionComponent collisionComponent = entity.getComponent(CollisionComponent.class);
final SizeComponent sizeComp = sizeComponentMapper.get(entity);
if (collisionComponent != null) {
shapeRenderer.setColor(Color.RED);
shapeRenderer.rect(sizeComp.interpolatedPosition.x + collisionComponent.rectOffset.x, sizeComp.interpolatedPosition.y + collisionComponent.rectOffset.y,
collisionComponent.collisionRectangle.width, collisionComponent.collisionRectangle.height);
}
if (sizeComp != null) {
shapeRenderer.setColor(Color.BLUE);
shapeRenderer.rect(sizeComp.interpolatedPosition.x, sizeComp.interpolatedPosition.y, sizeComp.boundingRectangle.width, sizeComp.boundingRectangle.height);
}
}
shapeRenderer.setColor(Color.BLUE);
for (Portal portal : map.getPortals()) {
shapeRenderer.rect(portal.getArea().x, portal.getArea().y, portal.getArea().width, portal.getArea().height);
}
if (cameraLockEntityRevelationComponent != null) {
shapeRenderer.setColor(Color.WHITE);
shapeRenderer.circle(cameraLockEntitySizeComponent.interpolatedPosition.x + cameraLockEntitySizeComponent.boundingRectangle.width * 0.5f,
cameraLockEntitySizeComponent.interpolatedPosition.y + cameraLockEntitySizeComponent.boundingRectangle.height * 0.5f,
cameraLockEntityRevelationComponent.revelationCircle.radius, 64);
}
shapeRenderer.end();
}
#Override
public void dispose() {
Gdx.app.debug(TAG, "Disposing Gamerenderer");
super.dispose();
if (shapeRenderer != null) {
shapeRenderer.dispose();
}
if (frameBuffer != null) {
frameBuffer.dispose();
}
}
}
Related
Unable to put swing's JPopupMenu to SystemTray [duplicate]
Currently, the PopupMenu will show up when I right-click on the TrayIcon in the SystemTray. However, I want it to do the same when I left-click on the TrayIcon. I thought I might accomplish this by using a mouseListener on the TrayIcon, but I don't know what method to invoke in the mouseClicked event to achieve the desired results. icon = new TrayIcon(img, tooltip, popup); icon.addMouseListener( new MouseAdapter() { public void mouseClicked(MouseEvent e) { popup.setEnabled(true); } }); Using the setEnabled() method does not make the popup menu appear when I left-click the TrayIcon. It actually has no noticeable effect. I'm wondering what method I should use in the mouseClicked() body in order to make the popup show up when it is left-clicked.
Basically, in your mouse listener, you need to determine which button was pressed (and optional, how many times). The critical piece of code is this... if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 1) { ... } I've also included some additional code that makes sure the popup does not cover the task bar and is displayed within the viewable area of the screen (it's a nit pick of mine ;)) public class TestTrayIcon02 { public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { #Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception ex) { } try { final TrayIcon ti = new TrayIcon(ImageIO.read(getClass().getResource("/Smiley.png")), "Have a nice day"); final JPopupMenu popup = new JPopupMenu(); JMenuItem mi = new JMenuItem("Get me some"); mi.addActionListener(new ActionListener() { #Override public void actionPerformed(ActionEvent e) { SystemTray.getSystemTray().remove(ti); System.exit(0); } }); popup.add(mi); ti.addMouseListener(new MouseAdapter() { #Override public void mouseClicked(MouseEvent e) { if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 1) { Rectangle bounds = getSafeScreenBounds(e.getPoint()); Point point = e.getPoint(); int x = point.x; int y = point.y; if (y < bounds.y) { y = bounds.y; } else if (y > bounds.y + bounds.height) { y = bounds.y + bounds.height; } if (x < bounds.x) { x = bounds.x; } else if (x > bounds.x + bounds.width) { x = bounds.x + bounds.width; } if (x + popup.getPreferredSize().width > bounds.x + bounds.width) { x = (bounds.x + bounds.width) - popup.getPreferredSize().width; } if (y + popup.getPreferredSize().height > bounds.y + bounds.height) { y = (bounds.y + bounds.height) - popup.getPreferredSize().height; } popup.setLocation(x, y); popup.setVisible(true); } } }); SystemTray.getSystemTray().add(ti); } catch (Exception ex) { ex.printStackTrace(); } } }); } public static Rectangle getSafeScreenBounds(Point pos) { Rectangle bounds = getScreenBoundsAt(pos); Insets insets = getScreenInsetsAt(pos); bounds.x += insets.left; bounds.y += insets.top; bounds.width -= (insets.left + insets.right); bounds.height -= (insets.top + insets.bottom); return bounds; } public static Insets getScreenInsetsAt(Point pos) { GraphicsDevice gd = getGraphicsDeviceAt(pos); Insets insets = null; if (gd != null) { insets = Toolkit.getDefaultToolkit().getScreenInsets(gd.getDefaultConfiguration()); } return insets; } public static Rectangle getScreenBoundsAt(Point pos) { GraphicsDevice gd = getGraphicsDeviceAt(pos); Rectangle bounds = null; if (gd != null) { bounds = gd.getDefaultConfiguration().getBounds(); } return bounds; } public static GraphicsDevice getGraphicsDeviceAt(Point pos) { GraphicsDevice device = null; GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice lstGDs[] = ge.getScreenDevices(); ArrayList<GraphicsDevice> lstDevices = new ArrayList<GraphicsDevice>(lstGDs.length); for (GraphicsDevice gd : lstGDs) { GraphicsConfiguration gc = gd.getDefaultConfiguration(); Rectangle screenBounds = gc.getBounds(); if (screenBounds.contains(pos)) { lstDevices.add(gd); } } if (lstDevices.size() > 0) { device = lstDevices.get(0); } else { device = ge.getDefaultScreenDevice(); } return device; } }
What you're trying to do is apparently not possible: You cannot show the PopupMenu with its show method since you need to specify a JComponent but your TrayIcon isn't one (weird enough though that TrayIcon still manages to do it, so apparently there is a way, don't ask me though..). So, as MadProgrammer suggested, you should try using JPopupMenu instead. Don't add it to your TrayIcon for that won't be possible, but display your JPopupMenu by adding a MouseListener to your TrayIcon. That should do the trick: final TrayIcon tray = new TrayIcon( img, tooltip, null); final JPopupMenu menu = new JPopupMenu(); ... // your menu initialization. tray.addMouseListener( new MouseAdapter() { #Override public void mouseClicked(MouseEvent evt) { menu.setLocation( evt.getPoint() ); menu.setVisible( true ); } }
libgdx snake logic explained
This is the code from a book I am reading. It is just a snake game. you can paste this code into editor and change 3 texture files to what you have on computer. The code works fine and this is probably really stupid, but I am unable to make the connection between snakeBody parts and their position. How exactly does the body of the snake(not the head) knows where it should go after the head of the snake changes position? Can you elaborate on this? Thank you // class 1/2: public class MyGdxGame extends Game { #Override public void create () { setScreen(new GameScreen()); } } class 2/2: package com.mygdx.game; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.ScreenAdapter; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.utils.Array; public class GameScreen extends ScreenAdapter{ private static final float MOVE_TIME = 0.5F; private static final int SNAKE_MOVEMENT = 32; private static final int RIGHT = 0; private static final int LEFT = 1; private static final int UP = 2; private static final int DOWN = 3; private SpriteBatch batch; private Texture snakeHead; private Texture snakeBody; private Texture apple; private boolean appleAvailable = false; private int appleX, appleY; private float timer = MOVE_TIME; private int snakeX = 0, snakeY = 0; private int snakeXBeforeUpdate = 0, snakeYBeforeUpdate = 0; private int snakeDirection = RIGHT; private Array<BodyPart> bodyParts = new Array<BodyPart>(); #Override public void show() { super.show(); batch = new SpriteBatch(); snakeHead = new Texture(Gdx.files.internal("snakehead.png")); snakeBody = new Texture(Gdx.files.internal("snakeBody.png")); apple = new Texture(Gdx.files.internal("apple.png")); } #Override public void render(float delta) { super.render(delta); queryInput(); timer -= delta; if (timer <= 0) { timer = MOVE_TIME; moveSnake(); checkForOutOfBounds(); updateBodyPartsPosition(); } checkAppleCollision(); checkAndPlaceApple(); clearScreen(); draw(); } private void queryInput() { boolean lPressed = Gdx.input.isKeyPressed(Input.Keys.LEFT); boolean rPressed = Gdx.input.isKeyPressed(Input.Keys.RIGHT); boolean uPressed = Gdx.input.isKeyPressed(Input.Keys.UP); boolean dPressed = Gdx.input.isKeyPressed(Input.Keys.DOWN); if (lPressed) snakeDirection = LEFT; if (rPressed) snakeDirection = RIGHT; if (uPressed) snakeDirection = UP; if (dPressed) snakeDirection = DOWN; } private void moveSnake() { snakeXBeforeUpdate = snakeX; snakeYBeforeUpdate = snakeY; switch (snakeDirection) { case RIGHT: { snakeX += SNAKE_MOVEMENT; return; } case LEFT: { snakeX -= SNAKE_MOVEMENT; return; } case UP: { snakeY += SNAKE_MOVEMENT; return; } case DOWN: { snakeY -= SNAKE_MOVEMENT; return; } } } private void checkForOutOfBounds() { if (snakeX >= Gdx.graphics.getWidth()) { snakeX = 0; } if (snakeX < 0) { snakeX = Gdx.graphics.getWidth() - SNAKE_MOVEMENT; } if (snakeY >= Gdx.graphics.getHeight()) { snakeY = 0; } if (snakeY < 0) { snakeY = Gdx.graphics.getHeight() - SNAKE_MOVEMENT; } } private void updateBodyPartsPosition() { if (bodyParts.size > 0) { BodyPart bodyPart = bodyParts.removeIndex(0); bodyPart.updateBodyPosition(snakeXBeforeUpdate, snakeYBeforeUpdate); bodyParts.add(bodyPart); } } private void checkAndPlaceApple() { if (!appleAvailable) { do { appleX = MathUtils.random(Gdx.graphics.getWidth() / SNAKE_MOVEMENT - 1) * SNAKE_MOVEMENT; appleY = MathUtils.random(Gdx.graphics.getHeight() / SNAKE_MOVEMENT - 1) * SNAKE_MOVEMENT; appleAvailable = true; } while (appleX == snakeX && appleY == snakeY); } } private void checkAppleCollision() { if (appleAvailable && appleX == snakeX && appleY == snakeY) { BodyPart bodyPart = new BodyPart(snakeBody); bodyPart.updateBodyPosition(snakeX, snakeY); bodyParts.insert(0,bodyPart); appleAvailable = false; } } private void clearScreen() { Gdx.gl.glClearColor(Color.BLACK.r, Color.BLACK.g, Color.BLACK.b, Color.BLACK.a); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); } private void draw() { batch.begin(); batch.draw(snakeHead, snakeX, snakeY); for (BodyPart bodyPart : bodyParts) { bodyPart.draw(batch); } if (appleAvailable) { batch.draw(apple, appleX, appleY); } batch.end(); } private class BodyPart { private int x, y; private Texture texture; public BodyPart(Texture texture) { this.texture = texture; } public void updateBodyPosition(int x, int y) { this.x = x; this.y = y; } public void draw(Batch batch) { if (!(x == snakeX && y == snakeY)) batch.draw(texture, x, y); } } }
First it moves the head in moveSnake(), making sure to keep track of where the head was before the move. Then in updateBodyPartsPosition() it puts the last piece of the body where the head was just moved from.
sleep function not working correctly
I am using the code below to make my splash screen package Splashscreentest; /* * SplashDemo.java * */ import java.awt.*; import java.awt.event.*; public class Splashscreentest extends Frame implements ActionListener { static void renderSplashFrame(Graphics2D g, int frame) { final String[] comps = {"foo", "bar", "baz"}; g.setComposite(AlphaComposite.Clear); g.fillRect(300,140,400,400); g.setPaintMode(); g.setColor(Color.BLACK); g.drawString("Loading "+comps[(frame/5)%3]+"...", 120, 150); } public Splashscreentest() { super("SplashScreen demo"); setSize(3000, 2000); setLayout(new BorderLayout()); Menu m1 = new Menu("File"); MenuItem mi1 = new MenuItem("Exit"); m1.add(mi1); mi1.addActionListener(this); this.addWindowListener(closeWindow); MenuBar mb = new MenuBar(); setMenuBar(mb); mb.add(m1); final SplashScreen splash = SplashScreen.getSplashScreen(); if (splash == null) { System.out.println("SplashScreen.getSplashScreen() returned null"); return; } Graphics2D g = splash.createGraphics(); if (g == null) { System.out.println("g is null"); return; } for(int i=0; i<100; i++) { renderSplashFrame(g, i); splash.update(); try { Thread.sleep(5000); } catch(InterruptedException ex) { } } splash.close(); setVisible(true); toFront(); } #Override public void actionPerformed(ActionEvent ae) { System.exit(0); } private static final WindowListener closeWindow = new WindowAdapter(){ #Override public void windowClosing(WindowEvent e){ e.getWindow().dispose(); } }; public static void main (String args[]) { } } The splash screen is not remaining on screen for the 5 seconds I would expect it to from the Thread.sleep command I used. The image for my splash screen is in this project within source packages
You're calling Thread.Sleep within the for loop. Change it to for(int i=0; i<100; i++) { renderSplashFrame(g, i); splash.update(); try { Thread.sleep(50); } catch(InterruptedException ex) { } }
JLabel will not change after button click
Basically, I want the text of 'lblIndividualScore' to change when the button 'btnCalculate' is clicked...but when i click it, the label doesn't change. I put a println right after it and I know that everything is being calculated correctly...it just won't change. below is the code portions, any ideas? Here is the action listener snippet else if (e.getSource() == btnCalculate) { setClassification(); setTargetOrLight(); setProneTotal(); setStandingTotal(); setKneelingTotal(); setIndividualTotal(); } Here is what the action listener calls public void setClassification() { classification = (String)cmbClassification.getSelectedItem(); if (classification.equals("Senior") && target) { txtProne2.setEditable(true); txtKneeling2.setEditable(true); txtStanding2.setEditable(true); txtProne2.setVisible(true); txtKneeling2.setVisible(true); txtStanding2.setVisible(true); lblStanding.setText("Standing"); lblKneeling.setText("Kneeling"); } else if (classification.equals("Intermediate") || (classification.equals("Senior") && !target)) { txtProne2.setEditable(false); txtKneeling2.setEditable(false); txtStanding2.setEditable(false); txtProne2.setVisible(false); txtKneeling2.setVisible(false); txtStanding2.setVisible(false); lblStanding.setText("Standing"); lblKneeling.setText("Kneeling"); } else { txtProne2.setEditable(false); txtKneeling2.setEditable(false); txtStanding2.setEditable(false); txtProne2.setVisible(false); txtKneeling2.setVisible(false); txtStanding2.setVisible(false); lblStanding.setText("Prone"); lblKneeling.setText("Prone"); } } public void setTargetOrLight() { if (((String)cmbTarget.getSelectedItem()).equals("Target Rifle")) { target = true; } else { target = false; } } public void setProneTotal() { try { if (classification.equals("Senior") && target) { int prone1 = 0; int prone2 = 0; prone1 = Integer.parseInt(txtProne1.getText()); prone2 = Integer.parseInt(txtProne2.getText()); proneTotal = prone1 + prone2; } else if (classification.equals("Intermediate") || (classification.equals("Senior") && !target)) { proneTotal = Integer.parseInt(txtProne1.getText()); } else { int prone1 = Integer.parseInt(txtProne1.getText()); int prone2 = Integer.parseInt(txtStanding1.getText()); int prone3 = Integer.parseInt(txtKneeling1.getText()); proneTotal = prone1 + prone2 + prone3; } } catch(NumberFormatException nfe) { System.err.println(nfe + ": You must enter a valid number - Prone"); } } public void setStandingTotal() { try { if (classification.equals("Senior") && target) { int standing1 = 0; int standing2 = 0; standing1 = Integer.parseInt(txtStanding1.getText()); standing2 = Integer.parseInt(txtStanding2.getText()); standingTotal = standing1 + standing2; } else if (classification.equals("Intermediate") || (classification.equals("Senior") && !target)) { standingTotal = Integer.parseInt(txtStanding1.getText()); } else { standingTotal = 0; } } catch (NumberFormatException nfe) { System.err.println(nfe + ": You must enter a valid number - Standing"); } } public void setKneelingTotal() { try { if (classification.equals("Senior") && target) { int kneeling1 = 0; int kneeling2 = 0; kneeling1 = Integer.parseInt(txtKneeling1.getText()); kneeling2 = Integer.parseInt(txtKneeling2.getText()); kneelingTotal = kneeling1 + kneeling2; } else if (classification.equals("Intermediate") || (classification.equals("Senior") && !target)) { kneelingTotal = Integer.parseInt(txtKneeling1.getText()); } else { kneelingTotal = 0; } } catch (NumberFormatException nfe) { System.err.println(nfe + ": You must enter a valid number - Kneeling"); } } public void setIndividualTotal() { individualTotal = proneTotal + kneelingTotal + standingTotal; lblIndividualTotal.setText("" + individualTotal); System.err.println(individualTotal); } As stated above, I have that end println 'System.err.println(individualTotal);' printing the total and it DOES print so the number is getting there but the lbl isn't changing. Please let me know if there is anything else that you need. EDIT: The setTexts in the setClassification() method also do not work.
Please post an SSCCE instead of long pieces of code. See below for an example SSCCE which updates the text of a JLabel when a JButton is pressed, and which works without any fancy steps. When you manage to create an SSCCE reproducing your problem, you most likely will know what causes your problem, and if not, we do not have to go through irrelevant lines of code import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import java.awt.EventQueue; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class ChangeLabelText { public static void main( String[] args ) { EventQueue.invokeLater( new Runnable() { #Override public void run() { JFrame frame = new JFrame( "TestFrame" ); JPanel content = new JPanel( new FlowLayout( ) ); final JLabel label = new JLabel( "Label" ); content.add( label ); JButton button = new JButton( "Change text" ); button.addActionListener( new ActionListener() { #Override public void actionPerformed( ActionEvent e ) { label.setText( "Another text" ); } } ); content.add( button ); frame.getContentPane().add( content ); frame.pack(); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame.setVisible( true ); } } ); } }
Trying To Render Scene To FBO Returns White
So this is what I'm trying to do. I'm trying to make a 2d game using LWJGL that has a dynamically generated terrain using images as tiles. It works fine, but when I try to do a zoom, the tiles get a dark shade on the edges and I get an extra pixel in-between tiles. Here's a screenshot of before and after zoom: Before and After Zoom Screenshot: http://postimage.org/image/rhuc9744/ I've looked and looked, and from what little I've gathered on the internet, I think the gist is that zoom is causing pixel-precision issues which gets worse after blending. I saw a blog saying I can overlap some pixels between tiles, but it seems too complicated. I've tried all blending options, and none of them worked. So I figured, I should just render all the tiles into a buffer, an FBO, and then apply it as one big texture, so even when I zoom, I won't see dark edges because it would all be just one giant picture. So I've read a lot of tutorials on FBO, but most if not all of them are meant for 3D, which I actually got working. The problem is when I apply it to 2d ortho. The code breaks and all I get is a white box. I've been stuck on this problem for days, and I can't seem to find an answer using google. Here's a sample code I'm t trying to get working: package com.helgravis; import static org.lwjgl.opengl.EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT; import static org.lwjgl.opengl.EXTFramebufferObject.GL_DEPTH_ATTACHMENT_EXT; import static org.lwjgl.opengl.EXTFramebufferObject.GL_FRAMEBUFFER_EXT; import static org.lwjgl.opengl.EXTFramebufferObject.GL_RENDERBUFFER_EXT; import static org.lwjgl.opengl.EXTFramebufferObject.glBindFramebufferEXT; import static org.lwjgl.opengl.EXTFramebufferObject.glBindRenderbufferEXT; import static org.lwjgl.opengl.EXTFramebufferObject.glFramebufferRenderbufferEXT; import static org.lwjgl.opengl.EXTFramebufferObject.glFramebufferTexture2DEXT; import static org.lwjgl.opengl.EXTFramebufferObject.glGenFramebuffersEXT; import static org.lwjgl.opengl.EXTFramebufferObject.glGenRenderbuffersEXT; import static org.lwjgl.opengl.EXTFramebufferObject.glRenderbufferStorageEXT; import static org.lwjgl.opengl.GL11.GL_INT; import static org.lwjgl.opengl.GL11.GL_RGBA; import static org.lwjgl.opengl.GL11.GL_RGBA8; import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; import static org.lwjgl.opengl.GL11.glBindTexture; import static org.lwjgl.opengl.GL11.glGenTextures; import static org.lwjgl.opengl.GL11.glTexImage2D; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.MediaTracker; import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; import java.awt.image.ComponentColorModel; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.Raster; import java.awt.image.WritableRaster; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; import java.util.Hashtable; import javax.swing.JPanel; import org.lwjgl.LWJGLException; import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.DisplayMode; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL14; public class AnFBOExample { private int width, height, canvasWidth = 800, canvasHeight = 600; private String title; private boolean bFullscreen; public int FRAMERATE = 60; public int framebufferID; public int framebufferTextureID, spriteTextureID; public int depthRenderBufferID; public int fboWidth = 100, fboHeight = 100; public AnFBOExample() { bFullscreen = false; } public AnFBOExample(boolean bFullscreen) { this.bFullscreen = bFullscreen; } public void setTitle(String title) { this.title = title; if(Display.isCreated()) Display.setTitle(title); } public String getTitle() { return title; } public void setResolution(int x, int y) { width = x; height = y; } public void setCanvasSize(int x, int y) { canvasWidth = x; canvasHeight = y; } private boolean initDisplayMode() throws Exception { if(bFullscreen) Display.setFullscreen(true); try { DisplayMode[] dm = org.lwjgl.util.Display.getAvailableDisplayModes(width, height, -1, -1, -1, -1, 60, 60); org.lwjgl.util.Display.setDisplayMode(dm, new String[] { "width=" + width, "height=" + height, "freq=" + FRAMERATE, "bpp="+ org.lwjgl.opengl.Display.getDisplayMode().getBitsPerPixel() } ); return true; } catch(Exception e) { e.printStackTrace(); System.out.println("Unable to enter fullscreen, continuing in windowed mode"); } return false; } public void init() throws Exception { try { initDisplayMode(); Display.create(); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glEnable(GL11.GL_ALPHA_TEST); GL11.glAlphaFunc(GL11.GL_GREATER, 0.5f); GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glLoadIdentity(); GL11.glOrtho(0, canvasWidth, canvasHeight, 0, -1, 1); int framebufferID = glGenFramebuffersEXT(); int colorTextureID = glGenTextures(); int depthRenderBufferID = glGenRenderbuffersEXT(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID); glBindTexture(GL_TEXTURE_2D, colorTextureID); GL11.glTexParameteri(GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, fboWidth, fboHeight, 0, GL_RGBA, GL_INT, (java.nio.ByteBuffer) null); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D, colorTextureID, 0); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthRenderBufferID); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL14.GL_DEPTH_COMPONENT24, fboWidth, fboHeight); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT,GL_RENDERBUFFER_EXT, depthRenderBufferID); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); BufferedImage image = loadImage("resources/lamp.png"); spriteTextureID = getTexture(image); } catch(LWJGLException le) { le.printStackTrace(); } } public void draw() { glBindTexture(GL_TEXTURE_2D, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID); GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); GL11.glPushMatrix(); GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glBindTexture(GL11.GL_TEXTURE_2D, spriteTextureID); GL11.glBegin(GL11.GL_QUADS); { GL11.glTexCoord2f(0, 0); GL11.glVertex2f(0, 0); GL11.glTexCoord2f(0, 1f); GL11.glVertex2f(0, 50f); GL11.glTexCoord2f(1f, 1f); GL11.glVertex2f(50f, 50f); GL11.glTexCoord2f(1f, 0); GL11.glVertex2f(50f, 0); } GL11.glEnd(); GL11.glPopMatrix(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); GL11.glPushMatrix(); GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glBindTexture(GL11.GL_TEXTURE_2D, framebufferTextureID); GL11.glTranslatef(100f, 100f, 0); GL11.glBegin(GL11.GL_QUADS); { GL11.glTexCoord2f(0, 0); GL11.glVertex2f(0, 0); GL11.glTexCoord2f(0, 1f); GL11.glVertex2f(0, 100f); GL11.glTexCoord2f(1f, 1f); GL11.glVertex2f(100f, 100f); GL11.glTexCoord2f(1f, 0); GL11.glVertex2f(100f, 0); } GL11.glEnd(); GL11.glPopMatrix(); Display.update(); Display.sync(FRAMERATE); } public void draw2() { // glBindTexture(GL_TEXTURE_2D, 0); // glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); GL11.glPushMatrix(); GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glBindTexture(GL11.GL_TEXTURE_2D, spriteTextureID); GL11.glBegin(GL11.GL_QUADS); { GL11.glTexCoord2f(0, 0); GL11.glVertex2f(0, 0); GL11.glTexCoord2f(0, 1f); GL11.glVertex2f(0, 50f); GL11.glTexCoord2f(1f, 1f); GL11.glVertex2f(50f, 50f); GL11.glTexCoord2f(1f, 0); GL11.glVertex2f(50f, 0); } GL11.glEnd(); GL11.glPopMatrix(); // glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); // GL11.glPushMatrix(); // GL11.glEnable(GL11.GL_TEXTURE_2D); // GL11.glBindTexture(GL11.GL_TEXTURE_2D, framebufferTextureID); // GL11.glTranslatef(100f, 100f, 0); // GL11.glBegin(GL11.GL_QUADS); // { // GL11.glTexCoord2f(0, 0); // GL11.glVertex2f(0, 0); // GL11.glTexCoord2f(0, 1f); // GL11.glVertex2f(0, 100f); // GL11.glTexCoord2f(1f, 1f); // GL11.glVertex2f(100f, 100f); // GL11.glTexCoord2f(1f, 0); // GL11.glVertex2f(100f, 0); // } // GL11.glEnd(); // GL11.glPopMatrix(); // // Display.update(); // Display.sync(FRAMERATE); } public void cleanup() { Display.destroy(); } public void run() { while(!Thread.interrupted()) { progress(); handleEvents(); draw(); //draw2(); } } public void handleEvents() { while(Keyboard.next()) if(Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) quit(); if(Display.isCloseRequested()) quit(); } public void quit() { System.exit(0); } public void progress() { //Add game logic here } protected static boolean waitForImage(Image image, Component c) { Image[] images = new Image[1]; images[0] = image; return waitForImages(images, c); } protected static boolean waitForImages(Image[] images, Component c) { MediaTracker tracker = new MediaTracker(c); for(int i=0; i<images.length; i++) tracker.addImage(images[i], 0); try { tracker.waitForAll(); } catch(InterruptedException ie) {} return !tracker.isErrorAny(); } public static BufferedImage loadImage(String imageFile) throws Exception { Image image = null; JPanel buffer = new JPanel(); image = buffer.getToolkit().getImage(imageFile); waitForImage(image, buffer); int width = image.getWidth(null); int height = image.getHeight(null); BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = bufferedImage.createGraphics(); g2d.drawImage(image, 0, 0, width, height, buffer); g2d.dispose(); return bufferedImage; } public int getTexture(BufferedImage image) throws Exception { return getTexture(image, GL11.GL_TEXTURE_2D, GL11.GL_RGBA, GL11.GL_LINEAR, GL11.GL_LINEAR); } public int getTexture(String resourceName, int target, int dstPixelFormat, int minFilter, int magFilter) throws Exception { BufferedImage bufferedImage = loadImage(resourceName); return getTexture(bufferedImage, target, dstPixelFormat, minFilter, magFilter); } private int createTextureID() { ByteBuffer temp = ByteBuffer.allocateDirect(4 * 1); temp.order(ByteOrder.nativeOrder()); IntBuffer tmp = temp.asIntBuffer(); GL11.glGenTextures(tmp); return tmp.get(0); } public int getTexture(BufferedImage bufferedImage, int target, int dstPixelFormat, int minFilter, int magFilter) throws Exception { int srcPixelFormat = 0; int textureID = createTextureID(); GL11.glBindTexture(target, textureID); if(bufferedImage.getColorModel().hasAlpha()) srcPixelFormat = GL11.GL_RGBA; else srcPixelFormat = GL11.GL_RGB; ByteBuffer textureBuffer = convertImageData(bufferedImage); if(target == GL11.GL_TEXTURE_2D) { GL11.glTexParameteri(target, GL11.GL_TEXTURE_MIN_FILTER, minFilter); GL11.glTexParameteri(target, GL11.GL_TEXTURE_MAG_FILTER, magFilter); } GL11.glTexImage2D(target, 0, dstPixelFormat, get2Fold(bufferedImage.getWidth()), get2Fold(bufferedImage.getHeight()), 0, srcPixelFormat, GL11.GL_UNSIGNED_BYTE, textureBuffer); return textureID; } private int get2Fold(int fold) { int ret = 2; while (ret < fold) ret *= 2; return ret; } #SuppressWarnings("rawtypes") private ByteBuffer convertImageData(BufferedImage bufferedImage) { ComponentColorModel glAlphaColorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] {8,8,8,8}, true, false, ComponentColorModel.TRANSLUCENT, DataBuffer.TYPE_BYTE); ComponentColorModel glColorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] {8,8,8,0}, false, false, ComponentColorModel.OPAQUE, DataBuffer.TYPE_BYTE); ByteBuffer imageBuffer = null; WritableRaster raster; BufferedImage texImage; int texWidth = 2; int texHeight = 2; while (texWidth < bufferedImage.getWidth()) texWidth *= 2; while (texHeight < bufferedImage.getHeight()) texHeight *= 2; if(bufferedImage.getColorModel().hasAlpha()) { raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, texWidth, texHeight, 4, null); texImage = new BufferedImage(glAlphaColorModel, raster, false, new Hashtable()); } else { raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, texWidth, texHeight, 3, null); texImage = new BufferedImage(glColorModel, raster, false, new Hashtable()); } Graphics g = texImage.getGraphics(); g.setColor(new Color(0f,0f,0f,0f)); g.fillRect(0,0,texWidth,texHeight); g.drawImage(bufferedImage,0,0,null); byte[] data = ((DataBufferByte) texImage.getRaster().getDataBuffer()).getData(); imageBuffer = ByteBuffer.allocateDirect(data.length); imageBuffer.order(ByteOrder.nativeOrder()); imageBuffer.put(data, 0, data.length); imageBuffer.flip(); return imageBuffer; } public static void main(String args[]) throws Exception { AnFBOExample window = new AnFBOExample(false); window.setResolution(800, 600); window.setCanvasSize(800, 600); window.init(); window.setTitle("FBO Test"); window.run(); } } The code loads an image in resource/lamp.png, which can be any .png file, and tries to render it to an FBO, then applies it as a texture in a 2d quad. For some reason, I only get a white blank quad when I try to bind the FBO as a texture. I'm not sure if I'm not rendering to the FBO properly, or I'm not binding it correctly. You can check the method draw() so you know what I'm talking about. Like I said, I've been stuck in this problem for day, so any help would be very much appreciated. resources/lamp.png: http://s3.postimage.org/rhpdn5ms/lamp.png?noCache=1315464566
framebufferTextureID, shouldn't it be colourTextureID?