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;
}
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
I am getting an error: java.lang.NullPointerException on Graphics g.
this is my code:
package main;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
public class main implements Runnable {
public static final int WIDTH = 1024;
public static final int HEIGHT = 1024;
public static final String TITLE = "platformer";
public boolean running = false;
static main home = new main();
public Graphics g;
public static Canvas canvas = new Canvas();
public static void main(String[] args) {
home.display();
home.start();
}
public void display(){
JFrame frame = new JFrame(TITLE);
frame.setSize(WIDTH, HEIGHT);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
canvas.setPreferredSize(new Dimension(WIDTH, HEIGHT));
frame.add(canvas);
}
BufferStrategy bs;
public void render(){
bs = main.getCanvas().getBufferStrategy();
if(bs == null){
main.getCanvas().createBufferStrategy(3);
}
g = bs.getDrawGraphics();
g.fillRect(0, 0, WIDTH, HEIGHT);
g.dispose();
bs.show();
}
public void tick(){
}
public void run(){
long lastTime = System.nanoTime();
final double amountofticks = 60;
double ns = 1000000000/amountofticks;
double delta = 0;
double time = 0;
int frames = 0;
while(running){
long now = System.nanoTime();
delta += (now-lastTime)/ns;
time += (now-lastTime);
lastTime = now;
if(delta>=1){
home.tick();
home.render();
delta--;
frames++;
}
if(time>1000000000){
System.out.println(frames);
time = 0;
frames = 0;
}
}
stop();
}
private Thread thread;
public void start(){
running = true;
thread = new Thread(this);
thread.start();
}
public static Canvas getCanvas(){
return canvas;
}
public void stop(){
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
i am getting the error message:
Exception in thread "Thread-2" java.lang.NullPointerException
at main.main.render(main.java:37)
at main.main.run(main.java:59)
at java.lang.Thread.run(Unknown Source)
line 37 is
g = bs.getDrawGraphics();
I think that the graphics is null for some reason.
i have tried to make this code for a long time
Change line
main.getCanvas().createBufferStrategy(3);
to
bs = main.getCanvas().createBufferStrategy(3);
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();
}
}
I'm trying to make a 2D tile based game. I have been encountering an issue when attempting to draw new graphics and the old ones don't seem to have been removed.
If anyone knows why g.dispose isn't clearing the graphics then please help.
Here's my "Main" class:
package Main;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
public class Main extends Canvas implements Runnable {
private static final long serialVersionUID = 1L;
private JFrame frame;
static int size = 40;
static int tilesX = 20;
static int tilesY = 20;
static int width = size * 10;
static int height = size * 10;
private boolean running = false;
public static STATE state = STATE.MENU;
public static PLAYER type = PLAYER.ARCHER;
private Thread thread;
static tileMap grid = new tileMap();
tile[][] map = tileMap.map;
public Main() {
addKeyListener(new controls());
addMouseListener(new mouse());
Dimension wSize = new Dimension(width, height);
setPreferredSize(wSize);
frame = new JFrame();
}
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) {
e.printStackTrace();
}
}
public enum STATE {
MENU, GAME
}
public enum PLAYER {
ARCHER, KNIGHT
}
public static void main(String[] args) {
Main game = new Main();
game.frame = new JFrame("Game");
game.frame.add(game);
game.frame.setResizable(false);
game.frame.pack();
game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.frame.setVisible(true);
game.start();
}
public void run() {
while (running) {
if (state == STATE.MENU) {
menu();
} else if (state == STATE.GAME) {
tick();
render();
}
try {
Thread.sleep(16);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void menu() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(2);
return;
}
Graphics g = bs.getDrawGraphics();
g.drawRect(Main.width / 8, 20, Main.width / 3, 200);
g.drawString("Archer", Main.width / 8, 20);
g.drawRect((Main.width - Main.width / 3) - Main.width / 8, 20,
Main.width / 3, 200);
g.drawString("Knight", (Main.width - Main.width / 3) - Main.width / 8,
20);
g.dispose();
bs.show();
}
private void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
Graphics2D d = (Graphics2D) g;
camera.setCam();
g.translate(-camera.camX, -camera.camY);
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
d.setColor(map[i][j].getC());
d.fillRect(map[i][j].getX(), map[i][j].getY(), Main.size, Main.size);
d.setColor(Color.BLACK);
d.drawRect(map[i][j].getX(), map[i][j].getY(), Main.size, Main.size);
}
}
map[player.p.getX()][player.p.getY()].setC(player.p.getC());
if (type == PLAYER.ARCHER) {
d.drawString("Archer", 5, 15);
} else if (type == PLAYER.KNIGHT) {
d.drawString("Knight", 5, 15);
}
g.dispose();
bs.show();
}
static public void moved() {
tileMap.map[player.p.getX()][player.p.getY()].setC(Color.GREEN);
}
private void tick() {
if (player.p == null) {
player.createP();
}
}
}
Graphics#dispose releases any internal resources that the Graphics context may be holding, reducing the memory overhead, it does not "clear" the context.
From the JavaDocs
Disposes of this graphics context and releases any system resources that it is using. A Graphics object cannot be used after dispose has been called.
What it doesn't do is effect the underlying content, that would be, well, annoying, as using a copy of a Graphics object is a good and easy way to make complex changes without effecting the original context.
To "clear" the context you could use fillRect to paint a color/background before you performing you next cycle of painting. Do this just after Graphics g = bs.getDrawGraphics();
I was trying to follow these tutorials http://zetcode.com/tutorials/javagamestutorial/animation/ and none of the three examples on that page seem to be working for me. One of them uses a swing timer, one uses the utility timer, and the last and supposedly most effective and accurate according to the page uses a thread to animate.
I will show you the one using the thread, since it is the way that I think I will be doing thing's when using animation for making games.
ThreadAnimationExample.java (in the tutorial it is called star.java but obviously that wont work)
import java.awt.EventQueue;
import javax.swing.JFrame;
public class ThreadAnimationExample extends JFrame {
public ThreadAnimationExample() {
add(new Board());
setTitle("Star");
pack();
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame ex = new ThreadAnimationExample();
ex.setVisible(true);
}
});
}
}
Board.java (the main class)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class Board extends JPanel
implements Runnable {
private final int B_WIDTH = 350;
private final int B_HEIGHT = 350;
private final int INITIAL_X = -40;
private final int INITIAL_Y = -40;
private final int DELAY = 25;
private Image star;
private Thread animator;
private int x, y;
public Board() {
loadImage();
initBoard();
}
private void loadImage() {
ImageIcon ii = new ImageIcon("star.png");
star = ii.getImage();
}
private void initBoard() {
setBackground(Color.BLACK);
setPreferredSize(new Dimension(B_WIDTH, B_HEIGHT));
setDoubleBuffered(true);
x = INITIAL_X;
y = INITIAL_Y;
}
#Override
public void addNotify() {
super.addNotify();
animator = new Thread(this);
animator.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
drawStar(g);
}
private void drawStar(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(star, x, y, this);
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
private void cycle() {
x += 1;
y += 1;
if (y > B_HEIGHT) {
y = INITIAL_Y;
x = INITIAL_X;
}
}
#Override
public void run() {
long beforeTime, timeDiff, sleep;
beforeTime = System.currentTimeMillis();
while (true) {
cycle();
repaint();
timeDiff = System.currentTimeMillis() - beforeTime;
sleep = DELAY - timeDiff;
if (sleep < 0) {
sleep = 2;
}
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
System.out.println("Interrupted: " + e.getMessage());
}
beforeTime = System.currentTimeMillis();
}
}
}
If you are using Eclipse you should create a source folder and add that image to the source folder. Then you could use this:
ImageIcon ii = new ImageIcon( getClass().getResource("/imageName.png") );
I am just starting to get into graphics and when I am trying to get the graphics, I get the error"run:
Exception in thread "Thread-2" java.lang.NullPointerException
at gamedev.Display.render(Display.java:97)
at gamedev.Display.run(Display.java:108)
at java.lang.Thread.run(Thread.java:724)"
and I have no clue on what is going on! Any help is greatly appreciated.
//The display class for the game
//Crated: 10-30-2013
//Last Modified: 10-30-2013
package gamedev;
import gamedev.Graphics.Render;
import gamedev.Graphics.Screen;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.JFrame;
public class Display extends Canvas implements Runnable {
public static final int GAMEWIDTH = 600;
public static final int GAMEHEIGHT = 600;
private static Thread thread;
private static boolean running = false;
private Render render;
private Screen screen;
private BufferedImage img;
private int[] pixels;
public static void main(String[] args) {
System.out.println("display.main");
Display gameWindow = new Display();
JFrame gameFrame = new JFrame();
gameFrame.add(gameWindow);
gameFrame.setResizable(false);
gameFrame.setVisible(true);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
gameFrame.setLocation(dim.width / 2 - gameFrame.getSize().width / 2, dim.height / 2 - gameFrame.getSize().height / 2);
gameFrame.setSize(GAMEWIDTH, GAMEHEIGHT);
gameFrame.setTitle("Game Frame");
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gameWindow.start();
}
public Display() {
System.out.println("display.Display");
screen = new Screen(GAMEWIDTH, GAMEHEIGHT);
img = new BufferedImage(GAMEWIDTH, GAMEHEIGHT, BufferedImage.TYPE_INT_RGB);
pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
}
private void start() {
System.out.println("display.Started");
if(running)
return;
running = true;
thread = new Thread(this);
thread.start();
}
private String stop() {
System.out.println("display.Stopped");
if (!running) {
System.out.println("running");
running = false;
try {
thread.join();
} catch (Exception e) {
System.exit(0);
return e.getStackTrace().toString();
}
return "Program Stopped";
} else {
return "Program Not Stopped";
}
}
private void tick() {
}
private void render() {
System.out.println("display.render");
BufferStrategy bs = this.getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
}
for (int i = 0; i < GAMEWIDTH * GAMEHEIGHT; i++) {
pixels[i] = screen.PIXELS[i];
}
screen.Render();
Graphics g = bs.getDrawGraphics();
g.drawImage(img, 0, 0, GAMEWIDTH, GAMEHEIGHT, null);
g.dispose();
bs.show();
}
#Override
public void run() {
System.out.println("display.run");
while (running) {
tick();
render();
}
}
}
Change this:
BufferStrategy bs = this.getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
}
to:
BufferStrategy bs = this.getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
bs = this.getBufferStrategy();
}
The problem is that if bs is null, you create a buffer strategy but don't assign anything to bs.