BufferStrategy and Graphics g - java

I have a sprite sheet that I want to use in a src folder within the project. Here is some code I have for a simple game I am making. I get an error when trying to draw anything with the paintbrush or (g). Can you help me figure out what is wrong?
I have a pre-existing background that I want to draw the images over. I deleted the code, the background image isn't what's causing the issues.
package NewCards;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferStrategy;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Game extends JFrame implements Runnable {
/**
*
*/
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private boolean live = false; //running
private boolean dead = false;
//instances of external classes here.
private Thread thread;
/**
* Launch the application.
*/
//initialize here.
public void init() {
}
private synchronized void start() {
if (running)
return;
live = true;
thread = new Thread(this);
thread.start();
}
private synchronized void stop() {
if(!running)
return;
try {
thread.join(); //attempts to join threads, if unsuccessful, throw Exception error.
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.exit(1);
}
public void run() {
init();
long lasttime = System.nanoTime();
final double amountofticks = 60.0;
double ns = 1000000000 / amountofticks;
double delta = 0;
int update = 0;
int frames = 0;
long timer = System.currentTimeMillis();
// TODO Auto-generated method stub
while (running) {
long now = System.nanoTime();
delta += (now - lasttime) / ns;
lasttime = now;
if (delta >= 1) {
tick();
update++;
delta--;
}
render();
frames++;
if(System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.println(update + " Frames, FPS: " + frames);
update = 0; // resets fps for updates. If not the beats would just double.
frames = 0; // statement above applies here in terms of FPS
}
}
stop();
}
private void tick(){
}
private void render() {
BufferStrategy bs = this.getBufferStrategy();
if (bs== null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.fillRect(1, 1, 200, 500);
g.dispose();
bs.show();
}
public static void main(String[] args) {
final Game game = new Game(); //game starter.
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Game frame = new Game();
JLabel backgroundImage = new JLabel();
backgroundImage.setSize(800, 800);
frame.getContentPane().add(backgroundImage);
Image background = new ImageIcon(this.getClass().getResource("/Artificial intelligence.png")).getImage();
backgroundImage.setIcon(new ImageIcon(background));
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
game.start();
}
});
}
/**
* Create the frame.
*/
public Game() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 800, 800);
setTitle("MyEmpire-1.1.1/Windows/Display/Menus/Loop");
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
}
}

Related

Getting java.io.IOException: closed whenever I close my program

Every time I Run my program it runs fine. But when I close it after running the program for a few seconds, then I get the java.io.IOException: closed error. I've tried looking around and couldn't find a solution. The only fix I could find was just not using the e.printstacktrace in the try-catch block, but that obviously doesn't fix the issue. Here is the Code:
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Main extends Canvas implements Runnable{
private static final long serialVersionUID = -661485289446387445L;
private Thread thread;
public int blackPos;
public int whitePos;
public boolean isWhiteTurn; // In single player this determines board orientation, in multiplayer it doesn't
public boolean running;
public final int HEIGHT = 800;
public final int WIDTH = 1200;
//public File[] imgSrc = {new File("/images/urBoard.png"), new File("/rsc/urBackground.jpg")};
public BufferedImage[] img = new BufferedImage[2];
public Board board;
public Main() {
new Window(WIDTH, HEIGHT, this);
board = new Board(this);
}
public void run()
{
requestFocus();
long lastTime = System.nanoTime();
double amountOfTicks = 60.0D;
double ns = 1.0E9D / amountOfTicks;
double delta = 0.0D;
long timer = System.currentTimeMillis();
int frames = 0;
while (this.running)
{
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 1.0D)
{
tick();
delta -= 1.0D;
}
if (this.running) {
render();
}
frames++;
if (System.currentTimeMillis() - timer > 1000L)
{
timer += 1000L;
System.out.println("FPS: " + frames);
frames = frames;
frames = 0;
}
}
}
public synchronized void start() {
thread = new Thread(this);
thread.start();
running=true;
}
public synchronized void stop() {
try
{
this.thread.join();
this.running = false;
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void tick() {
board.tick();
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if(bs == null) {
createBufferStrategy(3);
return;
}
try {
img[0] = ImageIO.read(getClass().getResource("/rsc/urBoard.png"));
img[1] = ImageIO.read(getClass().getResource("/rsc/urBackground.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
Graphics g = bs.getDrawGraphics();
g.drawImage(img[1], 0, 0, WIDTH, HEIGHT, null);
g.setColor(Color.GREEN);
g.drawLine(200, 0, 200, 800);
g.setFont(new Font("times new roman", Font.BOLD, 30));
g.drawString("END PIECES", 10, 30);
board.render(g);
g.dispose();
bs.show();
}
public static void main(String[] args) {
new Main();
}
}
and here is the error that I get whenver I close the GUI after it has ran for a couple seconds:
java.io.IOException: closed
at javax.imageio.stream.ImageInputStreamImpl.checkClosed(ImageInputStreamImpl.java:110)
at javax.imageio.stream.ImageInputStreamImpl.close(ImageInputStreamImpl.java:857)
at javax.imageio.stream.FileCacheImageInputStream.close(FileCacheImageInputStream.java:250)
at javax.imageio.ImageIO.read(ImageIO.java:1451)
at javax.imageio.ImageIO.read(ImageIO.java:1400)
at main.Main.render(Main.java:99)
at main.Main.run(Main.java:54)
at java.lang.Thread.run(Thread.java:745)
I've noticed that if I close the window right after i start the program the error doesn't come. It only comes when I've run the program for about 3-4 seconds, and then I close the window. What would cause this to happen, and what would be the fix?
It looks like your render() method may be running when closing the app. As your resources aren't changing between render() calls, move this block to the start of the Main() constructor so that img[] is set up once, and throws an exception if resources are not found:
try {
img[0] = ImageIO.read(getClass().getResource("/rsc/urBoard.png"));
img[1] = ImageIO.read(getClass().getResource("/rsc/urBackground.jpg"));
} catch (IOException e) {
throw new RuntimeException("Could not find resources");
}
The field running is used in different threads so it should be marked volatile in order that each thread reads consistent values:
public volatile boolean running;

Why is my eclipse not setting my background color?

I have designed a code for a game. The problem is that the background won't change to any of my selected colors I have picked from graphics color library.
I need someone to figure this out with the code i have provided (please don't make a whole new code). idk why java/ eclipse won't display it??? am i missing something?? The program here should display a GUI with a background color blue. instead i get white.
public class MainApp extends Canvas implements Runnable {
private static final long serialVersionUID = 8928635543572788908L;
private static final int WIDTH= 648, HEIGHT= WIDTH/ 12 * 9;
private Thread thread;
private boolean running= false;
public MainApp()
{
new Window(WIDTH, HEIGHT, "App", this);
}
public synchronized void start()
{
thread= new Thread(this);
thread.start();
running= true;
}
public void run()
{
long lastTime= System.nanoTime();
double amountOfTicks= 60.0;
double ns= 1000000000 / amountOfTicks;
double delta= 0;
long timer= System.currentTimeMillis();
int frames= 0;
while(running){
long now= System.nanoTime();
delta += (now- lastTime) / ns;
lastTime= now;
while(delta >= 1){
tick();
delta--;
}
if(running)
render();
frames++;
if(System.currentTimeMillis() - timer > 1000)
{
timer += 1000;
System.out.print("FPS: " + frames);
frames= 0;
}
}
stop();
}
public synchronized void stop()
{
try
{
thread.join();
running= false;
}catch(Exception e){e.printStackTrace();}
}
public void tick()
{
}
public void render()
{
BufferStrategy bs= this.getBufferStrategy();
if(bs== null)
{
this.createBufferStrategy(3);
return;
}
Graphics g= bs.getDrawGraphics();
g.setColor(Color.BLUE);
g.fillRect(0, 0, WIDTH, HEIGHT);
g.dispose();
bs.show();
}
public static void main(String[] args) {
new MainApp();
}
}
Your codes a little messed up, you shouldn't be making a new instance of Window from MainApp, the Window should be creating it (IMHO).
Also, you should be overriding the getPreferredSize method the the MainApp, as this is what should be controlling the viewable size of the window, this way, when you use pack on the JFrame, it will ensure that the window is larger then the preferredSize of it's contents, allowing the frame decorations to wrap around the outside of it.
BUT, the main problem you have, is adding the MainApp to the JFrame AFTER it's already been made visible
The following works for me...
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 MainApp extends Canvas implements Runnable {
private static final long serialVersionUID = 8928635543572788908L;
private static final int WIDTH = 648, HEIGHT = WIDTH / 12 * 9;
private Thread thread;
private boolean running = false;
public MainApp() {
new Window("App", this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(WIDTH, HEIGHT);
}
public synchronized void start() {
thread = new Thread(this);
thread.start();
running = true;
}
public void run() {
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
int frames = 0;
while (running) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 1) {
tick();
delta--;
}
if (running) {
render();
}
frames++;
if (System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.print("FPS: " + frames);
frames = 0;
}
}
stop();
}
public synchronized void stop() {
try {
thread.join();
running = false;
} catch (Exception e) {
e.printStackTrace();
}
}
public void tick() {
}
public void render() {
BufferStrategy bs = this.getBufferStrategy();
if (bs == null) {
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(Color.BLUE);
g.fillRect(0, 0, WIDTH, HEIGHT);
g.dispose();
bs.show();
}
public static void main(String[] args) {
new MainApp();
}
public static class Window {
private Window(String title, MainApp app) {
JFrame frame = new JFrame(title);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(app);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
app.start();
}
}
}

How to change color of a Window (Problems with Buffer Strategy )

I have been trying to follow a simple tutorial online(https://www.youtube.com/watch?v=1gir2R7G9ws). When I try to enter the code that he enters I don't get the same results. Some things that I type end up as errors that it can't use. It happens particularly when I try to use GetBufferStrategy. I'm not quite sure what is wrong with my code. I could really use some help.
Here's what I've got :
package components;
import java.awt.*;
import java.awt.image.BufferStrategy;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LayoutManager;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.*;
import javax.swing.*;
/* FrameDemo.java requires no other files. */
public class Window {
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private Thread thread;
private boolean running = false;
public synchronized void start(){
thread = new Thread();
thread.start();
running = true;
}
public synchronized void stop(){
try{
thread.join();
running=false;
}catch(Exception e) {
e.printStackTrace();
}
}
public void run(){
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
int frames = 0;
while(running)
{
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >=1)
{
tick();
delta--;
}
if(running)
render();
frames++;
if(System.currentTimeMillis() - timer > 1000)
{
timer += 1000;
System.out.println("FPS: "+ frames);
frames = 0;
}
}
stop();
}
private void tick(){
}
private void render() {
BufferStrategy bs = this.getBufferStrategy();
if (bs==null){
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(Color.black);
g.fillRect(0,0,873,374);
g.dispose();
bs.show();
}
private void createBufferStrategy(int i) {
}
private BufferStrategy getBufferStrategy() {
return null;
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("Mr. Krebs");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel emptyLabel = new JLabel("");
emptyLabel.setPreferredSize(new Dimension(1000, 700));
frame.getContentPane().add(emptyLabel, BorderLayout.CENTER);
//Display the window.
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Your class should extend Canvas:
public class Window extends Canvas {
...
}
In your render() method you're using this.getBufferStrategy and this.createBufferStrategy. Since those two instructions calls methods that are in the Canvas class if you don't type extends Canvas, you'll get errors because those methods can't be found.

Graphics.drawimage not working Java 8

I have been using Graphics.drawImage for a very long time to render images, but after I installed java 8, it stopped working. There are no errors. I don't understand what's going on.
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
public class Game implements Runnable {
private BufferedImage img = new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);
private boolean running;
private Thread thread;
private JFrame f;
private Canvas c;
public Game() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gs = ge.getScreenDevices();
for (GraphicsDevice gd : gs) {
GraphicsConfiguration[] gc = gd.getConfigurations();
for (GraphicsConfiguration gc1 : gc) {
f = new JFrame("Title", gd.getDefaultConfiguration());
c = new Canvas(gc1);
f.getContentPane().add(c);
f.setUndecorated(false);
f.setIgnoreRepaint(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(700, 600);
f.setResizable(false);
f.setLocationRelativeTo(null);
f.setFocusable(true);
f.setVisible(true);
}
}
}
public void init() {
img.getGraphics().drawImage(img, 0, 0, Color.BLACK, null);
}
#Override
public void run() {
long lastTime = System.nanoTime();
double nsPerTick = 1000000000D / 60;
int ticks = 0;
int frames = 0;
long lastTimer = System.currentTimeMillis();
double delta = 0;
init();
while (running) {
long now = System.nanoTime();
delta += (now - lastTime) / nsPerTick;
lastTime = now;
boolean shouldRender = true;
while (delta >= 1) {
ticks++;
tick();
delta -= 1;
shouldRender = true;
}
try {
Thread.sleep(2);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
if (shouldRender) {
frames++;
render();
}
if (System.currentTimeMillis() - lastTimer >= 1000) {
lastTimer += 1000;
frames = 0;
ticks = 0;
}
}
}
public synchronized void start() {
running = true;
thread = new Thread(this, "GAME");
thread.start();
}
public synchronized void stop() {
running = false;
try {
thread.join();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
public static void main(String[] args) {
new Game().start();
}
public void tick() { /*player movement, ect*/ }
public void render() {
c.createBufferStrategy(3);
BufferStrategy bs = c.getBufferStrategy();
Graphics g = bs.getDrawGraphics();
g.drawImage(img, 100, 100, null);
//I should also not that strings won't draw either.
g.drawString("Hello, world", 50, 50);
g.dispose();
bs.show();
}
}
I don't understand why this wouldn't be working, because it was working fine in java 7, and I did not make any changes to my code before or after I installed java 8.
Also I am using a MacBook pro if that helps.
On Mac OS X version 10.9.4, I can verify that createBufferStrategy(2) works under Java 8, while createBufferStrategy(3) fails unless I revert to Java 7. As an aside, note that Swing GUI objects should be constructed and manipulated only on the event dispatch thread.
As tested:
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import java.awt.EventQueue;
public class Game implements Runnable {
private BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
private boolean running;
private Thread thread;
private JFrame f;
private Canvas c;
public Game() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gs = ge.getScreenDevices();
for (GraphicsDevice gd : gs) {
GraphicsConfiguration[] gc = gd.getConfigurations();
for (GraphicsConfiguration gc1 : gc) {
f = new JFrame("Title", gd.getDefaultConfiguration());
c = new Canvas(gc1);
f.add(c);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setSize(360, 300);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
}
public void init() {
img.getGraphics().drawImage(img, 0, 0, Color.BLUE, null);
}
#Override
public void run() {
long lastTime = System.nanoTime();
double nsPerTick = 1000000000D / 60;
int ticks = 0;
int frames = 0;
long lastTimer = System.currentTimeMillis();
double delta = 0;
init();
while (running) {
long now = System.nanoTime();
delta += (now - lastTime) / nsPerTick;
lastTime = now;
boolean shouldRender = true;
while (delta >= 1) {
ticks++;
tick();
delta -= 1;
shouldRender = true;
}
try {
Thread.sleep(2);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
if (shouldRender) {
frames++;
render();
}
if (System.currentTimeMillis() - lastTimer >= 1000) {
lastTimer += 1000;
frames = 0;
ticks = 0;
}
}
}
public synchronized void start() {
running = true;
thread = new Thread(this, "GAME");
thread.start();
}
public synchronized void stop() {
running = false;
try {
thread.join();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Game().start();
}
});
}
public void tick() { /*player movement, ect*/ }
public void render() {
c.createBufferStrategy(2);
BufferStrategy bs = c.getBufferStrategy();
Graphics g = bs.getDrawGraphics();
g.drawImage(img, 100, 100, null);
g.drawString("Hello, world: " + System.currentTimeMillis(), 50, 50);
g.dispose();
bs.show();
}
}

Run Method is called, but Wont Draw

If you run the program, you can see that it prints "Run() method is called", when the run gets called. But the System.out.println() inside the if statement does not get called nor the render() method gets called.
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
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;
public static String TITLE = "";
private Thread thread;
private boolean running = false;
private JFrame frame;
public void start() {
if(running) return;
thread = new Thread(this);
thread.start();
}
public void stop() {
if(!running) return;
try{
thread.join();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
System.out.println("Run() has been called");
long lastTime = System.nanoTime();
long timer = System.currentTimeMillis();
double ns = 1000000000.0 / 60.0;
double delta = 0;
int ticks = 0;
int fps = 0;
while(running) {
long now = System.nanoTime();
delta += (now-lastTime) / ns;
lastTime = now;
while(delta >= 1) {
tick();
ticks++;
delta--;
}
render();
fps++;
if(System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.println("Fps: " + fps + " Ticks: " + ticks);
fps = 0;
ticks = 0;
}
}
stop();
}
public void tick() {
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if(bs==null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.fillRect(36, 25, 25, 25);
g.dispose();
bs.show();
}
public Game() {
setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
frame = new JFrame();
}
public static void main(String[] args) {
Game game = new Game();
game.frame.setResizable(false);
game.frame.setTitle("SPACE ADAPT PRE-ALPHA 0.001");
game.frame.add(game);
game.frame.pack();
game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.frame.setLocationRelativeTo(null);
game.frame.setVisible(true);
game.start();
}
}
You never set running to true, then it's false. As a side note not related with this question but most of swing components methods are not thread-safe so calling in another thread that is not the Event Dispatch Thread would not work as you expected.
Read more Concurrency in Swing

Categories