Witam! Nie dawno zacząłem naukę pisania gier w Javie. Na razie uczę się z youtube, lecz po próbie dodania własnych tekstur przez SpriteSheet wywala mi błąd. Nigdzie nie mogę poszukać rozwiązania mojego problemu. Czy mógł by ktoś powiedzieć dlaczego wywala mi błąd? Na komentarze nie zwracajcie uwagi, mają pomóc w modyfikacji kodu w późniejszym czasie, gdy już będę ogarniał nieco więcej.
Treść błędu
Thread[Display](Suspended(exception NullPointerException))
- Sprite.load() line: 33
- Sprite.<init>(int,int,int,SpriteSheet)line:26
- Sprite.<clinit>() line:18
- Screen.render(int,int) line:53
- Game.render() line: 127
*Game.run() line:83 - Thread.run line: not available
Klasa Screen
package avim.gra.graphics;
import java.util.Random;
public class Screen {
private int width,height;
public int[]pixels;
public final int MAP_SIZE =8; // wielkosc mapy ilosci tekstur w paczce?
//po tej cyfrze sie zapetla
public final int MAP_SIZE_MASK = MAP_SIZE -1;
public int[] tiles = new int[64*64]; //ilosc kolorow
private Random random = new Random();
//pobieramy z klasy game wartosci
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;
}
}
//czysci pixel
public void clear(){
for (int i =0; i <pixels.length;i++){
pixels[i]=0;
}
}
//rysuje pixel
public void render(int xOffset, int yOffset){
for(int y=0;y<height;y++){
int yy = y+yOffset;;
// if(yy<0 || yy>=height) break; //koniec renderu przy krawdzi
for(int x = 0; x<width;x++){
int xx = x + xOffset;;
// if(xx<0 || xx>=width)break; //koniec renderu przy krawedzi
// int tileIndex = (x / 16) + (y / 16) * 64;
int tileIndex = ((xx>>4)& MAP_SIZE_MASK) + ((yy>>4)&MAP_SIZE_MASK) * MAP_SIZE;
//x&15 bo 16x16 jest od 0 liczymy
pixels[x+y*width] = Sprite.grass.pixels[(x&15)+(y+15) * 16];
}//petla 2
}//petla 1
}//render
}//screen
Klasa Sprite
package avim.gra.graphics;
public class Sprite {
public final int SIZE;
private int x,y;
public static int[] pixels;
private SpriteSheet sheet;
//tworzenie sprite trawy, 16-wielkosc tekstury w px
// pierwsze 0 pozycja x w spritesheet.png
// drugie 0 pozycja y jak wyzej
// kratka nizej to zmiana x lub y o 1 wiecej
public static Sprite grass = new Sprite(16,0,0,null);
public Sprite(int size, int x, int y, SpriteSheet sheet){
SIZE = size;
pixels = new int [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];
}//petla x
}//petla y
}
}
Klasa SpriteSheet
package avim.gra.graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class SpriteSheet {
private String path;
public final int SIZE;
public int[] pixels;
//256 wielkosc px w pliku
public static SpriteSheet tiles = new SpriteSheet("/textures/spritesheet.png",256);
public SpriteSheet(String path, int size){
this.path = path;
this.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();
}
}
}
Klasa Game
package avim.gra;
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 avim.gra.graphics.Screen;
import avim.gra.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;
private Thread thread;
private JFrame frame;
private Keyboard key;
private boolean running = false;
public static String title="Gra";
private Screen screen;
private BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
private int[] pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
//tworzymy cnavas
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);
}
//start wątku
public synchronized void start() {
running = true;
thread = new Thread(this, "Display");
thread.start();
}
//zatryzmanie wątku
public synchronized void stop() {
running = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//ekran rendering i update
@Override
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;
System.out.println(updates + " ups, " + frames + " fps");
frame.setTitle(title + " | " + updates + " ups, " + frames + " fps");
updates = 0;
frames = 0;
}
}
stop();
}
int x=0,y=0;
public void update() {
key.update();
//porusznie mapy X i Y
if(key.up) y--;
if(key.down) y++;
if(key.left)x--;
if(key.right)x++;
}
public void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
//polaczeni z klsa screen
screen.clear();
screen.render(x,y);
for(int i = 0; i<pixels.length;i++){
pixels[i]= screen.pixels[i];
}
Graphics g = bs.getDrawGraphics();
// Rysowanie tutaj
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.drawImage(image,0,0,getWidth(),getHeight(),null);
g.dispose();
bs.show();
}
//ustawiamy cale okno
public static void main(String[] args) {
Game game = new Game();
game.frame.setResizable(false);
game.frame.setTitle(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();
}
}