When I run my game the JFrame is just white. Can someone explain?
I have no idea why this is happening and I'm having a really hard time finding out what could be the issue. I hope one of you can explain/know the answer. I look forward to hearing your answer and I would love to continue coding but I'm stuck atm, - Artycal.
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.io.IOException;
public class Game extends Canvas implements Runnable {
static GraphicsDevice device = GraphicsEnvironment
.getLocalGraphicsEnvironment().getScreenDevices()[0];
private static JFrame frame;
private static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
private BufferedImage image = new BufferedImage((int)width, (int)height, BufferedImage.TYPE_INT_ARGB);
private BufferedImage spriteSheet = null;
private static double width = screenSize.getWidth();
private static double height = screenSize.getHeight();
private boolean running;
private Thread thread;
private BufferedImage player;
public void init() {
BufferedImageLoader loader = new BufferedImageLoader();
try{
spriteSheet = loader.loadImage("/sprite_sheet.png");
}catch (IOException e){
e.printStackTrace();
}
SpriteSheet ss = new SpriteSheet(spriteSheet);
player = ss.grabImage(1, 1, 32, 32);
}
public void run() {
init();
long lastTime = System.nanoTime();
final double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
int updates = 0;
int frames = 0;
long timer = System.currentTimeMillis();
while (running){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
if (delta >= 1){
tick();
updates++;
delta--;
}
render();
frames++;
if (System.currentTimeMillis() - timer > 1000){
timer += 1000;
System.out.println(updates + " Ticks, Fps " + frames);
updates = 0;
frames = 0;
}
}
stop();
}
private void render() {
BufferStrategy bs = this.getBufferStrategy();
if (bs == null){
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(new Color(81, 218, 221));
g.drawRect(0, 0, getWidth(), getHeight());
g.setColor(new Color(81, 218, 221));
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
g.setColor(new Color(255, 174, 80));
g.drawImage(player, 100, 100, this);
g.dispose();
bs.show();
}
private void tick() {
}
public static void main(String[] args){
Game game = new Game();
frame = new JFrame("Game");
frame.setMaximumSize(new Dimension((int)width, (int)height));
frame.setMinimumSize(new Dimension((int)width, (int)height));
frame.setPreferredSize(new Dimension((int)width, (int)height));
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.add(game);
frame.pack();
frame.setVisible(true);
//device.setFullScreenWindow(frame);
game.start();
}
private synchronized void start() {
if (running)
return;
running = true;
thread = new Thread(this);
thread.start();
}
private synchronized void stop() {
if (!running)
return;
running = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.exit(1);
}
}
some things to note:
INT_ARGB for BufferedImage has a default alpha of 0 (completely clear) so unless you change the alpha value of the pixels you wont see anything.
drawRect draws only the outline of the rectangle. use fillRect to draw the entire rectangle.
as far as I know, drawing BufferedImages does not use the current color of the Graphics object as they are mainly defined as a rectangle made of different colored pixels. try drawing to the Images own Graphics object if you want to change its color.
you are exactly overlapping two drawings (the image and the rect) so you will only ever see one.
I hope I have finally been of some help.
Related
I have this code for a game called Wave, and normally when I run it, it should be a black window with white squares in it. But the window is white, with a very thin black stripe on the left of the window. I can barely see it.
Does anybody have any idea on why would this happen?
package wave.myFirstGame;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.util.Random;
public class Game extends Canvas implements Runnable {
private static final long serialVersionUID = 3580879553502102315L;
public static final int WITDH = 640, HEIGHT = WITDH / 12 * 9;
private Thread thread;
private boolean running = false;
private Random r;
public Handler handler;
public Game() {
new Window(WITDH, HEIGHT, "Wave", this);
handler = new Handler();
r = new Random();
for(int i = 0; i < 50; i++){
handler.addObject(new Player(r.nextInt(WIDTH), r.nextInt(HEIGHT), ID.Player));
}
handler.addObject(new Player(200, 200, ID.Player));
}
public synchronized void start() {// initializing the thread
thread = new Thread(this);
thread.start();
running = true;
}
public synchronized void stop() {
try {
thread.join();
running = false;
} catch (Exception e) {
e.printStackTrace();
}
}
// GAME LOOP
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(){
handler.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, WIDTH, HEIGHT);
handler.render(g);
g.dispose();
bs.show();
}
public static void main(String[] args) {
new Game();
}
}
Have a look into the API of Canvas. There you will find:
Fields inherited from interface java.awt.image.ImageObserver
[...] HEIGHT, [...], WIDTH
So since you extend your class from Canvas class you already have WIDTH and HEIGHT constants and for some reason WIDTH seams to have value 1.
So simply rename your constants and it will display as expected.
This is a follow up question to an earlier one of mine. I am making a java game, and it is basically a JFrame with a character image, some healthbars consisting of fillRect()s which are all on top of a background image. The problem is the healthbars and character are appearing but the background image isn't.
Here is a shortened version of the Game class which has the main() and render() methods:
public class Game extends Canvas implements Runnable{
public static boolean running = false;
public Thread gameThread;
private BufferedImage playerSpriteSheet;
private ImageManager im;
private static Player player;
private static HealthBar healthBars;
private static BackgroundImage backgroundImage;
public void init(){
ImageLoader loader = new ImageLoader();
playerSpriteSheet = loader.load("/spriteSheet.png");
SpriteSheet pss = new SpriteSheet(playerSpriteSheet);
im = new ImageManager(pss);
backgroundImage = new BackgroundImage("/background.png");
player = new Player(800, 250, im);
healthBars = new HealthBar(200, 200);
this.addKeyListener(new KeyManager());
}
public synchronized void start() {
if(running)return;
running = true;
gameThread = new Thread(this);
gameThread.start();
}
public synchronized void stop() {
if(!running)return;
running = false;
try {
gameThread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
init();
long lastTime = System.nanoTime();
final double amountOfTicks = 60D;
double ns = 1_000_000_000/amountOfTicks;
double delta = 0;
long now = System.nanoTime();
while(running)
{
delta += (now - lastTime)/ns;
lastTime = now;
if(delta >= 1)
{
tick();
delta--;
}
render();
}
stop();
}
public void tick() {
player.tick();
}
public void render() {
BufferStrategy bs = this.getBufferStrategy();
if(bs == null)
{
createBufferStrategy(3); //Use 5 at most
return;
}
Graphics g = bs.getDrawGraphics();
//RENDER HERE
backgroundImage.render(g);
player.render(g);
healthBars.render(g);
//END RENDER
g.dispose();
bs.show();
}
public static void main(String[] args)
{
JLabel backgroundImage;
JLabel controlKeyPanel;
JLabel statusLabel;
Game game = new Game();
game.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
game.setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
game.setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
JFrame frame = new JFrame("Title");
frame.setResizable(false);
frame.setSize(WIDTH * SCALE, HEIGHT * SCALE);
frame.setLayout(new BorderLayout());
backgroundImage = new JLabel(new ImageIcon("/background.png"));
String htmlButtonGuide = "words";
controlKeyPanel = new JLabel(htmlButtonGuide);
statusLabel = new JLabel("label");
frame.add(backgroundImage, BorderLayout.CENTER);
frame.add(controlKeyPanel, BorderLayout.EAST);
frame.add(statusLabel, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(game);
frame.setVisible(true);
game.start();
//Program seems to continue running after ESC
}
public static Player getPlayer() {
return player;
}
}
Here is the BackGroundImage class:
public class BackgroundImage {
private Image background = null;
public BackgroundImage(String s) {
if(s == null)
{
background = getImage(s);
}
}
public void render(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.drawImage(background, 0, 0, 1200, 600, null);
}
public Image getImage(String path) {
Image tempImage = null;
File image2 = new File(path);
try {
tempImage = ImageIO.read(image2);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return tempImage;
}
}
I am concerned with the render() method reusing the "g" Graphics object for adding all 3 things to the screen. I was told to not combine lightweight Swing health bars with the heavy AWT background and character? Can anyone point me in the right direction to get the background to show? Should the render method not take care of the background? I only need the background to be put up once. It doesn't need to be constantly updated like the health bars and characters right?
Let's start with...
backgroundImage = new BackgroundImage("/background.png");
Which becomes...
File image2 = new File(path);
or
File image2 = new File("/background.png");
so you can see it...can you see a problem with this? This is requesting a file which resides at the root location of the current drive...not really what I think you want...
The images are stored in a folder called "res" in the main project folder
Which would suggest you want to use...
backgroundImage = new BackgroundImage("res/background.png");
Assuming that the images are not embedded resources....
Next...
public BackgroundImage(String s) {
if (s == null) {
background = getImage(s);
}
}
So, you only ever want to try a load the image when it's reference is null???
Side notes...
frame.setSize(WIDTH * SCALE, HEIGHT * SCALE); is a bad idea, as frames have borders which occupy space within side the frame itself.
Better to override the getPreferredSize method of Canvas and provide a default size value you want to use and then call pack on the frame instead. This will calculate the size of the frame as the preferred size of it's content PLUS the frame border requirements...
You "game loop" is running wild...
while (running) {
delta += (now - lastTime) / ns;
lastTime = now;
if (delta >= 1) {
tick();
delta--;
}
render();
}
Basically, this will run as fast as it possibly can and will reduce the opportunity for other threads to run, eventually bringing your game (and probably your PC) to it's knees
This is "simple" concept of a run loop...
public void run() {
init();
final long amountOfTicks = 60;
long ns = Math.round(1_000_000_000 / (double)amountOfTicks);
int frames = 0;
long frameStart = System.currentTimeMillis();
while (running) {
long startedAt = System.nanoTime();
tick();
render();
long completedAt = System.nanoTime();
long duration = completedAt - startedAt;
long frameEnd = System.currentTimeMillis();
if (frameEnd - frameStart >= 1000) {
System.out.println(frames);
frames = 0;
frameStart = System.currentTimeMillis();
} else {
frames++;
}
long rest = ns - duration;
if (rest > 0) {
rest = TimeUnit.MILLISECONDS.convert(rest, TimeUnit.NANOSECONDS);
try {
Thread.sleep(rest);
} catch (InterruptedException ex) {
}
}
}
stop();
}
Basically, it tries to ensure that there is enough delay between each iteration in order to maintain the 60fps you are trying to target...without starving the system...
I am making a java game and at it's heart, it consists of a JFrame that holds a a JLabel that holds the background image. Early in the project this was being displayed. However, after I implemented a Game render method that put healthbars and a character on screen, the background image no longer displays. Here is the Game's render() and main() methods.
public class Game extends Canvas implements Runnable{
private static final long serialVersionUID = 1L;
public static final int WIDTH = 1200, HEIGHT = 600, SCALE = 1;
public static boolean running = false;
public Thread gameThread;
private BufferedImage playerSpriteSheet;
private ImageManager im;
private static Player player;
private static HealthBar healthBars;
public void init(){
ImageLoader loader = new ImageLoader();
playerSpriteSheet = loader.load("/spriteSheet.png");
SpriteSheet pss = new SpriteSheet(playerSpriteSheet);
im = new ImageManager(pss);
player = new Player(0, 0, im);
healthBars = new HealthBar(200, 200);
this.addKeyListener(new KeyManager());
}
public synchronized void start() {
if(running)return;
running = true;
gameThread = new Thread(this);
gameThread.start();
}
public synchronized void stop() {
if(!running)return;
running = false;
try {
gameThread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
init();
long lastTime = System.nanoTime();
final double amountOfTicks = 60D;
double ns = 1_000_000_000/amountOfTicks;
double delta = 0;
long now = System.nanoTime();
while(running)
{
delta += (now - lastTime)/ns;
lastTime = now;
if(delta >= 1)
{
tick();
delta--;
}
render();
}
stop();
}
public void tick() {
player.tick();
}
public void render() {
BufferStrategy bs = this.getBufferStrategy();
if(bs == null)
{
createBufferStrategy(3); //Use 5 at most
return;
}
Graphics g = bs.getDrawGraphics();
//RENDER HERE
player.render(g);
healthBars.render(g);
//END RENDER
g.dispose();
bs.show();
}
public static void main(String[] args)
{
JLabel backgroundImage;
JLabel controlKeyPanel;
JLabel statusLabel;
Game game = new Game();
game.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
game.setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
game.setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
JFrame frame = new JFrame("Java Game");
frame.setResizable(false);
frame.setSize(WIDTH * SCALE, HEIGHT * SCALE);
frame.setLayout(new BorderLayout());
backgroundImage = new JLabel(new ImageIcon("/background.png"));
String htmlButtonGuide = "<html>← - Move Left<br>→ - Move Right<br>A - Attack<br>S - Fire Gun<br>P - Position<br>esc - Exit</html>";
controlKeyPanel = new JLabel(htmlButtonGuide);
statusLabel = new JLabel("Game Status");
frame.add(backgroundImage, BorderLayout.CENTER); //This should be displaying the background image
frame.add(controlKeyPanel, BorderLayout.EAST);
frame.add(statusLabel, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(game);
frame.setVisible(true);
game.start();
}
public static Player getPlayer() {
return player;
}
}
Here is the catch, and where I think part of the issue is visible. Inside the render() method there are these 2 lines:
player.render(g);
healthBars.render(g);
If I put player.render(g) first, then both the player and health bars appear on the screen. However, if I put healthBars.render(g) before player.render(g), then the player doesn't appear. This really confuses me, because I would expect the one that renders second causes the first one to be hidden behind, but the opposite happens. Could anyone point me in the right direction?
BufferStrategy doesn't play well with Swing, as you've taken control of the painting process
Canvas can't be transparent, so it will hide anything beneath it...
When you use frame.add(game) you are replaceing what ever use to be at BorderLayout.CENTER
Instead of mixing lightweight (Swing) and heavy weight (AWT) components, paint the background image as part of your render process
public void render() {
BufferStrategy bs = this.getBufferStrategy();
if(bs == null)
{
createBufferStrategy(3); //Use 5 at most
return;
}
Graphics g = bs.getDrawGraphics();
//RENDER HERE
// Paint background here...
player.render(g);
healthBars.render(g);
//END RENDER
g.dispose();
bs.show();
}
I am trying to develop a game that imports the background images from a [100][100] matrix. The matrix will hold int values to correlate to what should be drawn on the background. A loop draws the images to the canvas and updates it based on key input from the user. Everything paints and moves fine however, it is very slow. Is there a better way to load the images rather than the way I am doing it?
This is the main game class:
package com.game.src.main;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.swing.JFrame;
public class Game extends Canvas implements Runnable{
static GraphicsEnvironment environment;
static GraphicsDevice device;
private static final long serialVersionUID = 1L;
public static final int WIDTH = 320;
public static final int HEIGHT = WIDTH / 12 * 9;
public static final int SCALE = 2;
public static final String TITLE = "fgfdsa";
private boolean running = false;
private Thread thread;
private Player p;
private Background b;
private Controller c;
private BufferedImage spriteSheet;
boolean isFiring = false;
public void init(){
BufferedImageLoader loader = new BufferedImageLoader();
try{
spriteSheet = loader.loadImage("/sprite_sheet_test.png");
}catch(IOException e){
e.printStackTrace();
}
requestFocus();
addKeyListener(new KeyInput(this));
c = new Controller();
p = new Player(getWidth() / 2, getHeight() / 2, this);
b = new Background(this);
}
private synchronized void start(){
if(running)
return;
running = true;
thread = new Thread(this);
thread.start();
}
private synchronized void stop(){
if(!running)
return;
running = false;
try {
thread.join();
} 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 updates = 0;
int frames = 0;
long timer = System.currentTimeMillis();
while(running){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
if(delta >= 1){
tick();
updates++;
delta--;
}
render();
frames++;
if(System.currentTimeMillis() - timer > 1000){
timer += 1000;
System.out.println(updates + " Ticks, Fps " + frames);
updates = 0;
frames = 0;
}
}
stop();
}
public void tick(){
p.tick();
b.tick();
c.tick();
}
public void render(){
BufferStrategy bs = this.getBufferStrategy();
if(bs == null){
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
b.render(g);
p.render(g);
c.render(g);
g.dispose();
bs.show();
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
switch(key){
case 37:
b.setX(5);
break;
case 38:
b.setY(5);
break;
case 39:
b.setX(-5);
break;
case 40:
b.setY(-5);
break;
case 32:
if(!isFiring){
c.addBullet(new Bullet(p.getX(), p.getY(), this));
isFiring = true;
}
}
}
public void keyReleased(KeyEvent e){
int key = e.getKeyCode();
switch(key){
case 37:
b.setX(0);
break;
case 38:
b.setY(0);
break;
case 39:
b.setX(0);
break;
case 40:
b.setY(0);
break;
case 32:
isFiring = false;
}
}
public static void main(String[] args){
Game game = new Game();
game.setPreferredSize(new Dimension(600, 600));
game.setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
game.setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
JFrame frame = new JFrame(game.TITLE);
frame.add(game);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
device = environment.getDefaultScreenDevice();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
game.start();
}
public BufferedImage getSpriteSheet(){
return spriteSheet;
}
}
This is the background class used to draw the image to the screen:
package com.game.src.main;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
public class Background {
private BufferedImage grass;
private BufferedImage background;
private BufferedImage tree;
int[][] matrix;
Game game;
//original starting coordinates of matrix to be drawn
int setX = -3200;
int setY = -3200;
//integers used to update coordinates of the matrix to be drawn
int helpX = 0;
int helpY = 0;
public Background(Game game){
this.game = game;
// load matrix into matrix array
GetMatrix gm = new GetMatrix();
matrix = gm.getMatrix();
//import the sprite from game class
background = game.getSpriteSheet();
//call sprite sheet class
SpriteSheet ss = new SpriteSheet(background);
//get coordinates of grass image
grass = ss.grabImage(1, 1, 32, 32);
// get coordinates of tree image
tree = ss.grabImage(4, 1, 32, 32);
}
public void tick(){
//update the start pixel of the background
setX += helpX;
setY += helpY;
if(setX > 0)
setX = 0;
if(setX < -4500)
setX = -4500;
if(setY > 0)
setY = 0;
if(setY < -5340)
setY = -5340;
}
public void render(Graphics g){
int x = 0;
int y = 0;
for(int i = setX; i < setX + 6400; i +=64){
x = 0;
for(int j = setY; j < setY + 6400; j += 64){
switch(matrix[x][y]){
case 0: g.drawImage(grass, i, j, i + 64, j + 64,
0, 0, 32, 32, null);
break;
case 1:
g.drawImage(grass, i, j, i + 64, j + 64,
0, 0, 32, 32, null);
g.drawImage(tree, i, j, i + 64, j + 64,
0, 0, 32, 32, null);
}
x++;
}
y++;
}
}
//sets the background start coordinates from key input
public void setX(int x){
helpX = x;
}
public void setY(int y){
helpY = y;
}
}
It is not obvious what SpriteSheet#grabImage(...) does. But I'm pretty sure that there is some call to BufferedImage#getSubImage(...) involved. Is that right?
If this is right, there are two potential issues here:
When you are loading an image with ImageIO, the type of the resulting image is not known. By "type" I refer to the BufferedImage#getType(). This type may be BufferedImage.TYPE_CUSTOM, particularly when it is a PNG with transparency. When an image with this type is painted, then this painting is awfully slow, because there are some color conversions done internally.
When you call BufferedImage#getSubImage(...), then the image on which you call this method will become "unmanaged". That means that the actual image data can no longer be held directly in video memory. (There are some very involved technical details behind that one. And these details may change between different JRE versions. For example, they changed between Java 6 and Java 7. However, the rule of thumb is: If you want to draw images with high performance, don't call BufferedImage#getSubImage(...) on the image that you want to paint)
The solution for both issues can be to convert the images into managed images of the type BufferedImage.TYPE_INT_ARGB. So for each image that you want to paint, you can call
BufferedImage toPaint = convertToARGB(originalImage);
with this method:
public static BufferedImage convertToARGB(BufferedImage image)
{
BufferedImage newImage = new BufferedImage(
image.getWidth(), image.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}
In your example, you could apply this to your grass and tree images.
Another (maybe even more important) issue is that you seem to be drawing your tiles scaled: You seem to paint a 64x64 pixels sprite with a size of 32x32. If this is correct, then you could consider rescaling the input image once, and then drawing the tiles with their original size of 32x32.
In any case, it's hard to predict how much speedup each of these changes will actually bring, but they should be worth a try.
i was making a program, game in specific, so i started with basic things, but when i try to test it it drops out weird errors which doesn't appear in code, so i suppose my code is fine, but i don't know what could be causing this. :(
This is the error:
Exception in thread "main" java.lang.NullPointerException
at java.awt.image.BufferedImage.<init>(Unknown Source)
at ca.hawk.game.Game.<init>(Game.java:33)
at ca.hawk.game.Game.main(Game.java:126)
And here's the code (package):
package ca.hawk.game;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.awt.image.IndexColorModel;
import javax.swing.JFrame;
public class Game extends Canvas implements Runnable{
private static final long serialVersionUID = 1L;
public static final int WIDTH = 160;
public static final int HEIGHT = WIDTH / 12 * 9;
public static final int SCALE = 3;
public static final String NAME = "Game";
private static final int BufferedImage = 0;
private static final IndexColorModel TYPE_INT_RGB = null;
private JFrame frame;
public boolean running = false;
public int tickCount = 0;
private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage, TYPE_INT_RGB);
private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
public Game(){
setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
frame = new JFrame(NAME);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(this, BorderLayout.CENTER);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public synchronized void start() {
running = true;
new Thread(this).start();
}
private synchronized void stop(){
running = false;
}
public void run() {
long lastTime = System.nanoTime();
double nsPerTick = 1000000000D/60D;
int ticks = 0;
int frames = 0;
long lastTimer = System.currentTimeMillis();
double delta = 0;
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) {
e.printStackTrace();
}
if (shouldRender){
frames++;
render();
}
if (System.currentTimeMillis() - lastTimer > 1000){
lastTimer += 1000;
System.out.println(frames +", "+ ticks);
frames = 0;
ticks = 0;
}
}
}
public void tick(){
tickCount++;
}
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.drawImage(image, 0, 0, getWidth(), getHeight(), null);
g.dispose();
bs.show();
}
public static void main(String[] args){
new Game().start();
}
}
change :
private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage, TYPE_INT_RGB);
to:
private BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage, BufferedImage.TYPE_INT_ARGB);
you set a varialbe TYPE_INT_RGB that is null, so when you make a buffered image it throws null pointer exception.
TYPE_INT_RGB is a public static final variable on BufferedImage. Public means you can access it in your object, static means its a class variable not an object variable and final means its ts always the same value e.g if its 10 it will always be 10.
with BufferedImage.TYPE_INT_RGB you can access it.