Java - Won't display a black screen - java

My Java program won't display a black screen when I tell it to. I can just see a greyish window with 0 FPS.
Here is my code:
package com.none.rain;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
public class Game extends Canvas implements Runnable {
private static final long serialVersionUID = 1L;
public static int width = 300;
public static int height = width / 16 * 9;
public static int scale = 3;
private boolean running = false;
private JFrame frame;
private Thread thread;
public Game() {
Dimension size = new Dimension(width*scale, height*scale);
setPreferredSize(size);
frame = new JFrame();
}
public synchronized void start() {
running = true;
thread = new Thread(this, "Display");
thread.start();
}
public synchronized void stop() {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
while (running) {
}
}
public void update() {
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.dispose();
bs.show();
}
public static void main(String[] args) {
Game game = new Game();
game.frame.setResizable(false);
game.frame.setTitle("Rain");
game.frame.add(game);
game.frame.pack();
game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.frame.setLocationRelativeTo(null);
game.frame.setVisible(true);
game.start();
}
}

Making the display black is something you do in your render() method, but you never call it.
If I take your code and add a call to render() in the run() method I get a frame with a black background:
public void run() {
while (running) {
render();
}
}

Related

Java graphics don't work?

I'm trying to make a game with a youtube tutorial and I am currently attempting to create and fill a rectangle the size of the window. Instead of going black, it stays grey (my default colour).
Any ideas? Thanks in advance!
Code:
import javax.swing.*;
import java.awt.image.BufferStrategy;
import java.awt.*;
public class Game extends Canvas implements Runnable {
private static final long serialVersionUID = 1L;
public static int width = 300;
public static int height = width / 16 * 9;
public static int scale = 3;
private Thread thread;
private JFrame frame; // Creates a window
private boolean running = false; // Checks to see if the game is running
public Game() {
Dimension size = new Dimension(width * scale, height * scale); // The window size
setPreferredSize(size); // Choosing the size I want
frame = new JFrame(); // Calling the frame
}
public synchronized void start() {
running = true;
thread = new Thread(new Game(), "Display"); // Calling the class
thread.start(); // Starting the class
}
public synchronized void stop() { // Ending the game
running = false;
try {
thread.join();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
while(running) {
update();
render();
}
}
public void update() {
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if(bs == null) {
createBufferStrategy(3); // Triple buffering strategy (speeds up process)
return;
}
Graphics g = bs.getDrawGraphics(); // Create a link between buffer and drawing on screen
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.dispose();
bs.show();
}
public static void main(String[] args) {
Game game = new Game(); // Calling the class to be able to change things in it
game.frame.setResizable(true); // Stopping window changing in size (causes graphical errors)
game.frame.setTitle("Game Window");
game.frame.add(game); // Fills the window with the class (can be done because of 'Canvas')
game.frame.pack(); // Sets the size of the window based on what is in the component above.
game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.frame.setLocationRelativeTo(null); // Centres the window in the screen
game.frame.setVisible(true);
game.start(); // Starts the game
}
}
Change thread = new Thread(new Game(), "Display"); to use this instead of new Game().

System Freezes upon Running this code

I'm following a Java game programming series on youtube, and all have been going well until we add some code to the program. The code for the program is:
package com.fagyapong.rain;
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
public class Game extends Canvas implements Runnable{
private static final long serialVersionUID = -247215114548172830L;
public static int width = 300;
public static int height = width / 16 * 9;
public static int scale = 3;
private JFrame frame;
public Thread thread;
private boolean running = false;
public Game() {
// Setup Game window
Dimension size = new Dimension(width * scale, height * scale);
setPreferredSize(size);
frame = new JFrame();
}
public synchronized void start() {
running = true;
thread = new Thread(this, "Display");
thread.start();
}
public synchronized void stop() {
running = false;
try {
thread.join();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
while (running) {
update();
render();
}
}
public void update() {
}
public void render() {
// Get the canvas' BufferStragy object
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(Color.GRAY);
g.fillRect(0, 0, getWidth(), getHeight());
g.dispose();
bs.show();
}
public static void main(String[] args) {
Game game = new Game();
game.frame.setResizable(false);
game.frame.setTitle("Rain");
game.frame.add(game);
game.frame.pack();
game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.frame.setLocationRelativeTo(null);
game.frame.setVisible(true);
game.start();
}
}
Below is code that causes the system freeze(it has been commented out in the above code)
Graphics g = bs.getDrawGraphics();
g.setColor(Color.GRAY);
g.fillRect(0, 0, getWidth(), getHeight());
g.dispose();
bs.show();
Okay, I figured out the problem a bit. I was having the same issue. The issue for me was the triple buffering. Instead, set the code to:
createBufferStrategy(2);
That way it's only double buffering. I don't have a fantastic computer, so I had to set it to 1 instead of 2. At that point, my guess is that it's not buffering at all. This is how I got it to work though.

Why Won't the Screen Change Color

I looked and the codes seems fine to me. Got an error but hopefully it's the source code, not something wrong with the cpu I have nor JDK.
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.*;
import javax.swing.JFrame;
public class Game extends Canvas implements Runnable {
public static int width = 300;
public static int height = width / 16*9;
public static int scale = 3;
private Thread thread;
private boolean running = false;
private JFrame frame;
public synchronized void start() {
running = true;
thread = new Thread(this, "Display");
thread.start();
}
public synchronized void stop() {
running = false;
try{
thread.join();
}catch(InterruptedException e){
e.printStackTrace();
}
}
public void run(){
while(running){
tick();
render();
}
}
public void tick() {
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if(bs==null){
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
bs.dispose();
bs.show();
}
public Game() {
Dimension size = new Dimension(width * scale, height * scale);
setPreferredSize(size);
frame = new JFrame();
}
public static void main(String[] args) {
Game game = new Game();
game.frame.setResizable(false);
game.frame.setTitle("Title");
game.frame.add(game);
game.frame.pack();
game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.frame.setLocationRelativeTo(null);
game.frame.setVisible(true);
game.start();
}
}
Then I got this error, even when I countlessly modified the source code I had.
Exception in thread "Display" java.lang.NullPointerException
at java.awt.Component$BltBufferStrategy.showSubRegion(Component.java:4307)
at java.awt.Component$BltBufferStrategy.show(Component.java:4255)
at com.thecherno.Rain.Game.render(Game.java:58)
at com.thecherno.Rain.Game.run(Game.java:39)
at java.lang.Thread.run(Thread.java:695)
Im starting to seem if it because of an outdated JDK. Current Version I have is JDK 6.
You state:
What Im trying to do is change color as seen in the render method. The background to be black.
Use Swing components such as a JComponent or JPanel.
Simply call setBackground(Color.BLACK) on the component will do.
You appear to be creating a game loop of some type. Consider using a Swing Timer for this.
e.g.,
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Game2 extends JPanel {
private static final int PREF_W = 300;
private static final int PREF_H = PREF_W / 16 * 9;
private static final int SCALE = 3;
private static final Color BACKGROUND = Color.BLACK;
private static final int TIMER_DELAY = 20;
private Timer swingTimer;
public Game2() {
setBackground(BACKGROUND);
swingTimer = new Timer(TIMER_DELAY, new TimerListener());
swingTimer.start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// TODO: add any custom painting here
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W * SCALE, PREF_H * SCALE);
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// TODO add code that gets called in game loop
}
}
private static void createAndShowGui() {
Game2 mainPanel = new Game2();
JFrame frame = new JFrame("Game2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Note that this code is based on your stated requirements and what I'm guessing are other requirements based on your code. If there are further requirements not mentioned, please elaborate them for us.
Try using g.dispose(); followed by bs.show(); and then
g = (Graphics2D)bs.getDrawGraphics();. I know it looks weird, but you are emptying the canvas and then refilling it using your strategy. You may also need to do an initial check for g being null and initialize it before the first display loop.

java - BufferStrategy is not creating stategy? (nullpointerexception)

I decided to start understanding BufferStrategy for my graphics.
I'm not sure if using my jframe in a static form is what's cause this, but it looks alright to me. What am I missing?
Main.java
package Main;
import java.awt.Toolkit;
public class Main implements Runnable {
private Thread gameThread;
private Game game;
private boolean running = false;
public static ClientFrame frame;
public static Toolkit kit;
public static int WIDTH = 300, HEIGHT = WIDTH*16/9, SCALE = 3;
public Main() {
game = new Game();
frame = new ClientFrame(game);
kit = frame.getToolkit();
frame.setVisible(true);
start();
}
public synchronized void start() {
running = true;
gameThread = new Thread(this);
gameThread.start();
}
public synchronized void stop() {
running = false;
gameThread.interrupt();
}
public void run() {
long startTime = System.nanoTime();
double nanoSec = 1000000000/60;
double delta = 0;
while(running) {
long currentTime = System.nanoTime();
delta += (currentTime - startTime)/nanoSec;
while(delta >= 1) {
game.update();
delta--;
}
game.render();
startTime = currentTime;
}
}
public static void main(String[] args) {
new Main();
}
}
Game.java
package Main;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import javax.swing.JPanel;
public class Game extends JPanel {
Player player;
int tileArea = 32;
public Game() {
player = new Player();
setPreferredSize(new Dimension(Main.WIDTH*Main.SCALE, Main.HEIGHT*Main.SCALE));
}
public void update() {
}
public void render() {
BufferStrategy bs = Main.frame.getBufferStrategy();
if(bs == null)
Main.frame.createBufferStrategy(3);
Graphics g = bs.getDrawGraphics();
player.paint(g);
g.dispose();
bs.show();
}
}
My Player.java only contains one method:
public void paint(Graphics g) {
g.fillRect(25, 25, 50, 50);
}
ERROR:
Exception in thread "Thread-2" java.lang.NullPointerException
at Main.Game.render(Game.java:30)
at Main.Main.run(Main.java:52)
at java.lang.Thread.run(Unknown Source)
You do not try to get the buffer strategy after you have created it:
BufferStrategy bs = Main.frame.getBufferStrategy();
if(bs == null)
Main.frame.createBufferStrategy(3);
// if bs was null before, it still is null
Graphics g = bs.getDrawGraphics();
Also note the point by #MadProgrammer that the buffer strategy belongs to a different component. If your intent is to create an AWT game (I'd recommend swing instead), you should probably use Canvas, and its createBufferStrategy().
try replacing
if(bs == null)
Main.frame.createBufferStrategy(3);
with
if (bs == null) {
Main.frame.crcreateBufferStrategy(3);
return;
}

Why won't this draw the image?

What I'm trying to do is make it so when I run my application, it starts the thread and the image is shown for 3 seconds (3000ms), then the thread stops running.
The path for the image is correct, the image file exists, and the thread itself runs; however, the image doesn't seem to show. What could be wrong? Here is my code:
package org.main;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class Splasher extends JPanel implements Runnable {
private static final long serialVersionUID = 1L;
Image image;
ImageIcon splash = new ImageIcon("res/splash.png");
public static Thread DrawSplash = new Thread(new Splasher());
public Splasher() {
setFocusable(true);
image = splash.getImage();
repaint();
}
boolean hasRan = false;
public void run() {
try {
System.out.println("Drawing Splash Screen");
repaint();
Thread.sleep(3000);
System.out.println("Repainted");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void paint(Graphics g) {
g.drawImage(image, 0, 0, null);
}
public Image getImage() {
return image;
}
}
There's not enough to go from you question.
You don't show how you use the splash screen, if it's attached to anything or how you start/use the Thread.
So the problem could be anything...
In addition to everything else VishalK has already pointed out, I would add public static Thread DrawSplash = new Thread(new Splasher()) is a bad idea. You shouldn't use static Threads are threads are non-reentrant, that is, you can run the same thread twice.
This is a little example demonstrating a "fading" splash screen, using a number of Swing Timers
This assumes you're using Java 7, there is away to make it work for Java 6, I've not posted that code.
public class TestSplashScreen01 {
public static void main(String[] args) {
new TestSplashScreen01();
}
public TestSplashScreen01() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
SplashScreen splash = new SplashScreen();
splash.start();
}
});
}
public class SplashScreen extends JWindow {
private SplashPane splash;
public SplashScreen() {
setBackground(new Color(0, 0, 0, 0));
splash = new SplashPane();
add(splash);
pack();
setLocationRelativeTo(null);
}
public void start() {
splash.start();
}
public class SplashPane extends JPanel {
private BufferedImage splash;
private Timer timer;
private float alpha = 0f;
private int duration = 1000;
private long startTime = -1;
public SplashPane() {
try {
splash = ImageIO.read(getClass().getResource("/res/SokahsScreen.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
timer = new Timer(3000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
fadeOut();
}
});
timer.setRepeats(false);
}
protected void fadeOut() {
Timer fadeInTimer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
long now = System.currentTimeMillis();
long runTime = now - startTime;
alpha = 1f - ((float) runTime / (float) duration);
if (alpha <= 0.01f) {
alpha = 0f;
((Timer) (e.getSource())).stop();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
dispose();
}
});
}
repaint();
}
});
startTime = System.currentTimeMillis();
fadeInTimer.setRepeats(true);
fadeInTimer.setCoalesce(true);
fadeInTimer.start();
}
protected void fadeIn() {
Timer fadeInTimer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
long now = System.currentTimeMillis();
long runTime = now - startTime;
alpha = (float) runTime / (float) duration;
if (alpha >= 1f) {
alpha = 1f;
((Timer) (e.getSource())).stop();
timer.start();
}
repaint();
}
});
startTime = System.currentTimeMillis();
fadeInTimer.setRepeats(true);
fadeInTimer.setCoalesce(true);
fadeInTimer.start();
}
public void start() {
if (!SplashScreen.this.isVisible()) {
alpha = 0f;
SplashScreen.this.setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
fadeIn();
}
});
}
}
#Override
public Dimension getPreferredSize() {
return splash == null ? super.getPreferredSize() : new Dimension(splash.getWidth(), splash.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (splash != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));
int x = (getWidth() - splash.getWidth()) / 2;
int y = (getHeight() - splash.getHeight()) / 2;
g2d.drawImage(splash, x, y, this);
g2d.dispose();
}
}
}
}
}
NB:
The problem with this example is once you call start, the program will continue to execute, this will require some kind of listener to tell interested parties when the splash screen has completed.
Alternatively, you could use a undecorated modal JDialog
Many mistakes that you have done in your code...
You have overriden paint method instead of paintComponent to draw Image.
You have used Thread for drawing and removing image on Swing component (JPanel). You should use javax.swing.Timer instead.
Although you should use javax.swing.Timer , but still the basic mistake that you did is that You have created a static Thread and within that passed a new object of Splasher instead of current object.
Each Time you want to make changes in the Graphics of a Component You should call repaint explicitly. For example, If you want to make the image to disappear after 3 seconds you should call repaint method after 3 seconds laps , and should have the proper logic written inside paintComponent method to remove that image.
Here is the modified version of your code , which is doing exactly what you are looking for.Have a look on it.:
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentAdapter;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.Timer;
import javax.swing.SwingUtilities;
public class Splasher extends JPanel {
private static final long serialVersionUID = 1L;
Image image;
ImageIcon splash = new ImageIcon("apple.png");
MyComponentListener componentListener ;
Timer timer ;
public Splasher()
{
componentListener = new MyComponentListener();
setFocusable(true);
image = splash.getImage();
timer = new Timer(3000, new LoadAction());
addComponentListener(componentListener);
}
boolean hasRan = false;
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if (image == null && timer !=null )
{
g.clearRect(0, 0, getWidth(), getHeight()) ;
timer.stop();
removeComponentListener(componentListener);
}
else
{
g.drawImage(image, 0, 0, null);
}
}
public Image getImage()
{
return image;
}
private class MyComponentListener extends ComponentAdapter
{
#Override
public void componentResized(ComponentEvent evt)
{
System.out.println("Resized..");
timer.start();
}
}
private class LoadAction implements ActionListener
{
public void actionPerformed(ActionEvent evt)
{
System.out.println("Drawing Splash Screen");
repaint();
image = null;
repaint();
System.out.println("Repainted");
}
}
public static void main(String st[])
{
SwingUtilities.invokeLater ( new Runnable()
{
#Override
public void run()
{
JFrame frame = new JFrame("Splash:");
frame.getContentPane().add(new Splasher());
frame.setSize(300,500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
}
Also Watch the following tutorial for Paint mechanism in java. http://docs.oracle.com/javase/tutorial/uiswing/painting/closer.html

Categories