Trying to set up a class hierarchy

Hey, I’m trying to setup a class hierarchy to do things quicker. I have an entity class and all of the others will inherit.

Problem is, because the constructor should include superclass’ constructor and it should be the first line in the constructor, I cannot do what I want.
This is my class:

public class Entity {
	public float BOX_TO_WORLD;
	public float WORLD_TO_BOX;

	// Drawing
	public Sprite sprite;
	public Texture texture;
	public SpriteBatch spriteBatch;

	// Box2D
	public Body body;
	public FixtureDef fixtureDef;
	public BodyDef bodyDef;
	public Shape shape;
	public World world;

	public Entity(Texture texture, SpriteBatch spriteBatch, World world,
			FixtureDef fixtureDef, BodyDef bodyDef, Shape shape, float WORLD_TO_BOX, float BOX_TO_WORLD) {
		// this.texture = texture;
		this.spriteBatch = spriteBatch;
		this.fixtureDef = fixtureDef;
		this.bodyDef = bodyDef;
		this.shape = shape;
		this.world = world;
		this.BOX_TO_WORLD = BOX_TO_WORLD;
		this.WORLD_TO_BOX = WORLD_TO_BOX;
		
		body = world.createBody(bodyDef);
		body.createFixture(fixtureDef);
		sprite = new Sprite(texture);
		
//Do other stuff etc.
	}

//I've only posted the constructor

So by doing it like this, I want to create a Player class and define fixtureDef, bodyDef, texture and other variables in that class. So that when I want to instantiate the Player, I would only need World and SpriteBatch. Meaning the constructor of my Player class would be like this:

public class Player extends Entity {
	Texture texture;
	FixtureDef fixtureDef;
	BodyDef bodyDef;
	CircleShape shape;

	public Player(SpriteBatch spriteBatch, World world, float WORLD_TO_BOX, float BOX_TO_WORLD) {
		//Planned to define texture, fixtureDef, bodyDef and shape and set their attributes here
		super(texture, spriteBatch, world, fixtureDef, bodyDef, shape, WORLD_TO_BOX,
				BOX_TO_WORLD);
		// TODO Auto-generated constructor stub
	}

}

So I would instantiate a Player easily just like this:

Player play = new Player(spriteBatch, world, WORLD_TO_BOX, BOX_TO_WORLD);

But the super constructor should be the first line. Moreover, I cannot use it if I set variables in the Player class which is understandable.

What can I do here?

The only solution which doesn’t break my Entity class I came up with is this:

public class Player {

	Entity player;
	FixtureDef fixtureDef;
	BodyDef bodyDef;
	Texture texture;
	PolygonShape shape;
	
	public void start(SpriteBatch spriteBatch, World world,float BOX_TO_WORLD, float WORLD_TO_BOX){
		shape = new PolygonShape();
		shape.setAsBox(.25f, .5f);
		fixtureDef = new FixtureDef();
		fixtureDef.density = 5;
		fixtureDef.friction = .1f;
		fixtureDef.restitution = .8f;
		fixtureDef.shape = shape;
		bodyDef = new BodyDef();
		bodyDef.type = BodyDef.BodyType.DynamicBody;
		bodyDef.position.set(5, 5);
		texture = new Texture("data/a.png");
		player = new Entity(texture, spriteBatch, world, fixtureDef, bodyDef, shape, WORLD_TO_BOX, BOX_TO_WORLD);
	}
	
	public void render(){
		player.render();
	}
	
	public void update(){
		player.update();
	}
}

HeyUall! I’m a new member! I believe I’ve got a solution for it and couldn’t resist not to register to answer it. HEHEHE!
How about defining methods to initialize those fields, and invoke them within super () itself?


public class Player extends Entity {
  Texture texture;
  FixtureDef fixtureDef;
  BodyDef bodyDef;
  CircleShape shape;

  public Player(SpriteBatch spriteBatch, World world, float WORLD_TO_BOX, float BOX_TO_WORLD) {
    //Planned to define texture, fixtureDef, bodyDef and shape and set their attributes here
    super (defTexture(), spriteBatch, world, defFixtureDef(), defBodyDef(), defShape(), WORLD_TO_BOX, BOX_TO_WORLD);
    // TODO Auto-generated constructor stub
  }

  public Texture defTexture() {
    return texture = new Texture();
  }

  public FixtureDef defFixtureDef() {
    return fixtureDef = new FixtureDef();
  }

  public BodyDef defBodyDef() {
    return bodyDef = new BodyDef();
  }

  public CircleShape defShape() {
    return shape = new CircleShape();
  }
}

Another option is when the instantiation isn’t too long as something like new Class(), we can do it inside the field declaration itself:

public class Player extends Entity {
  Texture texture = new Texture();
  FixtureDef fixtureDef = new FixtureDef();
  BodyDef bodyDef = new BodyDef();
  CircleShape shape = new CircleShape();

  public Player(SpriteBatch spriteBatch, World world, float WORLD_TO_BOX, float BOX_TO_WORLD) {
    //Planned to define texture, fixtureDef, bodyDef and shape and set their attributes here
    super (texture, spriteBatch, world, fixtureDef, bodyDef, shape, WORLD_TO_BOX, BOX_TO_WORLD);
    // TODO Auto-generated constructor stub
  }
}

Thanks. Both don’t look ideal, but I’ll definitely try them and get back to this thread.

Actually, there’s an inheritance bug in your Player class! You’re re-declaring those 4 fields which are already auto-inherited from Entity!
Also, all-caps names are for constant fields! ::slight_smile:

class Entity {
  public float BOX_TO_WORLD;
  public float WORLD_TO_BOX;

  // Drawing
  public Sprite sprite;
  public Texture texture;
  public SpriteBatch spriteBatch;

  // Box2D
  public Body body;
  public FixtureDef fixtureDef;
  public BodyDef bodyDef;
  public Shape shape;
  public World world;
}

class Player extends Entity {
  /*
  Texture texture;
   FixtureDef fixtureDef;
   BodyDef bodyDef;
   CircleShape shape;
   */

  public Player(SpriteBatch spriteBatch, World world, float WORLD_TO_BOX, float BOX_TO_WORLD) {
    //Planned to define texture, fixtureDef, bodyDef and shape and set their attributes here
    super (defTexture(), spriteBatch, world, defFixtureDef(), defBodyDef(), defShape(), WORLD_TO_BOX, BOX_TO_WORLD);
    // TODO Auto-generated constructor stub
  }

  public Texture defTexture() {
    return texture = new Texture();
  }

  public FixtureDef defFixtureDef() {
    return fixtureDef = new FixtureDef();
  }

  public BodyDef defBodyDef() {
    return bodyDef = new BodyDef();
  }

  public CircleShape defShape() {
    return shape = new CircleShape();
  }
}

I intended those to be constants, just forgot to add final :slight_smile:

Apparently we can’t refer to an instance method while explicitly invoking a constructor. So your methods won’t work.

Also, I removed the variables which are defined in Entity class from Player class. As you can guess, it still doesn’t work.

I kinda expected it not to work, but I can’t get my head around it. It must be something simple. And it must be something to do with the entity class, but I’d just correct it if I knew for sure that it’s the entity class :slight_smile:

Made a model mock-up. Instead of a constructor for parent Entity, turned it an init() method, so we can call it later! ::slight_smile:

class Entity {
    byte[] sprite, texture, spriteBatch;
    int[]  body, fixtureDef, bodyDef, shape, world;

    Entity init(byte[] texture, byte[] spriteBatch, int[] world, 
    int[] fixtureDef, int[] bodyDef, int[] shape) {
        this.texture = texture;
        this.spriteBatch = spriteBatch;
        this.fixtureDef = fixtureDef;
        this.bodyDef = bodyDef;
        this.shape = shape;
        this.world = world;

        body = new int[bodyDef.length];
        sprite = new byte[texture.length];

        return this;
    }
}
public class Player extends Entity {
    static final int NUM = 10;

    public Player(byte[] spriteBatch, int[] world) {
        texture = new byte[NUM];
        fixtureDef = new int[NUM];
        bodyDef = new int[NUM];
        shape = new int[NUM];

        init(texture, spriteBatch, world, fixtureDef, bodyDef, shape);
    }
}

That’s not what he was asking.

OP, you should most likely just create a separate initialize function that is called after you do all your stuff. This initialize function would send all of the new attributes up to its super class, but still allow you to retain the flexibility and ease of use of what you want to do.

Possibility: have the Player constructor provide either a default place-holder value or null for each Entity attribute that you wish to specify later.

public Player(SpriteBatch spriteBatch, World world, float WORLD_TO_BOX, 
    float BOX_TO_WORLD) 
{
    super (null, spriteBatch, world, null, null, null, WORLD_TO_BOX, BOX_TO_WORLD);
    // additional code 
}

Or rather than null arguments, new 1s! ::slight_smile:

public class Player extends Entity {
    public Player(SpriteBatch spriteBatch, World world) {
        super (new Texture(), spriteBatch, world, new FixtureDef(), new BodyDef(), new CircleShape());
    }
}

Thanks guys. I haven’t tried it yet, but an init() method looks fine to me. It is similar to what I came up with, but I guess it is better.

So instead of having a constructor, I’ll just have to call a method to use my object.
Or, maybe I set both a constructor and an initializing method, and use constructor with less arguments.

I’ll let you know when I try one of the suggested solutions.

This also looks like a good case for the use of a Factory pattern. Instead of making a class hierarchy of different types of entities just make one Entity class, and use a EntityFactory class to create different kinds of entities. For example:

public class EntityFactory {
	
	private SpriteBatch spriteBatch;
	// ...
	
	public EntityFactory(SpriteBatch spriteBatch, World world, float WORLD_TO_BOX, float BOX_TO_WORLD) {
		this.spriteBatch = spriteBatch;
		// set other local parameters ...
	}
	
	public Entity createPlayer() {
		Entity e = new Entity();
		e.spriteBatch = spriteBatch;
		// .. set other entity parameters, also those specific to player entity
		return e;
	}
}

This approach looks a bit easier to maintain to me, as it seperates configuration of the entity classes from their implementation. Also, maybe you find the Artemis entity system framework interesting which is used in some games and a good source of ideas & best practices.

Thanks. I admit I don’t have much knowledge about design patterns and I have to read about it. Also it seems they are indispensable for game developing.
You don’t have to apply any of them to your code, but they definitely give you some new perspective, which it seems what I need here.

Anyway, I still haven’t been able to test the suggestions here, I have a busy schedule these days, but I’m definitely going to try them out and get back to you guys for more information or for my findings :slight_smile:

May as well add what I am using at the moment. I basically use an Entity class that is very abstract:



public abstract class Entity implements Disposable, Updatable {

	/* Sprite */
	protected Sprite sprite;

	/* Box2D */
	protected Body body;
	protected BodyDef bd;
	protected FixtureDef fd;
	protected Fixture fixture;
	protected BodyEditorLoader bodyLoader;

public Entity() {
		bd = new BodyDef();
		fd = new FixtureDef();

	}




Obviously I have some fields that are related to pretty much every entity. Such as timers for animation. But pretty much all my entity related classes that use Box2D subclass from this.

Simple, works.

Here is what I have done to my classes:

public class Entity {
	// Variables
	
	public Entity(SpriteBatch spriteBatch, World world, float WORLD_TO_BOX, float BOX_TO_WORLD){
        //Some arguments which will be same for to all entities.
		this.spriteBatch = spriteBatch;
		this.WORLD_TO_BOX = WORLD_TO_BOX;
		this.BOX_TO_WORLD = BOX_TO_WORLD;
	}

	public void init (Texture texture, SpriteBatch spriteBatch, World world,
			FixtureDef fixtureDef, BodyDef bodyDef, Shape shape, float WORLD_TO_BOX, float BOX_TO_WORLD) {
		// These are what I want to define in subclasses, not in the main game screen.
		body = world.createBody(bodyDef);
		body.createFixture(fixtureDef);
		sprite = new Sprite(texture,0,0,16,32);
		//Shortened the code

	}

And this is one of the subclasses:

public class Player extends Entity{
	
	FixtureDef fixtureDef;
	BodyDef bodyDef;
	Texture texture;
	PolygonShape shape;
	
	public Player(SpriteBatch spriteBatch, World world, float WORLD_TO_BOX,
			float BOX_TO_WORLD) {
		super(spriteBatch, world, WORLD_TO_BOX, BOX_TO_WORLD);
		shape = new PolygonShape();
		shape.setAsBox(.25f, .5f);
		fixtureDef = new FixtureDef();
		fixtureDef.density = 5;
		fixtureDef.friction = .1f;
		fixtureDef.restitution = .8f;
		fixtureDef.shape = shape;
		bodyDef = new BodyDef();
		bodyDef.type = BodyDef.BodyType.DynamicBody;
		bodyDef.position.set(5, 5);
		texture = new Texture("data/a.png");
		super.init(texture, spriteBatch, world, fixtureDef, bodyDef, shape, WORLD_TO_BOX, BOX_TO_WORLD);
		// I made it like this, because this one won't have another subclass.
                // If I was going to make a subclass for this, this class' structure would be similar to Entity class.
	}

And I can call this easily like this:

Player player = new Player(spriteBatch, world, WTB, BTW);
public class Player extends Entity{
   
   FixtureDef fixtureDef;
   BodyDef bodyDef;
   Texture texture;
   PolygonShape shape;

I wonder if you are re-declaring Entity’s fields within Player again?
Also, you said that both WORLD_TO_BOX & BOX_TO_WORLD were supposed to be constants. But they’re instance variables after all! :o

What he said, just initialise all the fields in the super class, such as the body def and fixture def. Saves you from sung it every new entity class.

Maybe try using an init() method to instantiate those variables instead of the constructor like this :


public class Player extends Entity {
   Texture texture;
   FixtureDef fixtureDef;
   BodyDef bodyDef;
   CircleShape shape;

   public Player(SpriteBatch spriteBatch, World world, float WORLD_TO_BOX, float BOX_TO_WORLD) {
      super();
      //Planned to define texture, fixtureDef, bodyDef and shape and set their attributes here
      super.init(texture, spriteBatch, world, fixtureDef, bodyDef, shape, WORLD_TO_BOX,
            BOX_TO_WORLD);
      // TODO Auto-generated constructor stub
   }

}

Guys, check reply #16 :slight_smile: I took the advice of the people who replied to the thread and modified it to my needs.

@GoToLoop,
Yes I was. It was a dirty template which I was going to fix as much as I could, and yes, I fixed them.
Also, my point when I said they are meant to be constants was that they are constants in the main game class and I typed them all in capitals so that I don’t forget about the constants in the main class and give different values in one of the other classes. But I made them final in my code, maybe I posted a previous version of the code.

@Gibbo3771,
Yes, what you suggested would be easier and maybe better. But I thought “I’ll change the attributes of those BodyDef and FixtureDefs, so why not just initialize them in the subclasses?”
That idea comes from my laziness. Instead of forgetting the attributes of those objects and then wondering why my characters don’t act the way I set them up, I thought it would be good if I just write 2-3 more lines of codes in the subclasses. So if I forget those, it will just give me a null pointer error instead of weird behavior.

Thanks guys for pointing out the errors and making suggestions to make it better :slight_smile: My problem is fixed for now, but please feel free to add anything else.