I have two classes which uses several equal methods, so I thought I could use an abstract class instead of an interface to allow the abstract class to have method bodies, and reduce duplication of code in the other classes.
But I get an error saying x is "null" when running my main function, and I believe that is because it uses the empty variable from the abstract class. But for my method in the abstract class I need to declare the variables the methods uses, so how do I get it to use the variables from my subclass? Specifically, the error is in AGameFigures setPosition()
for bottom.x = x;
Here is my code:
abstract class AGameFigures {
public Rectangle hitbox;
int action;
ICollision collision;
float tileHeight, tileWidth;
float spriteHeight, spriteWidth;
float velocityY;
public AGameFigures(){
this.hitbox = hitbox;
this.action = action;
this.collision = collision;
this.tileHeight = tileHeight;
this.tileWidth =tileWidth;
this.spriteHeight = spriteHeight;
this.spriteWidth = spriteWidth;
this.velocityY = 0;
}
public void update(float delta) {
float oldY = hitbox.y;
hitbox.y = velocityY;
velocityY -= (25 * delta);
boolean collisionDown = false;
boolean collisionUpwards = false;
if(velocityY < 0) {
collisionDown = collision.collidesDownwards(hitbox.x, hitbox.y);
} else if(velocityY > 0) {
collisionUpwards = collision.collidesUpwards(hitbox.x, hitbox.y);
}
if(collisionDown) {
hitbox.y = (int) (oldY / tileHeight) * tileHeight;
velocityY = 0;
}
if(collisionUpwards) {
hitbox.y = (int) ((hitbox.y spriteHeight/2) / tileHeight) * tileHeight;
if(velocityY > 0)
velocityY = 0;
velocityY -= (25 * delta);
}
}
public void setPosition(float x, float y) {
hitbox.x = x;
hitbox.y = y;
}
abstract void moveLeft(float delta);
abstract void moveRight(float delta);
public void setVelocityY(float newVelY) {
velocityY = newVelY;
}
public void jump() {
if (velocityY == 0)
velocityY = 7;
}
public int hits(Rectangle r) {
if(hitbox.overlaps(r))
return 1;
return -1;
}
}
public class GamePlayer extends AGameFigures{
public Rectangle hitbox;
int action;
float tileHeight, tileWidth;
float spriteHeight, spriteWidth;
ICollision collision;
float velocityY;
public GamePlayer(float spriteHeight, float spriteWidth, ICollision collision) {
hitbox = new Rectangle(0.0f, 0.0f, 128.0f, 128.0f);
velocityY = 0;
hitbox.x = 0; hitbox.y = 0;
tileWidth = collision.getTileWidth(); tileHeight = collision.getTileHeight();
this.spriteHeight = spriteHeight; this.spriteWidth = spriteWidth;
this.collision = collision;
}
public void action(int type, float x, float y) {
if(type == 1) {
velocityY = 0;
setPosition(hitbox.x, y);
}
}
@Override
public void moveLeft(float delta) {
hitbox.x -= (200 * delta); // delta == "change of time" "for fluid change om motion"
if(collision.collidesLeftwards(hitbox.x, hitbox.y)) {
hitbox.x = (int) (hitbox.x / tileWidth) * tileWidth spriteWidth;
}
}
@Override
public void moveRight(float delta) {
hitbox.x = (200 * delta); // (value) * delta, endre value for å endre movementspeed
if(collision.collidesRightwards(hitbox.x, hitbox.y)) {
hitbox.x = (int) (hitbox.x / tileWidth) * tileWidth;
}
}
}
CodePudding user response:
From the AGameFigures
constructor:
public AGameFigures(){
this.hitbox = hitbox;
...
}
There are no arguments passed to the constructor, so hitbox
refers to the class instance field, which is null. This line of code from the constructor:
this.hitbox = hitbox;
is effectively:
this.hitbox = null;
So later on a null ponter is encountered. The constructor needs to be updated to pass the arguments:
public AGameFigures(Rectangle hitbox, ...){
this.hitbox = hitbox;
...
}
and the sub-classes will need to provide the constructor argument values.
GamePlayer
defines its own hitbox
which is probably causing some confusion. hitbox
should be removed from GamePlayer
, and just rely on the base class.
Check the compiler warnings, and do not (usually) ignore them!
CodePudding user response:
why you diclare the sames filed in superclass and subclass
CodePudding user response:
I think that your issue is in the constructor of the abstract class. The variables will always be null.
You need to provide params in the constructor:
public AGameFigures(Hitbox hitbox, int action, ICollision collision, float tileHeight, float tileWidth, float spriteHeight, float spriteWith, float velocityY){
this.hitbox = hitbox;
this.action = action;
this.collision = collision;
this.tileHeight = tileHeight;
this.tileWidth =tileWidth;
this.spriteHeight = spriteHeight;
this.spriteWidth = spriteWidth;
this.velocityY = 0;
}
And, you don't need to repeat the variables which are inherited.