gpt4 book ai didi

java.lang.NullPointerException 找不到源

转载 作者:行者123 更新时间:2023-11-30 09:19:34 25 4
gpt4 key购买 nike

我正在编写一个 java rpg 游戏,但遇到了困难。我的代码目前有 sprite 动画,一个带有 perlin 噪声和碰撞检测的随机 map 生成。 map 是平铺的,所以我目前正在尝试将 perlin 噪声转换为平铺。 perlin 函数生成一个数组,并将该数组的每个数字导入到一个 tile png 中。这就是问题所在:运行时错误:Java.Lang.NullPointerException。问题是我的编译器 (netbeans) 没有告诉我错误发生的位置,而是只给我这个错误代码。通过排除过程,我设法找到了错误,该错误发生在第 364 行。如果该站点不支持行,则它位于 loadTile() 方法中,位于“if(perlinIsland[x][y] <= 0.05)blockImg [x][y] = 方 block [0];"。我相信所有变量都已正确初始化,但我无法找到解决方案。请原谅长代码,但为了提供信息,我包含了所有内容。预先感谢您的帮助!

package java4k;

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import java.math.*;
import java.util.*;

/**
*
* @author Christophe
*/
public class Main extends JFrame implements Runnable{

public Image dbImage;
public Graphics dbGraphics;

//Image + Array size
final static int listWidth = 500, listHeight = 500;


//Move Variables
int playerX = 320, playerY = 240, xDirection, yDirection;

//Sprites
BufferedImage spriteSheet;

//Lists for sprite sheet: 1 = STILL; 2 = MOVING_1; 3 = MOVING_2
BufferedImage[] ARCHER_NORTH = new BufferedImage[4];
BufferedImage[] ARCHER_SOUTH = new BufferedImage[4];
BufferedImage[] ARCHER_EAST = new BufferedImage[4];
BufferedImage[] ARCHER_WEST = new BufferedImage[4];

Image[] TILE = new Image[8];

//Animation Variables
int currentFrame = 0, framePeriod = 150;
long frameTicker = 0l;
Boolean still = true;
Boolean MOVING_NORTH = false, MOVING_SOUTH = false, MOVING_EAST = false, MOVING_WEST = false;

BufferedImage player = ARCHER_SOUTH[0];

//World Tile Variables
//20 X 15 = 300 tiles
Rectangle[][] blocks = new Rectangle[listWidth][listHeight];
Image[][] blockImg = new Image[listWidth][listHeight];
Image[][] blockImgTrans = new Image[listWidth][listHeight];
Boolean[][] isSolid = new Boolean[listWidth][listHeight];
int tileX = 0, tileY = 0;
Random r = new Random();

Rectangle playerRect = new Rectangle(playerX + 4,playerY+20,32,20);
//Map Navigation
static final byte PAN_UP = 0, PAN_DOWN = 1, PAN_LEFT = 2, PAN_RIGHT = 3;

//Perlin noise variables:
Color test = new Color(0, 0, 0);
static float[][] perlinNoise = new float[listWidth][listHeight];
static float[][] gradiantNoise = new float[listWidth][listHeight];
static float[][] perlinIsland = new float[listWidth][listHeight];
static float[][] biome = new float[listWidth][listHeight];
//Saved as png
static BufferedImage perlinImage;



public Main(){

this.setTitle("JAVA4K");
this.setSize(640,505);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);

addKeyListener(new AL());

TILE[0] = new ImageIcon("C:/Users/Christophe/Documents/NetBeansProjects/Java4k/src/java4k/TILE_GRASS_1.png").getImage();
TILE[1] = new ImageIcon("C:/Users/Christophe/Documents/NetBeansProjects/Java4k/src/java4k/TILE_GRASS_2.png").getImage();
TILE[2] = new ImageIcon("C:/Users/Christophe/Documents/NetBeansProjects/Java4k/src/java4k/TILE_GRASS_3.png").getImage();
TILE[3] = new ImageIcon("C:/Users/Christophe/Documents/NetBeansProjects/Java4k/src/java4k/TILE_WATER_1.png").getImage();
TILE[4] = new ImageIcon("C:/Users/Christophe/Documents/NetBeansProjects/Java4k/src/java4k/TILE_TREE_1_BOT.png").getImage();
TILE[5] = new ImageIcon("C:/Users/Christophe/Documents/NetBeansProjects/Java4k/src/java4k/TILE_TREE_1_TOP.png").getImage();
TILE[6] = new ImageIcon("C:/Users/Christophe/Documents/NetBeansProjects/Java4k/src/java4k/TILE_TREE_2_BOT.png").getImage();
TILE[7] = new ImageIcon("C:/Users/Christophe/Documents/NetBeansProjects/Java4k/src/java4k/TILE_TREE_2_TOP.png").getImage();

loadTiles();

init();
}


//Step 1: Generates array of random number 0 < n < 1
public static float[][] GenerateWhiteNoise(int width, int height){

Random r = new Random();
Random random = new Random(r.nextInt(1000000000)); //Seed to 0 for testing
float[][] noise = new float[width][height];

for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
noise[i][j] = (float)random.nextDouble() % 1;
}
}

return noise;

}

//Step 2: Smooths out random numbers
public static float[][] GenerateSmoothNoise(float[][] baseNoise, int octave){

int width = baseNoise.length;
int height = baseNoise.length;

float[][] smoothNoise = new float[width][height];

int samplePeriod = 1 << octave; // calculates 2 ^ k
float sampleFrequency = 1.0f / samplePeriod;

for (int i = 0; i < width; i++)
{
//calculate the horizontal sampling indices
int sample_i0 = (i / samplePeriod) * samplePeriod;
int sample_i1 = (sample_i0 + samplePeriod) % width; //wrap around
float horizontal_blend = (i - sample_i0) * sampleFrequency;

for (int j = 0; j < height; j++)
{
//calculate the vertical sampling indices
int sample_j0 = (j / samplePeriod) * samplePeriod;
int sample_j1 = (sample_j0 + samplePeriod) % height; //wrap around
float vertical_blend = (j - sample_j0) * sampleFrequency;

//blend the top two corners
float top = Interpolate(baseNoise[sample_i0][sample_j0],
baseNoise[sample_i1][sample_j0], horizontal_blend);

//blend the bottom two corners
float bottom = Interpolate(baseNoise[sample_i0][sample_j1],
baseNoise[sample_i1][sample_j1], horizontal_blend);

//final blend
smoothNoise[i][j] = Interpolate(top, bottom, vertical_blend);
}
}

return smoothNoise;
}

//Used in GeneratePerlinNoise() to derivate functions
public static float Interpolate(float x0, float x1, float alpha)
{
float ft = alpha * 3.1415927f;
float f = (float) (1 - Math.cos(ft)) * .5f;
return x0*(1-f) + x1*f;
}

//Step 3: Combines arrays together to generate final perlin noise
public static float[][] GeneratePerlinNoise(float[][] baseNoise, int octaveCount)
{
int width = baseNoise.length;
int height = baseNoise[0].length;

float[][][] smoothNoise = new float[octaveCount][][]; //an array of 2D arrays containing

float persistance = 0.5f;

//generate smooth noise
for (int i = 0; i < octaveCount; i++)
{
smoothNoise[i] = GenerateSmoothNoise(baseNoise, i);
}

float[][] perlinNoise = new float[width][height];
float amplitude = 1.0f;
float totalAmplitude = 0.0f;

//blend noise together
for (int octave = octaveCount - 1; octave >= 0; octave--)
{
amplitude *= persistance;
totalAmplitude += amplitude;

for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
perlinNoise[i][j] += smoothNoise[octave][i][j] * amplitude;
}
}
}

//normalisation
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
perlinNoise[i][j] /= totalAmplitude;
}
}

return perlinNoise;
}

//Step 4: Generate circular gradiant: center = 0, outside = 1
public static float[][] GenerateCircularGradiant(float[][] base, int size, int centerX, int centerY){

base = new float[size][size];

for (int x = 0; x < base.length; x++) {
for (int y = 0; y < base.length; y++) {

//Simple squaring, you can use whatever math libraries are available to you to make this more readable
//The cool thing about squaring is that it will always give you a positive distance! (-10 * -10 = 100)
float distanceX = (centerX - x) * (centerX - x);
float distanceY = (centerY - y) * (centerY - y);

float distanceToCenter = (float) Math.sqrt(distanceX + distanceY);

//Make sure this value ends up as a float and not an integer
//If you're not outputting this to an image, get the correct 1.0 white on the furthest edges by dividing by half the map size, in this case 64. You will get higher than 1.0 values, so clamp them!
float mapSize = base.length/2;
//mapSize = 500;
distanceToCenter = distanceToCenter / mapSize;

base[x][y] = distanceToCenter - 0.2f;

}
}

return base;
}

//step 5: Combine perlin noise with circular gradiant to create island
public static float[][] GenerateIsland(float[][] baseCircle, float[][] baseNoise){

float[][] baseIsland = new float[baseNoise.length][baseNoise.length];

for(int x = 0; x < baseNoise.length; x++){
for(int y = 0; y < baseNoise.length; y++){
baseIsland[x][y] = baseNoise[x][y] - baseCircle[x][y];
}
}

return baseIsland;
}

//Method for optional paramater = float[][] biome
public static void GreyWriteImage(float[][] data, String filename){

float[][] temp = null;
GreyWriteImage(data, temp, filename);
}

//Converts array data to png image
public static void GreyWriteImage(float[][] data, float[][] biome, String fileName){
//this takes and array of doubles between 0 and 1 and generates a grey scale image from them

BufferedImage image = new BufferedImage(data.length,data[0].length, BufferedImage.TYPE_INT_RGB);

for (int y = 0; y < data[0].length; y++)
{
for (int x = 0; x < data.length; x++)
{


if (data[x][y]>1){
data[x][y]=1;
}
if (data[x][y]<0){
data[x][y]=0;
}


Color col;

//Deep Water 0 - 0.05
if(data[x][y] <= 0.05) col = new Color(0, 0, 255);
//Shallow Water 0.05 - 0.08
else if(data[x][y] <= 0.08) col = new Color(100, 100, 255);
//Beach 0.08 - 0.2
else if(data[x][y]<=0.15) col = new Color(255, 255, 0);
//Forest 0.2 - 0.6 + 0 0 0.7
else if(data[x][y]<=0.6 && biome != null && (biome[x][y] < 0.6 || biome[x][y] > 0.9)){
//Forest
if(biome[x][y] < 0.6) col = new Color(0, 150, 0);
//Desert
else col = new Color(200, 200, 0);
}
//Plains 0.2 - 0.6
else if(data[x][y] <= 0.6) col = new Color(0, 255, 0);
//Rocky Mountains 0.6 - 0.8
else if(data[x][y] <= 0.65) col = new Color(100, 100, 100);
//Snowy Mountains 0.6 - 1
else col = new Color(255, 255, 255);

image.setRGB(x, y, col.getRGB());
}
}

try {
// retrieve image
File outputfile = new File(fileName);
outputfile.createNewFile();

ImageIO.write(image, "png", outputfile);
} catch (IOException e) {
System.out.println("GREY WRITE IMAGE ERROR 303: " + e);
}
}



//First called to store image tiles in blockImg[][] and tile rectangles in blocks[][]
private void loadTiles(){

//Primary Perlin Noise Generation
perlinNoise = GenerateWhiteNoise(listWidth, listHeight);
GreyWriteImage(perlinNoise, "perlinNoise.png");
perlinNoise = GenerateSmoothNoise(perlinNoise, 7);
GreyWriteImage(perlinNoise, "smoothNoise.png");
perlinNoise = GeneratePerlinNoise(perlinNoise, 5);
GreyWriteImage(perlinNoise, "finalPerlin.png");
gradiantNoise = GenerateCircularGradiant(gradiantNoise, listWidth, listWidth/2 - 1, listHeight/2 - 1);
GreyWriteImage(gradiantNoise, "gradiantNoise.png");
perlinIsland = GenerateIsland(gradiantNoise, perlinNoise);
GreyWriteImage(perlinIsland, "perlinIsland.png");


//Biome Perlin Noise Generation
biome = GenerateWhiteNoise(listWidth, listHeight);
biome = GenerateSmoothNoise(biome, 6);
biome = GeneratePerlinNoise(biome, 5);
GreyWriteImage(perlinIsland, biome, "biome.png");






for(int y = 0; y < listHeight; y++){
for(int x = 0; x < listWidth; x++){

//Sets boundaries: 0 < perlinIsland[x][y] < 1
if (perlinIsland[x][y]>1) perlinIsland[x][y]=1;
if (perlinIsland[x][y]<0) perlinIsland[x][y]=0;

//Deep Water 0 - 0.05
if(perlinIsland[x][y] <= 0.05)blockImg[x][y] = TILE[0];
//Shallow Water 0.05 - 0.08
else if(perlinIsland[x][y] <= 0.08) blockImg[x][y] = TILE[3];
//Beach 0.08 - 0.2
else if(perlinIsland[x][y]<=0.15) blockImg[x][y] = TILE[4];
//Forest 0.2 - 0.6 + 0 0 0.7
else if(perlinIsland[x][y]<=0.6 && biome != null && (biome[x][y] < 0.6 || biome[x][y] > 0.9)){
//Forest
if(biome[x][y] < 0.6) blockImg[x][y] = TILE[5];
//Desert
else blockImg[x][y] = TILE[3];
}
//Plains 0.2 - 0.6
else if(perlinIsland[x][y] <= 0.6) blockImg[x][y] = TILE[2];
//Rocky Mountains 0.6 - 0.8
else if(perlinIsland[x][y] <= 0.65) blockImg[x][y] = TILE[3];
//Snowy Mountains 0.6 - 1
else blockImg[x][y] = TILE[1];

blocks[x][y] = new Rectangle(x*32, y*32, 32, 32);

}
}

}


//collision detection
public boolean collide(Rectangle in)
{
if(blocks[0][0] != null){
for (int y = (int)((playerRect.y - blocks[0][0].y) / 32)-1; y <= (int)((playerRect.y+playerRect.height - blocks[0][0].y) / 32)+1; y++){
for (int x = (int)((playerRect.x - blocks[0][0].x) / 32)-1; x <= (int)((playerRect.x+playerRect.width - blocks[0][0].x) / 32) + 1; x++){
if (x >= 0 && y >= 0 && x < 32 && y < 32){
if (blockImg[x][y] != null)
{
if (in.intersects(blocks[x][y]) && isSolid[x][y] == true){
{
return true;
}
}
}
}
}
}
}
return false;
}


//Key Listener
public class AL extends KeyAdapter{
public void keyPressed(KeyEvent e){

int keyInput = e.getKeyCode();
still = false;
if(keyInput == e.VK_LEFT){

navigateMap(PAN_RIGHT);
MOVING_WEST = true;

}if(keyInput == e.VK_RIGHT){

navigateMap(PAN_LEFT);
MOVING_EAST = true;

}if(keyInput == e.VK_UP){

navigateMap(PAN_DOWN);
MOVING_NORTH = true;

}if(keyInput == e.VK_DOWN){

navigateMap(PAN_UP);
MOVING_SOUTH = true;
}
}
public void keyReleased(KeyEvent e){

int keyInput = e.getKeyCode();
setYDirection(0);
setXDirection(0);

if(keyInput == e.VK_LEFT){

MOVING_WEST = false;
player = ARCHER_WEST[0];

}if(keyInput == e.VK_RIGHT){

MOVING_EAST = false;
player = ARCHER_EAST[0];

}if(keyInput == e.VK_UP){

MOVING_NORTH = false;
player = ARCHER_NORTH[0];

}if(keyInput == e.VK_DOWN){

MOVING_SOUTH = false;
player = ARCHER_SOUTH[0];
}
if( MOVING_SOUTH == MOVING_NORTH == MOVING_EAST == MOVING_WEST == false){
still = true;
}
}
}


public void moveMap(){


for(int a = 0; a < 30; a++){
for(int b = 0; b < 30; b++){
if(blocks[a][b] != null){
blocks[a][b].x += xDirection;
blocks[a][b].y += yDirection;
}
}
}

if(collide(playerRect) && blocks[0][0]!= null){
for(int a = 0; a < 30; a++){
for(int b = 0; b < 30; b++){
blocks[a][b].x -= xDirection;
blocks[a][b].y -= yDirection;
}
}
}
}


public void navigateMap(byte pan){
switch(pan){
default:
System.out.println("Unrecognized pan!");
break;
case PAN_UP:
setYDirection(-1);
break;
case PAN_DOWN:
setYDirection(+1);
break;
case PAN_LEFT:
setXDirection(-1);
break;
case PAN_RIGHT:
setXDirection(+1);
break;
}
}


//Animation Update
public void update(long gameTime) {

if (gameTime > frameTicker + framePeriod) {
frameTicker = gameTime;
currentFrame++;
if (currentFrame >= 4) {
currentFrame = 0;
}
}
if(MOVING_NORTH) player = ARCHER_NORTH[currentFrame];
if(MOVING_SOUTH) player = ARCHER_SOUTH[currentFrame];
if(MOVING_EAST) player = ARCHER_EAST[currentFrame];
if(MOVING_WEST) player = ARCHER_WEST[currentFrame];
}


public void setXDirection(int xdir){

xDirection = xdir;
}


public void setYDirection(int ydir){

yDirection = ydir;
}


//Method to get sprites
public BufferedImage grabSprite(int x, int y, int width, int height){
BufferedImage sprite = spriteSheet.getSubimage(x, y, width, height);
return sprite;
}


private void init(){
spriteSheet = null;
try {
spriteSheet = loadImage("ARCHER_SPRITESHEET.png");
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
for(int i = 0; i <= 3; i++){
ARCHER_NORTH[i] = grabSprite(i*16, 16, 16,16);
ARCHER_SOUTH[i] = grabSprite(i*16, 0, 16, 16);
ARCHER_EAST[i] = grabSprite(i*16, 32, 16, 16);
ARCHER_WEST[i] = grabSprite(i*16, 48, 16, 16);
}
}


public BufferedImage loadImage(String pathRelativeToThis) throws IOException{

URL url = this.getClass().getResource(pathRelativeToThis);
BufferedImage img = ImageIO.read(url);
return img;
}


public void paint(Graphics g){

dbImage = createImage(getWidth(), getHeight());
dbGraphics = dbImage.getGraphics();
paintComponent(dbGraphics);
g.drawImage(dbImage, 0, 25, this);

}

public void paintComponent(Graphics g){
requestFocus();

/**

//Draws tiles and rectangular boundaries for debugging
for(int a = 200; a < 230; a++){
for(int b = 200; b < 230; b++){
if(blockImg[a][b] != null && blocks[a][b] != null){
g.drawImage(blockImg[a][b], Math.round(blocks[a][b].x), Math.round(blocks[a][b].y), 32, 32, null);
}
}
}

//Draw player and rectangular boundary for collision detection
g.drawImage(player, playerX, playerY, 40, 40, null);
repaint();

//Draws transparent tiles
for(int a = 0; a < 20; a++){
for(int b = 0; b < 15; b++){
if(blockImgTrans[a][b] != null && blocks[a][b] != null){
g.drawImage(blockImgTrans[a][b], blocks[a][b].x, blocks[a][b].y, 32, 32, null);
}
}
}


**/
}

public void run(){
try{
while(true){
moveMap();
if(!still) update(System.currentTimeMillis());
Thread.sleep(13);
}
}catch(Exception e){
System.out.println("RUNTIME ERROR: " + e);
}
}


public static void main(String[] args) {
Main main = new Main();

//Threads
Thread thread1 = new Thread(main);
thread1.start();
}
}

最佳答案

您有限的 catch block 代码阻碍了您找到 null 的能力。

例如,这些代码行:

  try {
while (true) {
moveMap();
if (!still)
update(System.currentTimeMillis());
Thread.sleep(13);
}
} catch (Exception e) {
System.out.println("RUNTIME ERROR: " + e);
}

只会打印

RUNTIME ERROR: java.lang.NullPointerException

当此代码遇到 NPE 时没有行号或堆栈跟踪。

首先,您不应陷入普通异常,而应陷入显式异常。接下来,您应该使用信息量更大的 catch block ,例如至少通过 e.printStackTrace() 打印出堆栈跟踪的 block 。

上面的 block 真的应该写成:

public void run() {
while (true) {
moveMap();
if (!still)
update(System.currentTimeMillis());
try {
Thread.sleep(13);
// only catch the explicit exception and in localized code if possible.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

这样做,您会看到 NPE 出现在这里:

if (in.intersects(blocks[x][y]) && isSolid[x][y] == true) {

然后您可以在该行前面填充代码以查看导致问题的变量:

例如,

              if (blockImg[x][y] != null) {
System.out.println("in is null: " + (in == null));
System.out.println("blocks[x][y] is null: "
+ (blocks[x][y] == null));
System.out.println("isSolid is null: "
+ (isSolid == null));
System.out.println("isSolid[x][y] is null: "
+ (isSolid[x][y] == null));

if (in.intersects(blocks[x][y]) && isSolid[x][y] == true) {
{
return true;
}
}
}

您会看到问题是 isSolid[x][y] 为空:

in is null: false
blocks[x][y] is null: false
isSolid is null: false
isSolid[x][y] is null: true
in is null: false
blocks[x][y] is null: false
isSolid is null: false
isSolid[x][y] is null: true
in is null: false
blocks[x][y] is null: false
isSolid is null: false
isSolid[x][y] is null: true
Exception in thread "Thread-3" java.lang.NullPointerException
at pkg.Main.collide(Main.java:465)
at pkg.Main.moveMap(Main.java:557)
at pkg.Main.run(Main.java:693)
at java.lang.Thread.run(Unknown Source)
in is null: false
blocks[x][y] is null: false
isSolid is null: false
isSolid[x][y] is null: true
in is null: false
blocks[x][y] is null: false
isSolid is null: false
isSolid[x][y] is null: true
in is null: false
blocks[x][y] is null: false
isSolid is null: false
isSolid[x][y] is null: true

那是为什么?它是一个 boolean 值数组,而不是 boolean 值,因此它没有初始化为 Boolean.FALSE,而是默认为 null。解决方案:使用 boolean[][] 数组或显式初始化数组。

最重要的是:使用提供信息的 catch block ,不要捕获一般异常。


编辑 请注意,顺便说一句,为了让您的代码运行,我不得不禁用您对图像和 Sprite 表的使用,因为这些是我无法使用的资源。不过,这项努力应该是你的,因为你是 future 寻求的人。我要求以后,你将你的代码限制在我们可以测试和运行的最小代码,能够演示你的问题,但没有与你的问题无关的代码,并且不依赖外部资源,如图像、数据库等...,sscce .

关于java.lang.NullPointerException 找不到源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17898220/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com