Neural net learning algorithm - java

I have been working on making a neural network that has a goal, of hitting a moving target, it has inputs based on the distance from the shooter to the target from both axis, the rotation of the shooter, and the wind speed.
Every 5 seconds the shooter resets to a different position on the screen.
I have attempted to use a back prop algorithm, by giving calculating the error based on the distance the bullet hits from the target, and if the shooter doesn't fire a shot in the 5 second window there is also an error propagated.
My network however does not seem to be learning properly, I was wondering if anyone could point me in the right direction.
Here is my code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Random;
import java.util.stream.DoubleStream;
import javax.swing.JFrame;
public class ClassMain extends JFrame{
int ShooterLocationX = 100;
int ShooterLocationY = 150;
int shooterDiameter = 35;
int targetX = 525;
int targetY = 100;
int targetWidth = 15;
int targetLength = 50;
double error;
double targetVectorX=ShooterLocationX + 100;
double targetVectorY = ShooterLocationY+shooterDiameter/2;
boolean direction = false;
boolean ShotFired = false;
boolean rotateDirection;
boolean start =true;
boolean shotbeenFires;
double ShooterRotation = 0;
double[] outputs1 = new double[4];
double[] outputs2 = new double[8];
double[] outputs3 = new double[8];
double[] outputs4 = new double[3];
Percepton[] input = new Percepton[4];
Percepton[] hidden = new Percepton[8];
Percepton[] hidden2 = new Percepton[8];
Percepton[] output = new Percepton[3];
Shooter shot = new Shooter(ShooterRotation);
Random random = new Random();
long StartTime = 0;
long CurrTime = 0;
public static void main(String []args){
ClassMain CM= new ClassMain();
CM.setup();
}
public void setup(){
setSize(900,300);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
createBufferStrategy(2);
repaint();
for(int i = 0; i < 4; i ++){
input[i] = new Percepton();
input[i].setInputNumber(1);
}
for(int i =0;i < 8;i++){
hidden[i] = new Percepton();
hidden[i].setInputNumber(input.length);
}
for(int i =0;i < 8;i++){
hidden2[i] = new Percepton();
hidden2[i].setInputNumber(input.length);
}
for(int i = 0;i < 3; i++){
output[i] = new Percepton();
output[i].setInputNumber(hidden.length);
}
}
public void run(){
double[] temp = new double[10];
if(start){
StartTime = System.currentTimeMillis();
start = false;
}
CurrTime = System.currentTimeMillis();
if(CurrTime-StartTime > 5000){
ShooterLocationX=random.nextInt(400);
ShooterLocationY=random.nextInt(275);
shot.newX = ShooterLocationX+(shooterDiameter/2)-5;
shot.newY = ShooterLocationY+(shooterDiameter/2)-5;
shot.windSpeed = (float)(random.nextInt(200)-100)/100;
start = true;
if(!shotbeenFires){
error+=15;
}
for(int n = 0; n < output.length;n++){
output[n].learn(n, error, output[n].weights[n]);
}
for(int n = 0; n < hidden2.length;n++){
hidden2[n].learn(n, error, hidden2[n].weights[n]);
}
for(int n = 0; n < hidden.length;n++){
hidden[n].learn(n, error, hidden[n].weights[n]);
}
for(int n = 0; n < input.length;n++){
input[n].learn(n, error, input[n].weights[n]);
}
error = 0;
shotbeenFires = false;
}
outputs1[0] = input[0].sigmoid((((Math.max(ShooterLocationX,targetX)-Math.min(ShooterLocationX,targetX))/300)*2)*input[0].weights[0],1*input[0].biasWeight);
outputs1[1] = input[1].sigmoid((((Math.max(ShooterLocationY,targetY)-Math.min(ShooterLocationY,targetY))/150)*2)*input[1].weights[0],1*input[1].biasWeight);
outputs1[2] = input[2].sigmoid((ShooterRotation)*input[2].weights[0],1*input[2].biasWeight);
outputs1[3] = input[3].sigmoid((shot.windSpeed)*input[3].weights[0],1*input[3].biasWeight);
System.out.println("\n");
for(int n = 0;n < hidden.length;n++){
for(int i = 0;i<temp.length;i++){
temp[i] = 0;
}
for(int i = 0;i < outputs1.length;i++){
temp[i] = outputs1[i]*hidden[n].weights[i];
}
outputs2[n] = (float)DoubleStream.of(temp).sum();
outputs2[n] = hidden[1].sigmoid(outputs2[n],1*hidden[n].biasWeight);
//System.out.print(outputs2[n]);
}
System.out.println("\n");
for(int n = 0;n < hidden2.length;n++){
for(int i = 0;i<temp.length;i++){
temp[i] = 0;
}
for(int i = 0;i < outputs2.length;i++){
temp[i] = outputs2[i]*hidden2[n].weights[i];
}
outputs3[n] = (float)DoubleStream.of(temp).sum();
outputs3[n] = hidden2[1].sigmoid(outputs3[n],1*hidden2[n].biasWeight);
//System.out.print(outputs3[n]);
}
System.out.println("\n");
for(int n = 0;n < output.length;n++){
for(int i = 0;i<temp.length;i++){
temp[i] = 0;
}
for(int i = 0;i < outputs1.length;i++){
temp[i] = outputs3[n]*hidden[n].weights[i];
}
outputs4[n] = (float)DoubleStream.of(temp).sum();
outputs4[n] = output[n].sigmoid(outputs4[n],1*output[n].biasWeight);
//System.out.print(outputs4[n]);
}
if(!ShotFired){
System.out.println("\n");
if(outputs4[0] > 0.5){
ShotFired = true;
shot.rotation = ShooterRotation;
}
if (outputs4[1] > 0.5){
ShooterRotation = ShooterRotation + outputs3[1];
}
if(outputs4[2] > 0.5){
ShooterRotation =ShooterRotation - outputs3[2];
}
if(ShooterRotation*360 > 360){
ShooterRotation = ((ShooterRotation * 360) + 360) /360;
}else if(ShooterRotation * 360 < 0){
ShooterRotation = ((ShooterRotation*360)-360) /360;
}
}
for(int i = 0; i < 1; i++){
if(ShotFired){
shotbeenFires = true;
shot.newLocationX(shot.newX);
shot.newLocationY(shot.newY);
}
if(targetY < 20 ||targetY+targetLength >300){
direction = !direction;
}
if(direction){
targetY += 8;
}else{
targetY -= 8;
}
if(shot.newX + (15)>= targetX && shot.newX + 15 < targetX +targetWidth && shot.newY + 15> targetY && shot.newY <targetY + targetLength){
System.out.println("Target Hit");
error -= 10;
shot.newX = ShooterLocationX + shooterDiameter/2-5;
shot.newY = ShooterLocationY + shooterDiameter/2-5;
ShotFired = false;
}else if(shot.newX > 600|| shot.newX<10||shot.newY<10||shot.newY> 290){
System.out.println("MISS");
error += (shot.newY - targetY);
shot.newX = ShooterLocationX + shooterDiameter/2-5;
shot.newY = ShooterLocationY + shooterDiameter/2-5;
ShotFired = false;
}
}
repaint();
}
public void paint(Graphics g){
targetVectorX = ShooterLocationX + shooterDiameter/2 + Math.cos(Math.toRadians(ShooterRotation)) * 100;
targetVectorY = ShooterLocationY + shooterDiameter/2 + Math.sin(Math.toRadians(ShooterRotation)) * 100;
super.paint(g);
Graphics2D g2 = (Graphics2D)g;
g2.fillOval(ShooterLocationX, ShooterLocationY, shooterDiameter, shooterDiameter);
g2.setPaint(Color.RED);
g2.drawLine(ShooterLocationX + shooterDiameter/2, ShooterLocationY+shooterDiameter/2, (int)targetVectorX, (int)targetVectorY);
g2.setPaint(Color.BLUE);
g2.fillRect(targetX, targetY, targetWidth, targetLength);
g2.setPaint(Color.RED);
g2.fillOval((int)shot.newX, (int)shot.newY, 10, 10);
g2.setPaint(Color.gray);
g2.fillRect(600, 0, 300,300);
for(int i = 0; i < input.length;i++){
if(outputs1[i] > 0.5){
g2.setPaint(Color.red);
}else{
g2.setPaint(Color.white);
}
g2.drawOval(625+i*35, 250, 25, 25);
for(int j = 0;j<hidden.length;j++){
g2.drawLine(640+i*35, 250, 615+j*30, 195);
}
}
for(int i = 0; i < hidden.length;i++){
if(outputs2[i] > 0.5){
g2.setPaint(Color.red);
}else{
g2.setPaint(Color.white);
}
g2.drawOval(605+i*30, 175, 20, 20);
for(int j = 0;j<hidden2.length;j++){
g2.drawLine(615+i*30, 175, 615+j*30, 145);
}
}
for(int i = 0; i < hidden2.length;i++){
if(outputs3[i] > 0.5){
g2.setPaint(Color.red);
}else{
g2.setPaint(Color.white);
}
g2.drawOval(605+i*30, 125, 20, 20);
for(int j = 0;j<output.length;j++){
g2.drawLine(615+i*30, 125, 697+j*50, 75);
}
}
for(int i = 0; i < output.length;i++){
if(outputs4[i] > 0.5){
g2.setPaint(Color.red);
}else{
g2.setPaint(Color.white);
}
g2.drawOval(685+i*50, 50, 25, 25);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
run();
}
}
public class Shooter {
double windSpeed = 0.5;
int distance = 0;
double newX;
double newY;
double rotation;
double temp = 0;
public Shooter(double rotate){
rotation = rotate*360;
windSpeed = windSpeed*5;
}
public void newLocationX(double XPrev){
newX = XPrev + Math.cos(Math.toRadians(rotation)) * 20;
}
public void newLocationY(double YPrev){
newY = YPrev + Math.sin(Math.toRadians(rotation)) * 20;
newY =newY - windSpeed;
}
}
import java.util.Random;
public class Percepton {
int numOfInputs = 100;
float[] weights = new float[numOfInputs];
int sum;
double learningRate = 0.1;
float biasWeight;
float a;
float out;
Random random = new Random();
public void setWeight(int index,float weight){
weights[index] = weight;
}
public void setInputNumber(int inputs){
numOfInputs = inputs;
for(int i = 0; i < inputs; i++){
weights[i] = (float)(random.nextInt(400)-200)/200;
biasWeight = (float)(random.nextInt(400)-200)/200;
//System.out.println(weights[i]);
}
}
public void learn(int index, double error, float value){
weights[index] += (float)learningRate * (float)error * value;
}
public double sigmoid(double input,double bias){
return (float) (1/(1+Math.exp(-input*bias)));
}
}

Related

LibGDX applyLinearImpulse trying to implement Gravity....Confused

Street Fighter 2d clone I'm trying to get the player Ken to come back down after jumping. He just goes higher and higher but I want it to be like gravity so he's pulled back down. Then I will set a ground level where he cant pass through.
I've researched the applyLinearImpulse method to be called on the body which is initialised beforre asa I kept getting null pointer exception it seems that now it don't crash but Ken just gets drawn further up the Y Axis. Its left me very confused.
Any advice links greatly appreciated.
Ken class
public class Ken extends Player {
private static final int FRAME_COLS = 6, FRAME_ROWS = 1;
private static final int COLUMNS_KICK = 6;
private static final int COLUMNS_LEFT = 8;
private static final int COLUMNS_RIGHT = 8;
private static final int COLUMNS_JUMP = 10;
private static final int COLUMNS_PUNCH = 6;
private static final int COLUMNS_FRONTFLIP = 8;
private static final int COLUMNS_BACKFLIP = 8;
public static final int FRAME_FRONTFLIP = 1;
public static final int FRAME_BACKLIP = 1;
float x, y;
Animation<TextureRegion> walkAnimation;
Animation<TextureRegion> kickAnimation;
Animation<TextureRegion> punchAnimation;
Animation<TextureRegion> leftAnimation;
Animation<TextureRegion> rightAnimation;
Animation<TextureRegion> jumpAnimation;
Animation<TextureRegion> frontFlipAnimation;
Animation<TextureRegion> backFlipAnimation;
Texture walkSheet;
Texture kickSheet;
Texture punchSheet;
Texture leftSheet;
Texture rightSheet;
Texture jumpSheet;
Texture frontFlipSheet;
Texture backFlipSheet;
public Body body;
public World world;
boolean alive = true;
private final static int STARTING_X = 50;
private final static int STARTING_Y = 30;
TextureRegion reg;
float stateTime;
public Ken(GameScreen screen){
this.world = screen.getWorld();
defineKen();
createIdleAnimation();
kickAnimation();
punchAnimation();
lefttAnimation();
righttAnimation();
jumpAnimation();
frontFlipAnimation();
backFlipAnimation();
this.setPosition(STARTING_X, STARTING_Y);
}
public void createIdleAnimation() {
walkSheet = new Texture(Gdx.files.internal("ken/idle.png"));
TextureRegion[][] tmp = TextureRegion.split(walkSheet,
walkSheet.getWidth() / FRAME_COLS,
walkSheet.getHeight() / FRAME_ROWS);
TextureRegion[] walkFrames = new TextureRegion[FRAME_COLS * FRAME_ROWS];
int index = 0;
for (int i = 0; i < FRAME_ROWS; i++) {
for (int j = 0; j < FRAME_COLS; j++) {
walkFrames[index++] = tmp[i][j];
}
}
walkAnimation = new Animation<TextureRegion>(0.1f, walkFrames);
stateTime = 0f;
reg=walkAnimation.getKeyFrame(0);
}
public void kickAnimation(){
kickSheet = new Texture(Gdx.files.internal("ken/kick_low.png"));
TextureRegion [][] tmp = TextureRegion.split(kickSheet, kickSheet.getWidth() / COLUMNS_KICK,
kickSheet.getHeight() / FRAME_ROWS);
TextureRegion[] kickFrames = new TextureRegion[COLUMNS_KICK * FRAME_ROWS];
int index = 0;
for (int i = 0; i < FRAME_ROWS; i++) {
for (int j = 0; j < FRAME_COLS; j++) {
kickFrames[index++] = tmp[i][j];
}
}
kickAnimation = new Animation<TextureRegion>(8f, kickFrames);
stateTime = 6f;
reg = kickAnimation.getKeyFrame(1);
}
public void lefttAnimation(){
leftSheet = new Texture(Gdx.files.internal("ken/parry_b.png"));
TextureRegion [][] tmp = TextureRegion.split(leftSheet, leftSheet.getWidth() / COLUMNS_LEFT,
leftSheet.getHeight() / FRAME_ROWS);
TextureRegion[] leftFrames = new TextureRegion[COLUMNS_LEFT * FRAME_ROWS];
int index = 0;
for (int i = 0; i < FRAME_ROWS; i++) {
for (int j = 0; j < COLUMNS_LEFT; j++) {
leftFrames[index++] = tmp[i][j];
}
}
leftAnimation = new Animation<TextureRegion>(0.1f, leftFrames);
stateTime = 0f;
reg = punchAnimation.getKeyFrame(0);
}
public void righttAnimation(){
rightSheet = new Texture(Gdx.files.internal("ken/parry_f.png"));
TextureRegion [][] tmp = TextureRegion.split(rightSheet, rightSheet.getWidth() / COLUMNS_RIGHT,
rightSheet.getHeight() / FRAME_ROWS);
TextureRegion[] rightFrames = new TextureRegion[COLUMNS_RIGHT * FRAME_ROWS];
int index = 0;
for (int i = 0; i < FRAME_ROWS; i++) {
for (int j = 0; j < COLUMNS_RIGHT; j++) {
rightFrames[index++] = tmp[i][j];
}
}
rightAnimation = new Animation<TextureRegion>(0.1f, rightFrames);
stateTime = 0f;
reg = rightAnimation.getKeyFrame(0);
}
public void punchAnimation(){
punchSheet = new Texture(Gdx.files.internal("ken/punch.png"));
TextureRegion [][] tmp = TextureRegion.split(punchSheet, punchSheet.getWidth() / COLUMNS_PUNCH,
punchSheet.getHeight() / FRAME_ROWS);
TextureRegion[] punchFrames = new TextureRegion[COLUMNS_PUNCH * FRAME_ROWS];
int index = 0;
for (int i = 0; i < FRAME_ROWS; i++) {
for (int j = 0; j < COLUMNS_PUNCH; j++) {
punchFrames[index++] = tmp[i][j];
}
}
punchAnimation = new Animation<TextureRegion>(0.1f, punchFrames);
stateTime = 0f;
reg = punchAnimation.getKeyFrame(0);
}
public void jumpAnimation(){
jumpSheet = new Texture(Gdx.files.internal("ken/jump.png"));
TextureRegion [][] tmp = TextureRegion.split(jumpSheet, jumpSheet.getWidth() / COLUMNS_JUMP,
jumpSheet.getHeight() / FRAME_ROWS);
TextureRegion[] jumpFrames = new TextureRegion[COLUMNS_JUMP * FRAME_ROWS];
int index = 0;
for (int i = 0; i < FRAME_ROWS; i++) {
for (int j = 0; j < COLUMNS_JUMP; j++) {
jumpFrames[index++] = tmp[i][j];
}
}
jumpAnimation = new Animation<TextureRegion>(0.1f, jumpFrames);
stateTime = 0f;
reg = jumpAnimation.getKeyFrame(0);
}
public void frontFlipAnimation(){
frontFlipSheet = new Texture(Gdx.files.internal("ken/front_flip.png"));
TextureRegion [][] tmp = TextureRegion.split(frontFlipSheet, frontFlipSheet.getWidth() / COLUMNS_FRONTFLIP,
frontFlipSheet.getHeight() / FRAME_ROWS);
TextureRegion[] frontFlipFrames = new TextureRegion[COLUMNS_FRONTFLIP * FRAME_FRONTFLIP];
int index = 0;
for (int i = 0; i < FRAME_FRONTFLIP; i++) {
for (int j = 0; j < COLUMNS_FRONTFLIP; j++) {
frontFlipFrames[index++] = tmp[i][j];
}
}
frontFlipAnimation = new Animation<TextureRegion>(0.1f, frontFlipFrames);
stateTime = 0f;
reg = frontFlipAnimation.getKeyFrame(0);
}
public void backFlipAnimation(){
backFlipSheet = new Texture(Gdx.files.internal("ken/back_flip.png"));
TextureRegion [][] tmp = TextureRegion.split(backFlipSheet, backFlipSheet.getWidth() / COLUMNS_BACKFLIP,
backFlipSheet.getHeight() / FRAME_BACKLIP);
TextureRegion[] backFlipFrames = new TextureRegion[COLUMNS_BACKFLIP * FRAME_BACKLIP];
int index = 0;
for (int i = 0; i < FRAME_BACKLIP; i++) {
for (int j = 0; j < COLUMNS_BACKFLIP; j++) {
backFlipFrames[index++] = tmp[i][j];
}
}
backFlipAnimation = new Animation<TextureRegion>(0.1f, backFlipFrames);
stateTime = 0f;
reg = backFlipAnimation.getKeyFrame(0);
}
#Override
public void act(float delta) {
super.act(delta);
stateTime += delta;
stateTime += delta;
reg = walkAnimation.getKeyFrame(stateTime,true);
if(Gdx.input.isKeyPressed(Input.Keys.A)){
reg = kickAnimation.getKeyFrame(stateTime, false);
this.addAction(Actions.moveTo(getX() +2, getY(), 1 / 10F));
}
if(Gdx.input.isKeyPressed(Input.Keys.S)){
reg = punchAnimation.getKeyFrame(stateTime, false);
}
if(Gdx.input.isKeyPressed(Input.Keys.LEFT)){
reg = leftAnimation.getKeyFrame(stateTime, true);
this.addAction(Actions.moveTo(getX() - 10, getY(), 1 / 10f ));
}
if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)){
reg = rightAnimation.getKeyFrame(stateTime, true);
this.addAction(Actions.moveTo(getX() + 10, getY(), 1 /10f));
}
if(Gdx.input.isKeyPressed(Input.Keys.UP)){
body.applyLinearImpulse(new Vector2(0, 20), body.getWorldCenter(), true);
reg = jumpAnimation.getKeyFrame(stateTime, false);
this.addAction(Actions.moveTo(getX(), getY() + 10, 1/ 10f));
}
if(Gdx.input.isKeyPressed(Input.Keys.D)){
reg = frontFlipAnimation.getKeyFrame(stateTime, true);
this.addAction(Actions.moveTo(getX() + 5, getY(), 1 / 10f));
}
if(Gdx.input.isKeyPressed(Input.Keys.W)){
reg = backFlipAnimation.getKeyFrame(stateTime, true);
this.addAction(Actions.moveTo(getX() - 5, getY(), 1 / 10F));
}
}
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
Color color = getColor();
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
batch.draw(reg,getX(),getY(),getWidth()/2,getHeight()/2,getWidth(),getHeight(),getScaleX(),getScaleY(),getRotation());
}
private void defineKen(){
BodyDef bdef = new BodyDef();
bdef.position.set(32 / 100, 32 / 100);
bdef.type = BodyDef.BodyType.DynamicBody;
body = world.createBody(bdef);
FixtureDef fdef = new FixtureDef();
CircleShape shape = new CircleShape();
shape.setRadius(7 / 100);
fdef.shape = shape;
body.createFixture(fdef).setUserData(this);
body.createFixture(fdef).setUserData(this);
}
}
Repo
Thanks alot
You work with Box2d and Box2d is a 2d physics engine so it also integrated gravity.
First, when you create your World you can define the gravity force:
world = new World(new Vector2(0,-15f), true);
This will pull your Player down.
Then you must update the world every frame. So call in the render() method:
world.step(delta, 6, 2);
Now the Body position will be calculated by the world and gravity apply to the body.
Important now is that you first have a Static body as Ground otherwise, the body will fall down infinitely. Secondly, you must change the place where you draw the Image of Ken to the place of the Body so in act() method update the position:
setX(body.getPosition().x);
setY(body.getPosition().y);
Maybe you look for some Box2d tutorials to have a better understanding:
https://www.gamedevelopment.blog/full-libgdx-game-tutorial-box2d/

Grid line collision checking

Lately I've been working on a grid line detection system, I know that there was an algorithm out there that did excactly what I wanted it to do, but I'm that kind of person who wants to make stuff themselves. ;)
So I've had some succes when checking with 1 line, but now that I use a grid of 20x20 to check the lines it doesn't work anymore.
The problem is found somewhere in the collision class I made for this system.
Somehow the numbers get out of the grid array and I don't know why
here is the code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/**
*
* beschrijving
*
* #version 1.0 van 22-6-2016
* #author
*/
public class gridline extends JApplet {
// Begin variabelen
int[][] grid = new int[20][20];
int[] light = new int[2];
int[][] line = new int[2][2];
// Einde variabelen
public void init() {
Container cp = getContentPane();
cp.setLayout(null);
cp.setBounds(0, 0, 600, 600);
// Begin componenten
for (int a=0; a<20; a++) {
for (int b=0; b<20; b++) {
grid[a][b] = (int) (Math.random()*10);
} // end of for
} // end of for
line[0][0] = (int) (Math.random()*20);
line[0][1] = (int) (Math.random()*20);
line[1][0] = (int) (Math.random()*20);
line[1][1] = (int) (Math.random()*20);
light[0] = (int) (Math.random()*20);
light[1] = (int) (Math.random()*20);
// Einde componenten
} // end of init
//Custom classes
private boolean collide(int x1, int y1,int x2, int y2) {
boolean collide = true;
int tempx = x1 - x2;
int tempy = y1 - y2;
int sx = 0;
int sy = 0;
int x = 0;
int y = 0;
if (tempx == 0) {
tempx = 1;
sx = 1;
} // end of if
if (tempy == 0) {
tempy = 1;
sy = 1;
} // end of if
if (sx == 0) {
x = tempx + tempx/Math.abs(tempx);
} // end of if
else {
x = tempx;
} // end of if-else
if (sy == 0) {
y = tempy + tempy/Math.abs(tempy);
} // end of if
else {
y = tempy;
} // end of if-else
int absx = Math.abs(x);
int absy = Math.abs(y);
int nex = x/absx;
int ney = y/absy;
int off = 0;
float count = 0;
float step = 0;
if (absx != absy) {
if (absx == Math.min(absx,absy)) {
step = (float) absx/absy;
calc1: for (int a=0; a<absy; a++) {
count += step;
if (count > 1 && x1+off != x2) {
count -= 1;
off += nex;
} // end of if
if (grid[x1+off][y1+a*ney] == 9) {
collide = false;
break calc1;
} // end of if
} // end of for
} // end of if
else{
step = (float) absy/absx;
calc2: for (int a=0; a<absx; a++) {
count += step;
if (count > 1 && y1+off != y2) {
count -= 1;
off += ney;
} // end of if
if (grid[x1+a*nex][y1+off] == 9) {
collide = false;
break calc2;
} // end of if
} // end of for
}
} // end of if
else {
calc3: for (int a=0; a<absx; a++) {
if (grid[x1+a*nex][y1+a*ney] == 9) {
collide = false;
break calc3;
} // end of if
} // end of for
} // end of if-else
return collide;
}
private int length(int x1, int y1, int x2, int y2) {
double distance = Math.sqrt(Math.pow(x1-x2,2)+Math.pow(y1-y2,2));
return (int) distance;
}
// Begin eventmethoden
public void paint (Graphics g){
boolean draw = true;
Color col;
for (int a=0; a<20; a++) {
for (int b=0; b<20; b++) {
draw = collide(a,b,light[0],light[1]);
if (draw) {
int len = Math.max(255-length(a*30+15,b*30+15,light[0]*30+15,light[1]*30+15),0);
col = new Color(len,len,len);
g.setColor(col);
g.fillRect(a*30,b*30,30,30);
} // end of if
else{
col = new Color(0,0,0);
g.setColor(col);
g.fillRect(a*30,b*30,30,30);
}
} // end of for
} // end of for
}
// Einde eventmethoden
} // end of class gridline
I'll understand it if nobody wants to look through a code as big as this, but it could be helpful for your own projects and I'm completely okay with it if you copy and paste my code for your projects.
Many thanks in advace.

Painting balloons on Graphics2D

I want to make bubble shooter game and I have problem with generate bubbles at start. When trying to compile program, I have error: Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException.
public class MyPanel extends JPanel {
Init init;
public MyPanel(){
super();
init = new Init();
}
public void paint(Graphics g){
Dimension size = getSize();
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.GRAY);
g2d.fillRect(0, 0, size.width, size.height - 70);
for(int j = 0; j < 10; j++)
for(int i = 0; i < 20; i++){
init.fields[i][j].b.paint(g); //here compiler shows error
}
}
}
public class Field {
private int x;
private int y;
private int r = 30;
public Baloon b;
public Field(int x, int y){
this.x = x*r;
this.y = y*r;
}
public void addBaloon(int n){
b = new Baloon(this.x, this.y, r, n);
}
}
public class Init {
Parser pr = new Parser();
private int r = pr.getRadius();
private int x = pr.getXDimension();
private int y = pr.getYDimension();
private int ni = pr.getColorRange();
Field[][] fields = new Field[x][y];
private int startX = 20;
private int startY = 10;
public Init(){
for(int yi = 1; yi<y; yi++){
for (int xi = 1; xi<x; xi++){
fields[xi][yi] = new Field(xi*r, yi*r);
}
}
for(int yi = 1; yi < startY; yi ++){
for(int xi = 1 ; xi < startX; xi++){
Random rand = new Random();
int n = rand.nextInt(ni);
fields[xi][yi].addBaloon(n);
}
}
}
}
You are initializing array from index 1:
for(int yi = 1; yi<y; yi++){
for (int xi = 1; xi<x; xi++){
fields[xi][yi] = new Field(xi*r, yi*r);
}
}
While accessing it from 0 like:
for(int j = 0; j < 10; j++)
for(int i = 0; i < 20; i++){
init.fields[i][j].b.paint(g); //here compiler shows error
}
Array index starts from 0 and goes upto n-1. So you need to initialize like:
for(int yi = 0; yi<y; yi++){
for (int xi = 0; xi<x; xi++){
fields[xi][yi] = new Field(xi*r, yi*r);
}
}

java.lang.NullPointerException Can't Find Source

I'm in the process of programming a java rpg game, and have reached an impass. My code currently has sprite animation, a random map generation with perlin noise and collision detection. The map is tiled base, so i'm currently trying to convert the perlin noise to tiles. The perlin functions generate a array, and im each number of that array to a tile png. This is where the problem comes: RUNTIME ERROR: Java.Lang.NullPointerException.
The probleme is my compiler (netbeans) does not show me where the error occurs, but instead only gives me this error code. With a process of exclusion I managed to locate the error, which occurs at line 364. If this site doesnt support lines, it is at the loadTile() method, at "if(perlinIsland[x][y] <= 0.05)blockImg[x][y] = TILE[0];". I believe all the variables are correctly initialized, but I can't manage to find a solution. Please excuse the long code, but I included everything for the sake of information. Thanks you in advance for you help!
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();
}
}
Your limited catch block code hampers your ability to find your nulls.
For instance, these lines of code:
try {
while (true) {
moveMap();
if (!still)
update(System.currentTimeMillis());
Thread.sleep(13);
}
} catch (Exception e) {
System.out.println("RUNTIME ERROR: " + e);
}
Will only print
RUNTIME ERROR: java.lang.NullPointerException
without line numbers or stack trace when this code runs into an NPE.
First off, you should not be trapping for plain Exception but rather for explicit Exceptions. Next you should use a more informative catch block, for instance one that at least prints out the stack trace via e.printStackTrace().
The block above should really be written:
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();
}
}
}
Do this, and you'll see that the NPE occurs here:
if (in.intersects(blocks[x][y]) && isSolid[x][y] == true) {
Then you can stuff code in front of that line to see which variable is causing the problem:
e.g.,
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;
}
}
}
And you'll see the problem is that isSolid[x][y] is null:
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
And why is that? It's an array of Booleans, not booleans, so it is not initialized to Boolean.FALSE but rather it defaults to null. Solution: either use boolean[][] array or initialize your array explicitly.
Most important: use informative catch blocks and don't catch for general Exceptions.
Edit note that as an aside, in order for me to get your code to run, I had to disable your use of images and sprite sheets, since these are resources that are unavailable to me. This effort should be yours though since you are the one seeking in the future. I ask that in the future, you limit your code to the smallest code that we can test and run, that demonstrates your problem, but that has no code unrelated to your problem, and that does not rely on outside resources such as images, databases, etc..., an sscce.

Can anyone help me understand how to simulate fluids?

I'm trying to make a program that simulates the physics of fluids in Processing. In the IDE there's an included example:
/**
* Fluid
* by Glen Murphy.
*
* Click and drag the mouse to move the simulated fluid.
* Adjust the "res" variable below to change resolution.
* Code has not been optimised, and will run fairly slowly.
*/
int res = 2;
int penSize = 30;
int lwidth;
int lheight;
int pnum = 30000;
vsquare[][] v;
vbuffer[][] vbuf;
particle[] p = new particle[pnum];
int pcount = 0;
int mouseXvel = 0;
int mouseYvel = 0;
void setup()
{
size(200, 200);
noStroke();
frameRate(30);
lwidth = width/res;
lheight = height/res;
v = new vsquare[lwidth+1][lheight+1];
vbuf = new vbuffer[lwidth+1][lheight+1];
for (int i = 0; i < pnum; i++) {
p[i] = new particle(random(res,width-res),random(res,height-res));
}
for (int i = 0; i <= lwidth; i++) {
for (int u = 0; u <= lheight; u++) {
v[i][u] = new vsquare(i*res,u*res);
vbuf[i][u] = new vbuffer(i*res,u*res);
}
}
}
void draw()
{
background(#666666);
int axvel = mouseX-pmouseX;
int ayvel = mouseY-pmouseY;
mouseXvel = (axvel != mouseXvel) ? axvel : 0;
mouseYvel = (ayvel != mouseYvel) ? ayvel : 0;
for (int i = 0; i < lwidth; i++) {
for (int u = 0; u < lheight; u++) {
vbuf[i][u].updatebuf(i,u);
v[i][u].col = 32;
}
}
for (int i = 0; i < pnum-1; i++) {
p[i].updatepos();
}
for (int i = 0; i < lwidth; i++) {
for (int u = 0; u < lheight; u++) {
v[i][u].addbuffer(i, u);
v[i][u].updatevels(mouseXvel, mouseYvel);
v[i][u].display(i, u);
}
}
}
class particle {
float x;
float y;
float xvel;
float yvel;
int pos;
particle(float xIn, float yIn) {
x = xIn;
y = yIn;
}
void updatepos() {
float col1;
if (x > 0 && x < width && y > 0 && y < height) {
int vi = (int)(x/res);
int vu = (int)(y/res);
vsquare o = v[vi][vu];
float ax = (x%res)/res;
float ay = (y%res)/res;
xvel += (1-ax)*v[vi][vu].xvel*0.05;
yvel += (1-ay)*v[vi][vu].yvel*0.05;
xvel += ax*v[vi+1][vu].xvel*0.05;
yvel += ax*v[vi+1][vu].yvel*0.05;
xvel += ay*v[vi][vu+1].xvel*0.05;
yvel += ay*v[vi][vu+1].yvel*0.05;
o.col += 4;
x += xvel;
y += yvel;
}
else {
x = random(0,width);
y = random(0,height);
xvel = 0;
yvel = 0;
}
xvel *= 0.5;
yvel *= 0.5;
}
}
class vbuffer {
int x;
int y;
float xvel;
float yvel;
float pressurex = 0;
float pressurey = 0;
float pressure = 0;
vbuffer(int xIn,int yIn) {
x = xIn;
y = yIn;
pressurex = 0;
pressurey = 0;
}
void updatebuf(int i, int u) {
if (i>0 && i<lwidth && u>0 && u<lheight) {
pressurex = (v[i-1][u-1].xvel*0.5 + v[i-1][u].xvel + v[i-1][u+1].xvel*0.5 - v[i+1][u-1].xvel*0.5 - v[i+1][u].xvel - v[i+1][u+1].xvel*0.5);
pressurey = (v[i-1][u-1].yvel*0.5 + v[i][u-1].yvel + v[i+1][u-1].yvel*0.5 - v[i-1][u+1].yvel*0.5 - v[i][u+1].yvel - v[i+1][u+1].yvel*0.5);
pressure = (pressurex + pressurey)*0.25;
}
}
}
class vsquare {
int x;
int y;
float xvel;
float yvel;
float col;
vsquare(int xIn,int yIn) {
x = xIn;
y = yIn;
}
void addbuffer(int i, int u) {
if (i>0 && i<lwidth && u>0 && u<lheight) {
xvel += (vbuf[i-1][u-1].pressure*0.5
+vbuf[i-1][u].pressure
+vbuf[i-1][u+1].pressure*0.5
-vbuf[i+1][u-1].pressure*0.5
-vbuf[i+1][u].pressure
-vbuf[i+1][u+1].pressure*0.5
)*0.25;
yvel += (vbuf[i-1][u-1].pressure*0.5
+vbuf[i][u-1].pressure
+vbuf[i+1][u-1].pressure*0.5
-vbuf[i-1][u+1].pressure*0.5
-vbuf[i][u+1].pressure
-vbuf[i+1][u+1].pressure*0.5
)*0.25;
}
}
void updatevels(int mvelX, int mvelY) {
if (mousePressed) {
float adj = x - mouseX;
float opp = y - mouseY;
float dist = sqrt(opp*opp + adj*adj);
if (dist < penSize) {
if (dist < 4) dist = penSize;
float mod = penSize/dist;
xvel += mvelX*mod;
yvel += mvelY*mod;
}
}
xvel *= 0.99;
yvel *= 0.99;
}
void display(int i, int u) {
float tcol = 0;
if (col > 255) col = 255;
if (i>0 && i<lwidth-1 && u>0 && u<lheight-1) {
tcol = (+ v[i][u+1].col
+ v[i+1][u].col
+ v[i+1][u+1].col*0.5
)*0.4;
tcol = (int)(tcol+col*0.5);
}
else {
tcol = (int)col;
}
fill(tcol, tcol, tcol);
rect(x,y,res,res);
}
}
It's not really commented and I'm somewhat new to programming, so I have no idea where to start as far as understanding it. Is there any good reading on fluid physics? I'm more interesting in the visual effect than the accuracy of the simulation.
A good starting point could be the paper Stable Fluids, it will show you the math behind the fluid simulation, and in the third chapter it describe the implementation of a fluid solver. There is also an open source implementation available in sourceforge (you will need to checkout the source with cvs).

Categories