Puzzling Pointer Paradox Preventing Possibility of Perfection

Hi Forum,
I’ve run into a problem during development, probably due to my crappy skills as a software engineer but i need enlightenment.
Simplified version of my init():
[java]
Player player;
Enemy enemy;
@Override
public void initialize(AppStateManager stateManager, Application app) {
enemy = new Enemy(player, bulletAppState, assetManager, rootNode);
player = new Player(bulletAppState, assetManager, renderManager, viewPort, rootNode, inputManager, cam, enemy);
}
[/java]
The problem is, player needs to be instantiated before enemy because enemy needs to know where player is, and enemy needs to be instantiated before player because player needs to know where enemy is. I get Null pointers both ways!
Input appreciated,
Thanks

Neither of them need to know anything about the other when the are instantiated. You can provide that information later.

Well, with the code shown above, I get a NullPointer on line 55 of Enemy (which is where it calls player.playerControl.getPhysicsLocation()). The NullPointer is fixed by putting new Player() on the line above new Enemy() but then I get a new Null pointer which is the enemy pointer in player. It’s Null because enemy didnt exist when player comes into existence.

Don’t pass enemy on the constructor. Pass it later in a setEnemy() method.

I will point out that learning Java while also learning to write 3D games is very nearly one of the hardest things in life to do.

1 Like

I already consider myself competent in java, but thanks for the concern! (and the help :D)

Oh, and Merry Christmas

@glcheetham As a general rule, try to use constructors for initialization. Don’t try to do too much in them. That is: pass enemy to Player(), maybe ok. Do something with enemy besides variable assignment, no.

In this example, instead of passing one enemy to the player, one thing you could do is pass a collection of potential enemies, and later somewhere in your player’s main loop (Player.doSomething()) you could have conditions that test for an empty collection, if the collection is not empty then check to see if any potential enemies are in range, if one is in range then check to see if there are hostile feelings between the two, and so on with the conditions becoming more complicated as your game develops.

There is a difference between being competent in syntax and being competent in code structure/design. That being said, what @pspeed mentioned above is your solution. There should be no need for either classes to know anything about the other during initialization. They should acquire their targets after this. The case above is the extreme of applying liner code design to an object-oriented language.

Instead of being offended by what @pspeed said, I’d take it to heart and go read up on object-oriented design concepts WHILE you continue working on your game. It can only help.

2 Likes

As others said, don’t do much in constructor. But try to NOT introduce init method that must be manually called either.
So you can use setters to set object’s dependancies after construction.
But if you don’t like it, you can pass to constructor function that returns that dependancy (in java <8 (and in 8 it still will be, but syntax will look like it was not) it must be actualy object with such function). This allows you to create different behavior based on what provided function actually do. This is called strategy pattern.
And when I mentioned pattern, don’t use them because you can, that makes bad complex code from simple code.