JFrame sprite sheet black screen - java

So I have been trying to follow a tutorial
But it isn't working. It is a tutorial on making a sprite sheet with JFrame. I could get other things to work, but for some reason this won't. It is supposed to display a tiled image, but instead it displays a black screen.
Game.java
package ca.colescheler.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 javax.swing.JFrame;
import ca.colescheler.game.gfx.Screen;
import ca.colescheler.game.gfx.SpriteSheet;
#SuppressWarnings("unused")
public class Game extends Canvas implements Runnable {
/**
*
*/
private static final long serialVersionUID = 9086760045199246082L;
private BufferedImage image = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
private int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
public boolean running;
private static final long serialVesionUID = 1;
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;
int tickCount=1;
private SpriteSheet spriteSheet = new SpriteSheet("/sprite_sheet.png");
private Screen screen;
public static long getSerialvesionuid() {
return serialVesionUID;
}
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() {
screen = new Screen(WIDTH,HEIGHT,new SpriteSheet("/sprite_sheet.png"));
}
public void tick() {
tickCount++;
}
long now = System.nanoTime();
public synchronized void stop() {
// TODO Auto-generated method stub
}
public synchronized void start() {
// TODO Auto-generated method stub
//new Thread(this).start();
running = true;
run();
frames = 1;
ticks = 1;
}
static int frames = 0;
static int ticks = 0;
public void run() {
long lastTime = System.nanoTime();
double nsPerTick = 1000000000d/60d;
long lastTimer = System.currentTimeMillis();
double delta=0;
while (running) {
init();
long now = System.nanoTime();
delta += (now - lastTime) / nsPerTick;
lastTime = now;
boolean shouldRender = false;
while (delta >= 1) {
ticks++;
tick();
delta -= 1;
shouldRender = true;
}
if (shouldRender) {
render();
}
if (System.currentTimeMillis() - lastTimer > 1000) {
lastTimer += 1000;
System.out.println(frames + ", " + ticks);
frames=0;
ticks=0;
}
}
}
public void render() {
BufferStrategy bs = this.getBufferStrategy();
if (bs == null) {
this.createBufferStrategy(3);
return;
}
screen.render(pixels, 0, WIDTH);
Graphics g = bs.getDrawGraphics();
//g.drawRect(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();
}
}
SpriteSheet.java
package ca.colescheler.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) {
// TODO Auto-generated catch block
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);
//AARRGGBB
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]);
}
//85*0
}
}
Screen.java
package ca.colescheler.game.gfx;
public class Screen {
public static final int MAP_WIDTH = 64;
public static final int MAP_WIDTH_MASK = MAP_WIDTH - 1;
public int[] tiles = new int[MAP_WIDTH * MAP_WIDTH];
public int[] colours = new int[MAP_WIDTH * MAP_WIDTH * 4];
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;
for (int i=1;i<MAP_WIDTH*MAP_WIDTH;i++) {
colours[i*4+0] = 0xff00ff;
colours[i*4+1] = 0x00ffff;
colours[i*4+2] = 0xffff00;
colours[i*4+3] = 0xffffff;
}
}
public void render(int[] pixels, int offset, int row) {
for (int yTile = yOffset>>3;yTile <-(yOffset + height) >>3; yTile++) {
int yMin = yTile * 8 - yOffset;
int yMax = yMin + 8;
if (yMin < 0) yMin = 0;
if (yMax > height) yMax = height;
for (int xTile = xOffset >>3; xTile <=(xOffset+width) >>3; xTile++) {
int xMin = xTile * 8 - xOffset;
int xMax = xMin + 8;
if (xMin < 0) xMin = 0;
if (xMax > width) xMax = height;
int tileIndex = (xTile &(MAP_WIDTH_MASK)) + (yTile & (MAP_WIDTH_MASK)) * MAP_WIDTH;
for (int y = yMin;y<yMax;y++) {
int sheetPixel = ((y+yOffset) & 7) * sheet.width + ((xMin + xOffset) & 7);
int tilePixel = offset + xMin + y * row;
for (int x=xMin; x<xMax;x++) {
int colour = tileIndex * 4 + sheet.pixels[sheetPixel++];
pixels[tilePixel++]=colours[colour];
}
}
}
}
}}
Link to tutorial

In the file Screen.java, there is a typo. You should change height to width in the following line:
if (xMax > width) xMax = height;

Related

How to make Java game more efficient?

I have been working on a flappy bird clone so I can get more practice programming. Everything in the game works, however the game has frame skips and lag drops, and I do not know how to make Java programs run more smoothly. Am I supposed to measure the amount of time a method takes and try to shorten that, or do I do something else? I have seen people explain how to program Java games, but there is hardly anything on improving the performance. Any advice would be helpful. Thank you.
Hazards class
package entity;
import java.util.ArrayList;
public class Hazards {
public ArrayList<Horizontal> hors;
public ArrayList<Vertical> verts;
public Hazards(int width, int height, int thickness) {
hors = new ArrayList<Horizontal>();
hors.add(new Horizontal(0, 0, width, thickness));
hors.add(new Horizontal(0, height-thickness, width, thickness));
verts = new ArrayList<Vertical>();
}
}
Horizontal class
package entity;
import java.awt.Rectangle;
public class Horizontal {
public int xPos, yPos, width, height;
public Rectangle bounds;
public Horizontal(int x, int y, int w, int h) {
this.xPos = x;
this.yPos = y;
this.width = w;
this.height = h;
this.bounds = new Rectangle(x, y, w, h);
}
public void updateBounds(int x, int y, int w, int h) {
this.xPos = x;
this.yPos = y;
this.width = w;
this.height = h;
this.bounds = new Rectangle(x, y, w, h);
}
}
Vertical class
package entity;
import java.awt.Rectangle;
import java.util.Random;
public class Vertical {
public int xPos, width, gapSize, gapPos;
public boolean scoredOn = false;
public Rectangle top, bottom;
public Vertical(int xPos, int width, int roofHeight, int floorHeight, int gapSize) {
this.xPos = xPos;
this.width = width;
this.gapPos = new Random().nextInt(floorHeight - gapSize) + roofHeight;
this.top = new Rectangle();
this.bottom = new Rectangle();
this.top.setBounds(xPos, 0, width, gapPos);
this.bottom.setBounds(xPos, gapPos + gapSize, width, floorHeight - roofHeight + top.height + gapSize);
}
}
Content class
package main;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.JPanel;
public class Content extends JPanel {
private static final long serialVersionUID = 1L;
private Engine e;
private Rectangle bounds;
public Content(Engine engine) {
e = engine;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.clearRect(0, 0, this.getWidth(), this.getHeight());
// Roof and floor
g.setColor(Color.black);
for (int x = 0; x < e.e.hors.size(); x++) {
bounds = e.e.hors.get(x).bounds;
g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
}
// Pipes
g.setColor(Color.black);
for(int x = 0; x < e.e.verts.size(); x++) {
bounds = e.e.verts.get(x).top;
g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
bounds = e.e.verts.get(x).bottom;
g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
}
// Player
g.setColor(Color.black);
g.fillRect((int) e.p.xPos, (int) e.p.yPos, e.p.size, e.p.size);
// Score
g.setColor(Color.blue);
g.setFont(new Font("Monospaced", Font.PLAIN, 40));
g.drawString(Integer.toString(e.p.score), e.width/2, 80);
}
}
Engine class
package main;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import entity.Hazards;
import entity.Vertical;
import screen.TitleScreen;
public class Engine implements Runnable {
public JFrame f;
public String title = "Flappy Bird";
public int width = 500, height = 500;
public Content c;
public boolean running = false;
public boolean playing = false;
public Thread t;
public Player p;
public Hazards e;
public TitleScreen ts;
public JPanel mainPanel;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Engine e = new Engine();
e.execute();
}
});
}
public void execute() {
ts = new TitleScreen(width, height);
e = new Hazards(width, height, 30);
p = new Player(this);
c = new Content(this);
c.setPreferredSize(new Dimension(width, height));
c.setLayout(null);
c.addKeyListener(p);
mainPanel = new JPanel();
mainPanel.setPreferredSize(new Dimension(width, height));
mainPanel.setLayout(null);
f = new JFrame();
f.setTitle(title);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setResizable(false);
f.add(c);
// f.add(mainPanel);
f.pack();
f.createBufferStrategy(2);
f.setLayout(null);
f.setLocationRelativeTo(null);
f.setVisible(true);
c.requestFocus();
//ts.setScreen(mainPanel);
start();
}
public synchronized void start() {
if (running)
return;
running = true;
t = new Thread(this);
t.start();
}
public synchronized void stop() {
if (!running)
return;
running = false;
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
long lastime = System.nanoTime();
double AmountOfTicks = 60;
double ns = 1000000000 / AmountOfTicks;
double delta = 0;
int tick = 0;
while (running) {
long now = System.nanoTime();
delta += (now - lastime) / ns;
lastime = now;
if (delta >= 1) {
// Call all updates here
if (playing) {
p.updatePos();
tick++;
if (tick == 60) {
tick = 0;
p.distance += p.speed;
System.out.println(p.distance);
if ((p.distance % 4) == 0) {
System.out.println("Making new pipes-----------------------------------------------------");
e.verts.add(new Vertical(600, 10, 30, height - 30, 100));
}
}
for (int x = 0; x < e.verts.size(); x++) {
e.verts.get(x).top.x -= p.speed;
e.verts.get(x).bottom.x -= p.speed;
if(e.verts.get(x).top.x<-50) {
e.verts.remove(x);
System.out.println("removed a pipe");
}
if(p.xPos>e.verts.get(x).top.x && !e.verts.get(x).scoredOn) {
e.verts.get(x).scoredOn = true;
p.score++;
}
}
}
mainPanel.revalidate();
mainPanel.repaint();
f.revalidate();
f.repaint();
delta--;
}
}
}
}
Player class
package main;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Player implements KeyListener {
public int size = 10;
public double xPos = 50;
public double yPos = 240;
public double gravity = 3.4;
public double jumpForce = 16.6;
public double weight = 1;
public int speed = 2;
public int score = 0;
public int distance = 0;
public boolean jumping = false;
public double jumpTime = 10;
public int timed = 0;
public Rectangle bounds, temp, top, bottom;
public Engine en;
public Player(Engine engine) {
en = engine;
bounds = new Rectangle((int)xPos, (int)yPos, size, size);
}
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_W && en.playing) {
jumping = true;
} else if (e.getKeyCode() == KeyEvent.VK_SPACE) {
en.playing = !en.playing;
}
if(jumping) {
timed = 0;
jumpForce = 16.6;
}
}
public void keyReleased(KeyEvent e) {
}
public void updatePos() {
// collide with floor or ceiling
for(int x = 0; x < en.e.hors.size(); x++) {
temp = en.e.hors.get(x).bounds;
if(bounds.intersects(temp)) {
en.playing = false;
jumping = false;
timed = 0;
jumpForce = 0;
yPos = 240;
score = 0;
en.e.verts.clear();
distance = 0;
gravity = 3.8;
}
}
// collide with pipe
for(int x =0; x <en.e.verts.size();x++) {
top = en.e.verts.get(x).top;
bottom = en.e.verts.get(x).bottom;
if(bounds.intersects(top)||bounds.intersects(bottom)) {
en.playing = false;
jumping = false;
timed = 0;
jumpForce = 0;
yPos = 240;
score = 0;
gravity =3.4;
en.e.verts.clear();
distance = 0;
}
}
if (jumping && en.playing) {
gravity = 3.4;
yPos -= jumpForce;
jumpForce -= weight;
if (jumpForce == 0) {
jumping = false;
jumpForce = 16.6;
}
}
//if(!jumping && en.playing) {
gravity += 0.1;
//}
System.out.println(gravity);
yPos += gravity;
bounds.setBounds((int)xPos, (int)yPos, size, size);
}
}

Java - Graphics pixels aren't correctly updating?

Right now I just wanted to get my game window shown on the screen and I thought all would be well, except for the fact that the color red isn't shown on the whole window. Not sure why, I've gone over my code a few times and can't figure anything out. This is my code:
package 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;
public class Game extends Canvas implements Runnable {
private final String GAME_NAME;
private final int GAME_WIDTH;
private final int GAME_HEIGHT;
private final int SCALE;
private boolean isRunning;
private JFrame frame;
private BufferedImage image;
private int[] pixels;
public Game(String name, int width, int aspectRatio[], int scale) {
// Variabe Initialization
this.GAME_NAME = name;
this.GAME_WIDTH = width;
this.GAME_HEIGHT = width / aspectRatio[0] * aspectRatio[1];
this.SCALE = scale;
this.image = new BufferedImage(GAME_WIDTH, GAME_WIDTH, BufferedImage.TYPE_INT_RGB);
this.pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
this.frame = new JFrame(GAME_NAME);
Init();
}
private void Init() {
// Frame Setup
setMinimumSize(new Dimension(GAME_WIDTH * SCALE, GAME_HEIGHT * SCALE));
setMaximumSize(new Dimension(GAME_WIDTH * SCALE, GAME_HEIGHT * SCALE));
setPreferredSize(new Dimension(GAME_WIDTH * SCALE, GAME_HEIGHT * SCALE));
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 void Start() {
isRunning = true;
new Thread(this).start();
}
private void Stop() {
isRunning = false;
}
#Override
public void run() {
long lastTime = System.nanoTime();
long timer = System.currentTimeMillis();
final double ns = 1000000000d / 60d;
double delta = 0d;
int frames = 0;
int updates = 0;
while (isRunning) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 1) {
updates++;
Update();
delta--;
}
Render();
frames++;
if (System.currentTimeMillis() - timer > 1000) {
timer += 1000;
frame.setTitle(GAME_NAME + " | " + updates + " ups, " + frames + " fps");
updates = 0;
frames = 0;
}
}
}
public void Update() {
for (int y = 0; y < GAME_HEIGHT; y++) {
for (int x = 0; x < GAME_WIDTH; x++) {
pixels[x + y * GAME_WIDTH] = 0xffff0000;
}
}
}
public void Render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
requestFocus();
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("Game", 160, new int[]{12, 9}, 1).Start();
}
}
You've accidentally passed GAME_WIDTH as the height argument of the BufferedImage constructor call:
public Game(String name, int width, int aspectRatio[], int scale) {
// Variabe Initialization
this.GAME_NAME = name;
this.GAME_WIDTH = width;
this.GAME_HEIGHT = width / aspectRatio[0] * aspectRatio[1];
this.SCALE = scale;
this.image = new BufferedImage(GAME_WIDTH, GAME_WIDTH, BufferedImage.TYPE_INT_RGB);
// ^^^^^^^^^^
this.pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
this.frame = new JFrame(GAME_NAME);
Init();
}
You probably meant to use GAME_HEIGHT:
this.image = new BufferedImage(GAME_WIDTH, GAME_HEIGHT, BufferedImage.TYPE_INT_RGB);

Java - ImageIO not getting picture

I am trying to add the image sprite_sheet.png to my game project but I get these errors:
Exception in thread "main" java.lang.IllegalArgumentException: input == null!
at javax.imageio.ImageIO.read(Unknown Source)
at az.rehman.gfx.SpriteSheet.<init>(SpriteSheet.java:16)
at az.rehman.game.Game.<init>(Game.java:29)
at az.rehman.game.Game.main(Game.java:127)
Here are my classes:
package az.rehman.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.getResource(path));
} catch (IOException e) {
System.out.println("SpriteSheet file exception");
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]);
}
} // constructer end
} // class end
package az.rehman.game;
import az.rehman.gfx.SpriteSheet;
import javax.swing.*;
import java.awt.*;
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 {
public 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 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 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(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();
}
}

Getting a NullPointerException for some reason

I'm following a tutorial from theChernoProject, however in episode 22 i keep getting a nullPointerException whem trying to render the pixels array from the sprite ?
Error:
Exception in thread "Game" java.lang.ExceptionInInitializerError
at com.santec.game.learning.thecherno.graphics.Screen.render(Screen.java:40)
at com.santec.game.learning.thecherno.Game.render(Game.java:109)
at com.santec.game.learning.thecherno.Game.run(Game.java:78)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
at com.santec.game.learning.thecherno.graphics.Sprite.load(Sprite.java:23)
at com.santec.game.learning.thecherno.graphics.Sprite.<init>(Sprite.java:17)
at com.santec.game.learning.thecherno.graphics.Sprite.<clinit>(Sprite.java:10)
... 4 more
Classes:
Game.java :
package com.santec.game.learning.thecherno;
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;
import com.santec.game.learning.thecherno.graphics.Screen;
import com.santec.game.learning.thecherno.input.Keyboard;
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;
public static String title = "Rain";
private Thread thread;
private JFrame frame;
private boolean running = false;
private Screen screen;
private Keyboard key;
private BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
private int[] pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
public Game() {
Dimension size = new Dimension(width * scale, height * scale);
setPreferredSize(size);
screen = new Screen(width, height);
frame = new JFrame();
key = new Keyboard();
addKeyListener(key);
}
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 void run() {
long lastTime = System.nanoTime();
long timer = System.currentTimeMillis();
final double ns = 1000000000.0 / 60.0;
double delta = 0;
int frames = 0;
int updates = 0;
while(running) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >= 1) {
update();
updates++;
delta--;
}
render();
frames++;
if(System.currentTimeMillis() - timer > 1000) {
timer += 1000;
frame.setTitle(title + ": " + updates + " ups | " + frames + " fps");
updates = 0;
frames = 0;
}
}
stop();
}
int x = 0, y = 0;
public void update() {
key.update();
if(key.up) y--;
if(key.down) y++;
if(key.right) x++;
if(key.left) x--;
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if(bs == null) {
createBufferStrategy(3);
return;
}
screen.clear();
screen.render(x, y);
for(int i = 0; i < pixels.length; i++) {
pixels[i] = screen.pixels[i];
}
Graphics g = bs.getDrawGraphics();
{
g.setColor(Color.cyan);
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
}
g.dispose();
bs.show();
}
public static void main(String[] args) {
Game game = new Game();
game.frame.setResizable(false);
game.frame.setTitle(game.title);
game.frame.add(game);
game.frame.pack();
game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.frame.setLocationRelativeTo(null);
game.frame.setVisible(true);
game.start();
}
}
graphics/SpriteSheet.java :
package com.santec.game.learning.thecherno.graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
public class SpriteSheet {
private String path;
public final int SIZE;
public int[] pixels;
// Spritesheets
public static SpriteSheet terrain = new SpriteSheet("/textures/terrain.png", 96);
public SpriteSheet(String path, int size) {
this.path = path;
SIZE = size;
pixels = new int[SIZE * SIZE];
load();
}
private void load() {
try {
BufferedImage image = ImageIO.read(SpriteSheet.class.getResource(path));
int w = image.getWidth();
int h = image.getHeight();
image.getRGB(0, 0, w, h, pixels, 0, w);
} catch (IOException e) {
e.printStackTrace();
}
}
}
graphics/Screen.java :
package com.santec.game.learning.thecherno.graphics;
import java.util.Random;
public class Screen {
private int width, height;
public int[] pixels;
public final int MAP_SIZE = 8;
public final int MAP_SIZE_MASK = MAP_SIZE - 1;
public int[] tiles = new int[MAP_SIZE * MAP_SIZE];
private Random random = new Random();
public Screen(int width, int height) {
this.width = width;
this.height = height;
pixels = new int[width * height];
for(int i = 0; i < MAP_SIZE * MAP_SIZE; i++) {
tiles[i] = random.nextInt(0xffffff);
tiles[0] = 0;
}
}
public void clear() {
for(int i = 0; i < pixels.length; i++) {
pixels[i] = 0;
}
}
public void render(int xOffset, int yOffset) {
for(int y = 0; y < height; y++) {
int yy = y + yOffset;
if(yy >= height || yy < 0) break;
for(int x = 0; x < width; x++) {
int xx = x + xOffset;
if(xx >= width || xx < 0) break;
int tileIndex = ((xx >> 4) & MAP_SIZE_MASK) + ((yy >> 4) & MAP_SIZE_MASK) * 8;
pixels[x + y * width] = Sprite.grass.pixels[(xx & 15) + (yy & 15) * Sprite.grass.SIZE];
}
}
}
}
graphics/Sprite.java :
package com.santec.game.learning.thecherno.graphics;
public class Sprite {
public final int SIZE;
private int x, y;
public int[] pixels;
private SpriteSheet sheet;
public static Sprite grass = new Sprite(16, 0, 1, SpriteSheet.terrain);
public Sprite(int size, int x, int y, SpriteSheet sheet) {
SIZE = size;
this.x = x * size;
this.y = y * size;
this.sheet = sheet;
load();
}
private void load() {
for(int y = 0; y < SIZE; y++) {
for(int x = 0; x < SIZE; x++) {
pixels[x + y * SIZE] = sheet.pixels[(x + this.x) + (y + this.y) * sheet.SIZE];
}
}
}
}
You never initialize the pixels array.
add
this.pixels = new int[SIZE*SIZE]; // assuming that's the desired length or that array
to the start of your load method.

Null pointer exception despite done right

I recently was coding but encountered an null pointer exception
the stack trace says
Exception in thread "main" java.lang.NullPointerException
at com.masterkgames.twisteddream.level.SpawnLevel.generateLevel(SpawnLevel.java:34)
at com.masterkgames.twisteddream.level.Level.<init>(Level.java:22)
at com.masterkgames.twisteddream.level.SpawnLevel.<init>(SpawnLevel.java:16)
at com.masterkgames.twisteddream.Game.<init>(Game.java:49)
at com.masterkgames.twisteddream.Game.main(Game.java:138)
below are the 3 mentioned classes
Spawnlevel.java:
package com.masterkgames.twisteddream.level;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import com.masterkgames.twisteddream.level.tile.Tile;
public class SpawnLevel extends Level {
private Tile[] tiles;
private int[] levelPixels;
public SpawnLevel(String path) {
super(path);
}
protected void loadLevel(String path){
try{
BufferedImage image = ImageIO.read(SpawnLevel.class.getResource(path));
int w = image.getWidth();
int h = image.getHeight();
tiles = new Tile[w * h];
levelPixels = new int[w * h];
image.getRGB(0,0,w,h,levelPixels,0,w);
}catch(IOException e){
e.printStackTrace();
}
}
protected void generateLevel(){
for(int i = 0; i < levelPixels.length; i++){
if(levelPixels[i] == 0xff00) tiles[i] = Tile.Grass;
if(levelPixels[i] == 0xffff00) tiles[i] = Tile.Rose;
if(levelPixels[i] == 0x7f7f00) tiles[i] = Tile.Stone;
}
}
}
level.java:
package com.masterkgames.twisteddream.level;
import com.masterkgames.twisteddream.graphics.Screen;
import com.masterkgames.twisteddream.level.tile.Tile;
public class Level {
public Screen screen;
protected int width, height;
protected Tile[] tiles;
protected int[] tilesInt;
public Level(int width, int height) {
this.width = width;
this.height = height;
tilesInt = new int[width * height];
generateLevel();
}
public Level(String path) {
loadLevel(path);
generateLevel();
}
protected void generateLevel() {
}
private void loadLevel(String path) {
}
public void update() {
}
private void time() {
}
public void render(int xScroll, int yScroll, Screen screen) {
screen.setOffset(xScroll, yScroll);
int x0 = xScroll >> 4;
int x1 = (xScroll + screen.width + 16) >> 4;
int y0 = yScroll >> 4;
int y1 = (yScroll + screen.height + 16) >> 4;
for (int y = y0; y < y1; y++) {
for (int x = x0; x < x1; x++) {
// getTile(x, y).render(x, y, screen);
if (x + y * 16 < 0 || x + y * 16 >= 256) {
Tile.Void.render(x, y, screen);
continue;
}
tiles[x + y * 16].render(x, y, screen);
}
}
}
public Tile getTile(int x, int y) {
if (x < 0 || y < 0)
return Tile.Void;
if (x >= width || y >= height)
return Tile.Void;
if (tilesInt[x + y * width] == 0)
return Tile.Grass;
if (tilesInt[x + y * width] == 1)
return Tile.Rose;
if (tilesInt[x + y * width] == 2)
return Tile.Stone;
return Tile.Void;
}
}
and lastly
game.java:
package com.masterkgames.twisteddream;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
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.masterkgames.twisteddream.entity.mob.Player;
import com.masterkgames.twisteddream.graphics.Screen;
import com.masterkgames.twisteddream.input.Keyboard;
import com.masterkgames.twisteddream.level.Level;
import com.masterkgames.twisteddream.level.SpawnLevel;
public class Game extends Canvas implements Runnable {
private static final long serialVersionUID = 1L;
public static int width = 300;
public static int height = 168;
public static int scale = 3;
public String Title = "Twisted Dream";
private Thread thread;
private boolean running = false;
private Screen screen;
private Keyboard key;
private Level level;
private Player player;
private JFrame frame;
private BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
private int[] pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
public Game() {
Dimension size = new Dimension(width * scale, height * scale);
setPreferredSize(size);
screen = new Screen(width,height);
key = new Keyboard();
level = new SpawnLevel("/textures/level.png");
player = new Player(key);
frame = new JFrame();
addKeyListener(key);
}
public synchronized void start() {
thread = new Thread(this, "Display");
thread.start();
running = true;
}
public synchronized void stop() {
running = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void run() {
long lastTime = System.nanoTime();
long timer = System.currentTimeMillis();
final double ns = 1000000000.0 / 60.0;
double delta = 0;
int frames = 0;
int updates = 0;
requestFocus();
while (running) {
long nowTime = System.nanoTime();
delta += (nowTime - lastTime) / ns;
lastTime = nowTime;
while (delta >= 1){
update();
updates++;
delta--;
}
render();
frames++;
if(System.currentTimeMillis() - timer > 1000){
timer += 1000;
System.out.println(updates + " ups, " + frames + " fps");
frame.setTitle(Title + " | " + updates + " ups, " + frames + " fps");
updates = 0;
frames = 0;
}
}
stop();
}
public void update() {
key.update();
player.update();
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
screen.clear();
int xScroll = player.x - screen.width / 2;
int yScroll = player.y - screen.height / 2;
level.render(xScroll, yScroll, screen);
player.render(screen);
for(int i = 0; i < pixels.length; i++){
pixels[i] = screen.pixels[i];
}
Graphics g = bs.getDrawGraphics();
g.drawImage(image,0,0,getWidth(),getHeight(),null);
g.setFont(new Font("arial", 0, 15));
g.setColor(Color.white);
g.dispose();
bs.show();
}
public static void main(String[] args) {
Game game = new Game();
game.frame.setResizable(false);
game.frame.setTitle(game.Title);
game.frame.add(game);
game.frame.pack();
game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.frame.setLocationRelativeTo(null);
game.frame.setVisible(true);
game.start();
}
}
p.s this issue according to the stack trace is in the line for(int i = 0; i < levelPixels.length; i++) in SpawnLevel.java
in Level contructor you have generateLevel(); where you are using levelPixels, which is not initialized
contructor call
private void loadLevel(String path) {
}
from class Level, you have to call method loadLevel in SpawnLevel constructor
You are accessing the null array levelPixels.
Here is where your error is:
In your main you call a new SpawnLevel(path)
But SpawnLevel(path) calls the super constructor, which calls its blank yet defined loadLevel and generateLevel. The loadLevel and generateLevel in SpawnLevel are never called, and the member variables are never initialized.
So basically, you tried to use the Level class as an abstract class but you didnt do it correctly. The member variables should be in the Level class if they are to be shared by children of that class. Im guessing this is what you want to do.
you should really get familiar with the debugger, it will be a lifesaver for little problems like this.

Categories

Resources