I'm having an issue with my 2D game that I am following a tutorial for. I've scanned my code several times and cannot seem to resolve it. Sorry if my question sounds stupid, but I do welcome any help whatsoever.
Here's my source:
package game;
import gfx.SpriteSheet;
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 javax.swing.JFrame;
public class Game extends Canvas implements Runnable
{
private static final long serialVersionUD = 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 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();
private SpriteSheet spriteSheet = new SpriteSheet("SpriteSheet.png");
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);
}
private 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 = false;
while(delta >= 1)
{
ticks++;
tick();
delta -= 1;
shouldRender = true;
}
try {
Thread.sleep(2);
} catch (InterruptedException ex) {
}
if(shouldRender)
{
frames++;
render();
}
if(System.currentTimeMillis() - lastTimer >= 1000)
{
lastTimer += 1000;
System.out.println(frames + ", " + ticks);
frames = 0;
ticks = 0;
}
}
}
//Updates all of internal variables and logic and stuff.
public void tick()
{
tickCount++;
for(int i = 0; i < pixels.length; i++)
{
pixels [i] = i + tickCount;
}
}
//prints the updated logic.
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();
}
//Main method
public static void main(String[]args)
{
new Game().start();
}
}
package gfx;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
public class SpriteSheet
{
public String path;
public int width;
public int height;
public int[] pixels;
public SpriteSheet(String path)
{
BufferedImage image = null;
try
{
image = ImageIO.read(SpriteSheet.class.getResourceAsStream(path));
} catch (IOException e)
{
e.printStackTrace();
}
if(image == null)
{
return;
}
this.path = path;
this.width = image.getWidth();
this.height = image.getHeight();
pixels = image.getRGB(0, 0, width, height, null, 0, width);
for(int i = 0; i < pixels.length; i++)
{
pixels[i] = (pixels[i] & 0xff / 64);
}
for(int i = 0; i < 8; i++)
{
System.out.println(pixels[i]);
}
}
}
And here's a link to my video tutorial I'm using: Tutorial
I'm using eclipse on a 64 bit operating system(Windows).
Again, any help would be greatly appreciated, and thank you.
EDIT:
Error message:
Exception in thread "main" java.lang.IllegalArgumentException: input == null!
at javax.imageio.ImageIO.read(ImageIO.java:1348)
at gfx.SpriteSheet.<init>(SpriteSheet.java:21)
at game.Game.<init>(Game.java:34)
at game.Game.main(Game.java:144)
Sorry, forgot error message. XD
The error message is telling you what's wrong: Your image path is wrong. The image path must be given relative to the class files location.
Related
The game runs at about 2000 to 3100 fps in normal window mode. If i set the JFrame component to fullscreen and scale up my JPanel to also the same resolution, the fps drops to 20-70.
(This is a prototype, hardcoded resolutions will be later swapped out)
This is my relevant code (if this is not enough, I can provide more):
Game.java
import javax.swing.JFrame;
public class Game {
public static void main(String[] args) {
JFrame window = new JFrame("Platformer Test");
window.setContentPane(new GamePanel(window));
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(true);
//window.setUndecorated(true);
window.pack();
window.setVisible(true);
}
}
GamePanel.java
package Main;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
// custom imports
import GameState.GameStateManager;
#SuppressWarnings("serial")
public class GamePanel extends JPanel implements Runnable, KeyListener{
// dimensions
public static final int WIDTH = 320;
public static final int HEIGHT = 240;
public static final int SCALE = 2;
// Graphic Device (used for fullscreen)
static GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0];
private JFrame frame;
// game Thread
private Thread thread;
private boolean running;
private double GameTicks = 60;
// image
private BufferedImage image;
private Graphics2D g;
boolean renderFPS = false;
int frames = 0;
// game state manager
private GameStateManager gsm;
public GamePanel(JFrame frame) {
super();
this.frame = frame;
// set Window Size
setFocusable(true);
setFullscreen(true);
}
private void setFullscreen(boolean t) {
if(t) {
setPreferredSize(new Dimension(1920, 1080));
device.setFullScreenWindow(frame);
requestFocus();
}else {
setSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
requestFocus();
}
}
public void addNotify() {
super.addNotify();
if (thread == null) {
thread = new Thread(this);
addKeyListener(this);
thread.start();
}
}
private void init() {
// create image --> Game is drawn on here
image = new BufferedImage(
WIDTH, HEIGHT,
BufferedImage.TYPE_INT_RGB
);
// get graphics component of game image
g = (Graphics2D) image.getGraphics();
// starts game clock
running = true;
// adds new GameStateManager
gsm = new GameStateManager();
}
#Override
public void run() {
init();
//game loop setup
double ns = 1000000000 / GameTicks;
double delta = 0;
long lastTime = System.nanoTime();
long timer = System.currentTimeMillis();
int ticks = 0;
// game loop
while(running) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >= 1) {
update();
ticks++;
delta--;
}
if(running)
render();
frames++;
if(System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.println("FPS: " + frames + ", ticks: " + ticks);
renderFPS = true;
frames = 0;
ticks = 0;
}
}
}
private void update() {
gsm.update();
}
private void render() {
gsm.render(g);
int fps = 0;
// Draw To Screen
Graphics g2 = getGraphics();
g2.drawImage(image, 0, 0, WIDTH * SCALE, HEIGHT * SCALE, null);
//g2.drawImage(image, 0, 0, 1920, 1080, null);
if(renderFPS) {
fps = frames;
}
g2.setColor(Color.red);
g2.drawString("FPS: " + fps, 100,100);
g2.dispose();
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
gsm.keyPressed(e.getKeyCode());
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
gsm.keyReleased(e.getKeyCode());
}
}
Swing is not thread safe, you shouldn't be updating the UI, or the state the UI relies on, from outside the context of the Event Dispatching Thread. This means you shouldn't be using Thread as your "game loop".
See Concurrency in Swing for more details and How to Use Swing Timers for the most common solution.
Don't use JPanel#getGraphics, this is not how painting in Swing is done. Instead, override paintComponent. See Painting in AWT and Swing
and Performing Custom Painting for more details.
Don't use KeyListener, seriously, it's just not worth all the hacking around to make it work. Instead, use the key bindings API
The following, simple, example runs at roughly 171 updates a second (it separates the "timer ticks" and "paint ticks", as in Swing, it's not really possible to know when something is actually rendered to the screen) in both windowed and full screen
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.Instant;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public final class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0];
JFrame frame = new JFrame();
frame.add(new GamePanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
// device.setFullScreenWindow(frame);
}
});
}
public class GamePanel extends JPanel {
private Timer timer;
private int ticksPerSecond = 0;
private int paintsPerSecond = 0;
private int xDelta = 1;
private Rectangle boxy = new Rectangle(0, 0, 50, 50);
// Graphic Device (used for fullscreen)
public GamePanel() {
timer = new Timer(5, new ActionListener() {
private Instant lastTick;
private int ticks = 0;
#Override
public void actionPerformed(ActionEvent e) {
if (lastTick == null) {
lastTick = Instant.now();
}
if (Duration.between(lastTick, Instant.now()).toMillis() >= 1000) {
ticksPerSecond = ticks;
lastTick = Instant.now();
ticks = 0;
}
ticks++;
boxy.x += xDelta;
if (boxy.x + boxy.width > getWidth()) {
boxy.x = getWidth() - boxy.width;
xDelta *= -1;
} else if (boxy.x < 0) {
boxy.x = 0;
xDelta *= -1;
}
boxy.y = (getHeight() - boxy.height) / 2;
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
public void addNotify() {
super.addNotify();
timer.start();
}
#Override
public void removeNotify() {
timer.stop();
super.removeNotify();
}
private Instant lastPaint;
private int paints = 0;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (lastPaint == null) {
lastPaint = Instant.now();
}
if (Duration.between(lastPaint, Instant.now()).toMillis() >= 1000) {
paintsPerSecond = paints;
lastPaint = Instant.now();
paints = 0;
}
paints++;
Graphics2D g2d = (Graphics2D) g.create();
FontMetrics fm = g2d.getFontMetrics();
g2d.drawString("Ticks p/s " + ticksPerSecond, 10, 10 + fm.getAscent());
g2d.drawString("Paints p/s " + paintsPerSecond, 10, 10 + fm.getAscent() + fm.getHeight());
g2d.fill(boxy);
g2d.dispose();
}
}
}
If you "really" need absolute control over the painting process, then you should be using a BufferStrategy, see BufferStrategy and BufferCapabilities and the JavaDocs which has an excellent example of how it should be used.
Lots of things might effect the performance of the paint process, for example
A crazy experiment...
So, this example allows you to change the number of entities been rendered on the screen. Each entity is moving in it's own direction and is rotating (no collision detection).
I can get this to run up to roughly 20-25, 0000 entities before I start seeing a (significant) change in the number of updates per second. I rolled it to 100, 000 and it dropped to roughly 42 updates per second.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public final class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0];
GamePanel gamePanel = new GamePanel();
JSlider slider = new JSlider(1, 100000);
slider.setValue(100);
slider.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
if (slider.getValueIsAdjusting()) {
return;
}
gamePanel.setBoxCount(slider.getValue());
}
});
JFrame frame = new JFrame();
frame.add(gamePanel);
frame.add(slider, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
device.setFullScreenWindow(frame);
}
});
}
public class GamePanel extends JPanel {
private Timer timer;
private int ticksPerSecond = 0;
private int paintsPerSecond = 0;
private List<Box> boxes = new ArrayList<>(100);
// Graphic Device (used for fullscreen)
public GamePanel() {
for (int index = 0; index < 100; index++) {
boxes.add(new Box());
}
timer = new Timer(5, new ActionListener() {
private Instant lastTick;
private int ticks = 0;
#Override
public void actionPerformed(ActionEvent e) {
if (lastTick == null) {
lastTick = Instant.now();
}
if (Duration.between(lastTick, Instant.now()).toMillis() >= 1000) {
ticksPerSecond = ticks;
lastTick = Instant.now();
ticks = 0;
}
ticks++;
for (Box box : boxes) {
box.update(getSize());
}
repaint();
}
});
}
public void setBoxCount(int count) {
if (count < boxes.size()) {
boxes = boxes.subList(0, count);
return;
}
while (boxes.size() < count) {
boxes.add(new Box());
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
public void addNotify() {
super.addNotify();
timer.start();
}
#Override
public void removeNotify() {
timer.stop();
super.removeNotify();
}
private Instant lastPaint;
private int paints = 0;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (lastPaint == null) {
lastPaint = Instant.now();
}
if (Duration.between(lastPaint, Instant.now()).toMillis() >= 1000) {
paintsPerSecond = paints;
lastPaint = Instant.now();
paints = 0;
}
paints++;
Graphics2D g2d = (Graphics2D) g.create();
for (Box box : boxes) {
box.paint(g2d);
}
FontMetrics fm = g2d.getFontMetrics();
int yPos = 10 + fm.getAscent();
g2d.drawString("Ticks p/s " + ticksPerSecond, 10, yPos + fm.getAscent());
yPos += fm.getHeight();
g2d.drawString("Paints p/s " + paintsPerSecond, 10, yPos + fm.getAscent());
yPos += fm.getHeight();
g2d.drawString("Count " + boxes.size(), 10, yPos + fm.getAscent());
g2d.dispose();
}
}
private List<Color> colors = new ArrayList<>(Arrays.asList(new Color[]{
Color.BLACK, Color.BLUE, Color.CYAN, Color.DARK_GRAY, Color.GRAY, Color.GREEN,
Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.RED, Color.WHITE,
Color.YELLOW
}));
public class Box {
private Color fill;
private Rectangle shape;
private int x;
private int y;
private int xDelta;
private int yDelta;
private int rotationDelta;
private int angle = 0;
public Box() {
Random rnd = new Random();
int width = rnd.nextInt(45) + 5;
int height = rnd.nextInt(45) + 5;
x = rnd.nextInt(400) - width;
y = rnd.nextInt(400) - height;
xDelta = rnd.nextInt(2) + 1;
yDelta = rnd.nextInt(2) + 1;
if (rnd.nextBoolean()) {
xDelta *= -1;
}
if (rnd.nextBoolean()) {
yDelta *= -1;
}
rotationDelta = rnd.nextInt(5);
if (rnd.nextBoolean()) {
rotationDelta *= -1;
}
shape = new Rectangle(x, y, width, height);
Collections.shuffle(colors);
fill = colors.get(0);
shape = new Rectangle(0, 0, width, height);
}
public void update(Dimension bounds) {
x += xDelta;
y += yDelta;
angle += rotationDelta;
if (x + getWidth() > bounds.width) {
x = bounds.width - getWidth();
xDelta *= -1;
} else if (x < 0) {
x = 0;
xDelta *= -1;
}
if (y + getWidth() > bounds.height) {
y = bounds.height - getWidth();
yDelta *= -1;
} else if (y < 0) {
y = 0;
yDelta *= -1;
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth() {
return shape.width;
}
public int getHeight() {
return shape.height;
}
public void paint(Graphics2D g2d) {
g2d = (Graphics2D) g2d.create();
g2d.translate(x, y);
g2d.rotate(Math.toRadians(angle), getWidth() / 2, getHeight() / 2);
g2d.setColor(fill);
g2d.fill(shape);
g2d.dispose();
}
}
}
I'm having troubles with my Brick Breaker game that I am making in my 12th grade programming class.
Currently, it seems that only the brick in Bricks.render does draw. When I output what the X and Y of the bricks should be it puts each brick in the right position. So I believe I'm drawing it wrong.
MCVE:
Game.java
package main;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferStrategy;
public class Game extends Canvas implements Runnable {
// variables
private static final long serialVersionUID = 1L;
public static final int WIDTH = 480, HEIGHT = 600, SCALE = 1;
public final String TITLE = "Brick Breaker";
private static boolean running = false;
private Thread thread;
private int fpsDisplay = 0;
Bricks[] level1 = new Bricks[16];
// creates a new Game (which creates the game window)
public static void main(String[] args) {
new Game();
}
public Game() {
new GameWindow(WIDTH, HEIGHT, SCALE, TITLE, this);
System.out.println("[" + TITLE + " has started.]");
}
// called in GameWindow, starts the thread and game loop
public synchronized void start() {
if (running)
return;
thread = new Thread(this);
thread.start();
running = true;
}
public void init() {
this.createlevel1();
}
// used for updating what's happening in the game
private void tick() {
}
// renders the graphics
private void render() {
// --------- INIT GRAPHICS --------- //
BufferStrategy bs = this.getBufferStrategy();
if (bs == null) {
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
Graphics2D g2d = (Graphics2D) g;
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
FontMetrics fontMetrics = g2d.getFontMetrics();
// --------- INIT GRAPHICS --------- //
// clearing background
super.paint(g);
g2d.setColor(Color.black);
g2d.drawString(Integer.toString(fpsDisplay) + " FPS",
WIDTH - 9 - fontMetrics.stringWidth(Integer.toString(fpsDisplay) + " FPS"), 14);
// render level 1
for (int i = 0; i < 16; i++) {
level1[i].render(g);
}
// render level 1
// ---------
g.dispose();
g2d.dispose();
bs.show();
// ---------
}
public void createlevel1() {
int brickCount = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
level1[brickCount] = new Bricks(50 + i * 100, 50 + j * 100);
System.out.println("X: " + (50 + i * 100) + " Y: " + (50 + j * 100));
brickCount++;
}
}
}
// 60 tps game loop
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("Ticks: " + updates + ", FPS: " + frames);
fpsDisplay = frames;
updates = 0;
frames = 0;
}
}
stop();
}
// called at the end of the loop, stops the thread
public synchronized void stop() {
try {
thread.join();
running = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Bricks.java
package main;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
#SuppressWarnings("unused")
public class Bricks {
private int x, y, w, h;
private Boolean isAlive;
private Color randColour;
public Bricks(int x, int y) {
x = this.x;
y = this.y;
w = 75;
h = 25;
isAlive = true;
randColour = Color.blue;
}
public void render(Graphics g) {
g.setColor(randColour);
g.fillRect(x, y, w, h);
}
}
GameWindow.java
package main;
import java.awt.Canvas;
import java.awt.Dimension;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
public class GameWindow extends Canvas {
private static final long serialVersionUID = -5131420759044457697L;
public GameWindow(int WIDTH, int HEIGHT, int SCALE, String TITLE, Game game) {
JFrame frame = new JFrame(TITLE);
frame.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
frame.setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
frame.setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
try {
frame.setIconImage(ImageIO.read(new File("res/Brick-icon.png")));
} catch (IOException e) {
frame.setIconImage(null);
e.printStackTrace();
System.out.println("ICON ERROR: Icon image not found. (Default Icon is set.)");
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.add(game);
frame.pack();
game.start();
// displays the window 400ms later to allow for the game to fully load
try {
Thread.sleep(400);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
frame.setVisible(true);
}
}
In Bricks.java:
x = this.x;
y = this.y;
should be:
this.x = x;
this.y = y;
package aaron.game;
import java.awt.BorderLayout;
import java.awt.Canvas;
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.*;
import javax.swing.JFrame;
import aaron.game.gfx.Colours;
import aaron.game.gfx.Font;
import aaron.game.gfx.Screen;
import aaron.game.gfx.SpriteSheet;
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 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();
private int[] colours = new int[6*6*6];
private Screen screen;
public InputHandler input;
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 void init(){
int index = 0;
for(int r = 0;r<6;r++){
for(int g = 0;g<6;g++){
for(int b = 0;b<6;b++){
int rr= (r*255/5);
int gg= (g*255/5);
int bb= (b*255/5);
colours[index++] = rr<<16| gg<<8 | bb;
}
}
}
screen = new Screen(WIDTH, HEIGHT, new SpriteSheet("/sprite_sheet.png"));
input = new InputHandler(this);
}
public synchronized void start() {
running = true;
new Thread(this).start();
}
public synchronized void stop() {
running = false;
}
public void run() {
long lastTime = System.nanoTime();
double nsPerTick = 1000000000D/60D;
int frames = 0;
int ticks = 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) {
e.printStackTrace();
}
if (shouldRender){
frames++;
render();
}
if(System.currentTimeMillis() - lastTimer >= 1000){
lastTimer += 1000;
System.out.println(ticks + " ticks, " + frames + " frames");
frames = 0;
ticks = 0;
}
}
}
public void tick(){
tickCount++;
if(input.up.isPressed()){screen.yOffset--;}
if(input.down.isPressed()){screen.yOffset++;}
if(input.left.isPressed()){screen.xOffset--;}
if(input.right.isPressed()){screen.xOffset++;}
for (int i = 0; i < pixels.length; i++){
pixels[i] = i + tickCount;
}
}
public void render(){
BufferStrategy bs = getBufferStrategy();
if (bs == null){
createBufferStrategy(3);
return;
}
for(int y=0;y<32;y++){
for(int x=0;x<32;x++){
boolean flipX = x%2==1;
boolean flipY = y%2==1;
screen.render(x<<3, y<<3, 0, Colours.get(555,505,055,550), flipX, flipY);
}
}
// Font.render("Hello Wolrd! 0157", screen, 0, 0, Colours.get(000, -1, -1, 555));
for(int y=0;y<screen.height;y++){
for(int x=0;x<screen.width;x++){
int colourCode=screen.pixels[x+y*screen.width];
if(colourCode<255)pixels[x+y*WIDTH]=colours[colourCode];
}
}
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();
}
}
^This is my main class [ // Font.render("Hello Wolrd! 0157", screen, 0, 0, Colours.get(000, -1, -1, 555));] < this is where i am getting the error...
package aaron.game.gfx;
public class Font {
private static String chars = "" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ " + "0123456789.,:;'\"!?$%()-=+/ ";
public static void render(String msg, Screen screen, int x, int y, int colour, int scale) {
msg = msg.toUpperCase();
for (int i = 0; i < msg.length(); i++) {
int charIndex = chars.indexOf(msg.charAt(i));
if (charIndex >= 0) screen.render(x + (i * 8), y, charIndex + 30 * 32, colour, false, false);
}
}
}
This is the class for reading my fonts
package aaron.game.gfx;
public class Screen {
public static final int MAP_WIDTH = 64;
public static final int MAP_WIDTH_MASK = MAP_WIDTH - 1;
public int[]pixels;
public int xOffset = 0;
public int yOffset = 0;
public int width;
public int height;
public SpriteSheet sheet;
public Screen(int width, int height, SpriteSheet sheet){
this.width = width;
this.height = height;
this.sheet = sheet;
pixels=new int[width * height];
}
public void render(int xPos, int yPos, int tile, int colour){
render(xPos, yPos, tile, colour, false, false);
}
public void render(int xPos, int yPos, int tile, int colour, boolean mirrorX, boolean mirrorY){
xPos -= xOffset;
yPos -= yOffset;
int xTile = tile %32;
int yTile = tile /32;
int tileOffset=(xTile<<3)+(yTile<<3)*sheet.width;
for(int y=0;y<8;y++){
if(y+yPos<0 || y+yPos>=height)continue;
int ySheet = y;
if(mirrorY) ySheet = 7 - y;
for(int x=0;x<8;x++){
if(x+xPos<0 || x+xPos>=width)continue;
int xSheet = x;
if(mirrorX) xSheet = 7 - x;
int col=(colour>>(sheet.pixels[xSheet+ySheet*sheet.width+tileOffset]*8))&255;
if(col<255) pixels[(x+xPos)+(y+yPos)*width]=col;
}
}
}
}
This is my display class, anyway this error is killing me and i hae no idea how to fix it whatsoever, I have looked all over the place bot a single place, the error i am getting is
The method render(String, Screen, int, int, int, int) in the type Font is not applicable for the arguments (String, Screen, int, int, int)
Try cleaning and rebuilding the project. It seems like an older version of the program is being run...
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Improve this question
I am working on a game and I am getting this error for my code:
Exception in thread "main" java.lang.IllegalArgumentException: input == null!
at javax.imageio.ImageIO.read(Unknown Source)
at com.mcserverpros.game.gfx.SpriteSheet.<init>(SpriteSheet.java:21)
at com.mcserverpros.game.Game.<init>(Game.java:32)
at com.mcserverpros.game.Game.main(Game.java:146)
This is my Game.java class:
package com.mcserverpros.game;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.JFrame;
import com.mcserverpros.game.gfx.SpriteSheet;
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 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 SpriteSheet spriteSheet = new SpriteSheet("/sprite_sheet.png");
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();
}
public synchronized void stop() {
running = false;
}
public void run() {
long lastTime = System.nanoTime();
double nsPerTick = 1000000000D / 60D;
int frames = 0;
int ticks = 0;
long lastTimer = System.currentTimeMillis();
double delta = 0;
while (running) {
long now = System.nanoTime();
delta += (now - lastTime) / nsPerTick;
lastTime = now;
boolean shouldRender = false;
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(ticks + " ticks" + ", " + frames + " frames");
frames = 0;
ticks = 0;
}
}
}
public void tick() {
tickCount++;
for (int i = 0; i < pixels.length; i++) {
pixels[i] = i + tickCount;
}
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
g.dispose();
bs.show();
}
public static void main(String[] args) {
new Game().start();
}
}
And this is my SpriteSheet.java class
package com.mcserverpros.game.gfx;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
public class SpriteSheet {
public String path;
public int width;
public int height;
public int[] pixels;
public SpriteSheet(String path) {
BufferedImage image = null;
try {
image = ImageIO.read(SpriteSheet.class.getResourceAsStream(path));
} catch (IOException e) {
e.printStackTrace();
}
if (image == null) {
return;
}
this.path = path;
this.width = image.getWidth();
this.height = image.getHeight();
pixels = image.getRGB(0, 0, width, height, null, 0, width);
for (int i = 0; i < pixels.length; i++) {
pixels[i] = (pixels[i] & 0xff) / 64;
}
for (int i = 0; i < 8; i++) {
System.out.println(pixels[i]);
}
}
}
Check this line:
ImageIO.read(SpriteSheet.class.getResourceAsStream(path))
It seems that SpriteSheet.class.getResourceAsStream(path) is returning a null value. It's quite possible that path isn't pointing to an actual file in the filesystem. Notice that you're passing "/sprite_sheet.png", that's a path relative to the source code's directory. Take a look at this post to get an idea of how you can build a relative path that works. If all else fails you could use an absolute path, but that won't be portable.
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.