I searched so long for a solution to run a simple LWJGL application on my MacBook Pro with Retina display. The problem is that the Retina display is flickering. But I just found uninformative hints.
Do you know any code solution to handle this? For example changing the viewport or something?
What have I to add to the following code?
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
public class MainDisplay {
final int DISPLAY_WIDTH = 640;
final int DISPLAY_HEIGHT = 480;
public void start() {
try {
Display.setDisplayMode(new DisplayMode(DISPLAY_WIDTH, DISPLAY_HEIGHT));
Display.create();
}
catch(LWJGLException exception) {
exception.printStackTrace();
}
while(!Display.isCloseRequested()) {
Display.update();
}
Display.destroy();
}
}
Did you actually try to render anything?
It sounds like the back buffer contains garbage data, and you're not painting anything in that loop. Every time you invoke the Display.update() it flips the back-buffer, and if you've not painted on it then you get the flickering of garbage data.
Try something like:
while(!Display.isCloseRequested()) {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glEnd();
Display.update();
}
Which clears the display before flipping the back-buffer.
In general, if you don't actually display anything then you're at the whims of the graphics driver and memory as to what ends up on the screen. If I used your code, I see the following in the window:
Related
I downloaded LWJGL 3 today, and found out that it was almost completly rewritten. I looked up a tutorial on how to create a window, but I still have problems creating a window.
The code runs without problems: no errors in the console, but the window isn't displayed!
I hope you can help me, I searched a lot for LWJGL 3 tutorials, but they seem pretty old, so I decided to ask my question here.
Here's my code:
//EDIT: Changed my code so everything runs in one thread but it still doesn' t work. Even System.out.println() doesn't work. No console output is displayed!
//IMPORTANT: I just realized that this may be a bug in GLFW (I'm working on Linux) !
package net.newworld.test;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.Version;
import org.lwjgl.glfw.GLFWVidMode;
public class Main {
private static long window;
private static int width = 1280;
private static int height = 800;
private static void init() {
glfwInit();
System.out.println("Initializing LWJGL...");
System.out.println("LWJGL Version: "+ Version.getVersion());
glfwWindowHint(GLFW_VISIBLE, GL_FALSE); //Set window visible after creation
window = glfwCreateWindow(width, height, "New World", 0, 0);
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); //Get primary monitor
glfwSetWindowPos(window, (vidmode.width() - width) / 2, (vidmode.height() - height) / 2); //Set window position
glfwMakeContextCurrent(window); //Make OpenGL contect current
glfwShowWindow(window); //Show window
}
public static void main(String[] args) {
init();
}
}
The problem might be that you forgot to add the window proc loop (which is blocking)
public static void main(String[] args) {
init();
while (!glfwWindowShouldClose(window)) {
glfwWaitEvents();
}
}
I have made it open a full screen window but now how can i create a button to have it exit the application?
Also, do you know any good tutorials to learn. I can't seem to find many?
Lastly can i use the opengl code that i learn to work with java in c++ or is that opengl completely different?
This is the code i have:
package game;
import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.opengl.*;
import org.lwjgl.*;
public class Main {
public Main() {
try {
Display.setDisplayMode(Display.getDesktopDisplayMode());
Display.setFullscreen(true);
Display.create();
} catch(LWJGLException e) {
e.printStackTrace();
}
}
}
lwjgl does not provide any high level widgets such as buttons. You'll need to draw the button using gl calls (use the button image as texture for a quad. Start with a colored rectangle before trying textures). Then you'll need to check for mouse click events in the button area. You may want to consider using a higher level library on top of lwjgl to simplify this.
Here is some code that I made that draws and handles buttons.
You can specify the X, Y and Texture of each button and when the button is clicked the variable isClicked becomes true. As for closing the application , use
if(EXITBUTTON.isClicked)
{
System.exit(0);
}
Button Class:
You need LWJGL and Slick Util.
import java.awt.Rectangle;
import java.io.IOException;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.newdawn.slick.Color;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;
public class Button {
public int X;
public int Y;
public Texture buttonTexture;
public boolean isClicked=false;
Rectangle bounds = new Rectangle();
public void addButton(int x, int y , String TEXPATH){
X=x;
Y=y;
try {
buttonTexture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream(TEXPATH));
System.out.println(buttonTexture.getTextureID());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bounds.x=X;
bounds.y=Y;
bounds.height=buttonTexture.getImageHeight();
bounds.width=buttonTexture.getImageWidth();
System.out.println(""+bounds.x+" "+bounds.y+" "+bounds.width+" "+bounds.height);
}
public void Draw(){
if(bounds.contains(Mouse.getX(),(600 - Mouse.getY()))&&Mouse.isButtonDown(0)){
isClicked=true;
}else{
isClicked=false;
}
Color.white.bind();
buttonTexture.bind(); // or GL11.glBind(texture.getTextureID());
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0,0);
GL11.glVertex2f(X,Y);
GL11.glTexCoord2f(1,0);
GL11.glVertex2f(X+buttonTexture.getTextureWidth(),Y);
GL11.glTexCoord2f(1,1);
GL11.glVertex2f(X+buttonTexture.getTextureWidth(),Y+buttonTexture.getTextureHeight());
GL11.glTexCoord2f(0,1);
GL11.glVertex2f(X,Y+buttonTexture.getTextureHeight());
GL11.glEnd();
}
}
In Java, I have successfully displayed an image on the screen. Now I want to make it move by running it through a for loop. The for loop runs 10 times and sleeps for 1 second each time. Instead of moving the image every second as expected, I have to wait 10 seconds, then 10 images show up.
Here's my code:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class ImageDraw extends JComponent {
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Image img1 = Toolkit.getDefaultToolkit().getImage("player.png");
int x = 0;
int y = 0;
for(int i = 0;i<10;i++){
try {
Thread.sleep(1000);
x+=10;
y+=10;
g2.drawImage(img1, x, y, this);
repaint();
} catch (InterruptedException e) {
e.printStackTrace();
System.exit(0);
}
} //end for
} //end paint
} //end class
How would I make it so the image looks as if it's moving everytime it runs through the loop?
In addition to other suggestions:
Never read the image in the painting method. Read the image when you construct the class or pass in the image with a setImage(...) method.
Custom painting is done by overriding the paintComponent() method, not the paint() method.
Use a Timer for this, and get rid of the Thread.sleep(). You're running this code on the UI thread, and when you call Thread.sleep() you're putting the UI thread to sleep, which means no updating until the entire loop is complete.
I want to create a splash screen for my Java application. I managed to do this using the NetBeans default tool that allows me to put some image in. But i want to have something "live" there, such as a progress bar showing the status of application load, some dynamic text, etc.
How do I do this? What are the things I need to know to start doing something like this?
Here is the Java tutorial walking you through exactly what you want to do. You can set the image on the command line so that it shows immediately, then you can manipulate it once the JVM is initialized to add text, progress bars, etc.
http://download.oracle.com/javase/tutorial/uiswing/misc/splashscreen.html
The trick is to create a splash screen using swing and then invoke using Java reflection the method, which is in another .java file, that loades the application. When done loading, dispose your splash screen.
After checking the code, you will understand how it works and now customize it your own way.
Here is some code:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JDialog;
/**
*
* #author martijn
*/
public class Splash {
public static void splash() {
try {
final BufferedImage img = ImageIO.read(Splash.class.getResourceAsStream("/path/to/your/splash/image/splash.png"));
JDialog dialog = new JDialog() {
#Override
public void paint(Graphics g) {
g.drawImage(img, 0, 0, null);
}
};
// use the same size as your image
dialog.setPreferredSize(new Dimension(450, 300));
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog.setUndecorated(true);
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
dialog.repaint();
try {
// Now, we are going to init the look and feel:
Class uim = Class.forName("javax.swing.UIManager");
uim.getDeclaredMethod("setLookAndFeel", String.class).invoke(null, (String) uim.getDeclaredMethod("getSystemLookAndFeelClassName").invoke(null));
// And now, we are going to invoke our loader method:
Class clazz = Class.forName("yourpackage.YourClass");
dialog.dispose();
// suppose your method is called init and is static
clazz.getDeclaredMethod("init").invoke(null);
} catch (Exception ex) {
ex.printStackTrace();
}
dialog.dispose();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
I'm learning Java by making a small game in a JApplet.
I got a little problem with my sprite's animation.
Here is the code :
this.sprite.setBounds(0,0,20,17);
this.sprite.setIcon(this.rangerDown);
for(int i = 0; i< 16;i++)
{
this.sprite.setBounds(this.sprite.getX(), this.sprite.getY()+1, 20, 17);
this.sprite.update(this.sprite.getGraphics());
try{
Thread.currentThread().sleep(100);
}catch(InterruptedException e){
}
}
It left some flicker during the animation. Once the animation end, the flicker disappears, but it's kind of ugly... I guess there is some step I missed.
I use this method because it gives the better result for now, but I would like to stay without AWT if possible, using Swing instead.
Any ideas how to get rid of the flicker?
Thanks for reading.
Screenshoot (Can't post images, sorry).
This is not a shadow. Its the border of your sprite. It just happens to be black and appears as a shadow. If you change the amount you shift your sprite (lets say by 50 pixels, not just 1) you will see what i mean.
To fix it what you need to do is to draw the background as well each time you update the location of your sprite. Although this will probably produce flickering.
The correct way to do it is to change the way you draw your objects. You need to override the paintComponent method of your panel and then simply call repaint each time you have updated the locations of your sprites.
EDIT:
See this code sample for basic usage. NOTE: This is NOT how you should write animation using Threads. I wrote that to show you what goes in the paintComponent method and wrote the animation Thread to show you that the "shadow" you mentioned is gone. NEVER have a non ending run loop in a thread :)
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
JFrame f = new JFrame("Test");
MyPanel c = new MyPanel();
f.getContentPane().add(c);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(350, 100);
f.setVisible(true);
}
}
class MyPanel extends JPanel {
int x = 0;
boolean toTheRight = true;
public MyPanel() {
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
x = (toTheRight)?x+5:x-5;
if (x>300)
toTheRight = false;
if (x<0)
toTheRight = true;
repaint();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g.create();
g2.setPaint(Color.white);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setPaint(Color.red);
g2.fillOval(x-2, 50, 4, 4);
}
}
The problem is double buffering.
In Applets:
Double buffering is done almost automatically. Call repaint() instead of paint in your method.
In Swing, there are many ways to do it. I usually go for the BufferStrategy route. When you're initializing your frame, do this:
JFrame frame;
... code to init frame here
frame.createBufferStrategy(2);
Then in your draw methods:
Graphics g = getBufferStrategy().getDrawGraphics();
..code to do drawing here...
g.dispose();
getBufferStrategy().show();