Java-Gaming.org Hi !
Featured games (91)
games approved by the League of Dukes
Games in Showcase (763)
Games in Android Showcase (229)
games submitted by our members
Games in WIP (852)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Trying to set up a class hierarchy  (Read 3755 times)
0 Members and 1 Guest are viewing this topic.
Offline kutucuk

Senior Devvie


Medals: 5
Exp: 3 years



« Posted 2014-02-16 15:10:43 »

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:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
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:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
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:
1  
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?
Offline kutucuk

Senior Devvie


Medals: 5
Exp: 3 years



« Reply #1 - Posted 2014-02-16 16:01:16 »

The only solution which doesn't break my Entity class I came up with is this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
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();
   }
}
Offline GoToLoop

Junior Devvie


Medals: 2
Exp: 1 year



« Reply #2 - Posted 2014-02-16 16:25:28 »

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?

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
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();
  }
}
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline GoToLoop

Junior Devvie


Medals: 2
Exp: 1 year



« Reply #3 - Posted 2014-02-16 16:30:50 »

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

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
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
  }
}
Offline kutucuk

Senior Devvie


Medals: 5
Exp: 3 years



« Reply #4 - Posted 2014-02-16 16:47:39 »

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

Junior Devvie


Medals: 2
Exp: 1 year



« Reply #5 - Posted 2014-02-16 17:18:56 »

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!   Roll Eyes

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
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();
  }
}
Offline kutucuk

Senior Devvie


Medals: 5
Exp: 3 years



« Reply #6 - Posted 2014-02-16 18:28:52 »

I intended those to be constants, just forgot to add final Smiley

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 Smiley
Offline GoToLoop

Junior Devvie


Medals: 2
Exp: 1 year



« Reply #7 - Posted 2014-02-16 19:56:08 »

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

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
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;
    }
}


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
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);
    }
}
Offline Opiop
« Reply #8 - Posted 2014-02-16 20:06:17 »

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.
Offline philfrei
« Reply #9 - Posted 2014-02-16 22:09:03 »

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

1  
2  
3  
4  
5  
6  
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
}

music and music apps: http://adonax.com
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline GoToLoop

Junior Devvie


Medals: 2
Exp: 1 year



« Reply #10 - Posted 2014-02-16 23:18:01 »

Or rather than null arguments, new 1s!   Roll Eyes  

1  
2  
3  
4  
5  
public class Player extends Entity {
    public Player(SpriteBatch spriteBatch, World world) {
        super (new Texture(), spriteBatch, world, new FixtureDef(), new BodyDef(), new CircleShape());
    }
}
Offline kutucuk

Senior Devvie


Medals: 5
Exp: 3 years



« Reply #11 - Posted 2014-02-17 04:37:55 »

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.
Offline Grunnt

JGO Kernel


Medals: 143
Projects: 8
Exp: 5 years


Complex != complicated


« Reply #12 - Posted 2014-02-17 07:38:19 »

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:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
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.

Offline kutucuk

Senior Devvie


Medals: 5
Exp: 3 years



« Reply #13 - Posted 2014-02-17 18:32:22 »

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 Smiley
Offline Gibbo3771

JGO Kernel


Medals: 128
Projects: 5
Exp: 1 year


Currently inactive on forums :(


« Reply #14 - Posted 2014-02-17 19:03:44 »

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 Smiley

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

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
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.

"This code works flawlessly first time and exactly how I wanted it"
Said no programmer ever
Offline kutucuk

Senior Devvie


Medals: 5
Exp: 3 years



« Reply #15 - Posted 2014-02-18 02:36:06 »

Here is what I have done to my classes:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
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:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
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:
1  
Player player = new Player(spriteBatch, world, WTB, BTW);
Offline GoToLoop

Junior Devvie


Medals: 2
Exp: 1 year



« Reply #16 - Posted 2014-02-18 02:51:29 »

1  
2  
3  
4  
5  
6  
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!  Shocked
Offline Gibbo3771

JGO Kernel


Medals: 128
Projects: 5
Exp: 1 year


Currently inactive on forums :(


« Reply #17 - Posted 2014-02-18 07:59:28 »

1  
2  
3  
4  
5  
6  
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!  Shocked

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.

"This code works flawlessly first time and exactly how I wanted it"
Said no programmer ever
Offline DazKins
« Reply #18 - Posted 2014-02-18 11:44:21 »

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

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
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
   }

}

DazKins

Check out my Dev Blog: http://dazkins.tumblr.com
Offline kutucuk

Senior Devvie


Medals: 5
Exp: 3 years



« Reply #19 - Posted 2014-02-18 16:34:57 »

Guys, check reply #16 Smiley 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 Smiley My problem is fixed for now, but please feel free to add anything else.
Pages: [1]
  ignore  |  Print  
 
 

 
EgonOlsen (492 views)
2018-06-10 19:43:48

EgonOlsen (595 views)
2018-06-10 19:43:44

EgonOlsen (406 views)
2018-06-10 19:43:20

DesertCoockie (743 views)
2018-05-13 18:23:11

nelsongames (1016 views)
2018-04-24 18:15:36

nelsongames (981 views)
2018-04-24 18:14:32

ivj94 (1545 views)
2018-03-24 14:47:39

ivj94 (557 views)
2018-03-24 14:46:31

ivj94 (1295 views)
2018-03-24 14:43:53

Solater (560 views)
2018-03-17 05:04:08
Java Gaming Resources
by philfrei
2017-12-05 19:38:37

Java Gaming Resources
by philfrei
2017-12-05 19:37:39

Java Gaming Resources
by philfrei
2017-12-05 19:36:10

Java Gaming Resources
by philfrei
2017-12-05 19:33:10

List of Learning Resources
by elect
2017-03-13 14:05:44

List of Learning Resources
by elect
2017-03-13 14:04:45

SF/X Libraries
by philfrei
2017-03-02 08:45:19

SF/X Libraries
by philfrei
2017-03-02 08:44:05
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!