Author Topic: error when FlxG.resetGame()  (Read 2238 times)

VanDiest

  • Member
  • **
  • Posts: 21
  • Karma: +0/-0
    • View Profile
error when FlxG.resetGame()
« on: Tue, Apr 29, 2014 »
So I have this piece of code
Code: [Select]
if (Registry.player.overlaps(Registry.enemies)) FlxG.resetGame();

when I try to run the game and the player hits the enemies I get the notorious [Fault] exception, information=TypeError: Error #1009: Cannot access a property or method of a null object reference. error.

I have googled this and found a really old post here on the forum and the person had the same problem as I do right now, they said the problem had to do with using a Registry and he fixed it by adding init functions for his variables, but I am not sure where to add these init functions. Any help would be appreciated!

here is the said post
Fixed it! I was using a registry, and I assigned my variables in the class instead of inside of a init function. Which worked fine for playing the game, but not at all when it came time to reset it. Thanks guys.

Arkeus

  • Contributor
  • ****
  • Posts: 321
  • Karma: +1/-0
    • View Profile
    • I, Arkeus
Re: error when FlxG.resetGame()
« Reply #1 on: Tue, Apr 29, 2014 »
Usually this is because you keep references to the things you add to the state, and then continue to use them after resetting. For example, if you keep a variable pointing to your player you add, then call reset, then when something gets called on your player (before you re-set it, if you do) you'll get a null pointer because the reset disposed of all the objects added to your game, and now you're trying to use it.

Not always the case, but usually the most common in this case. Sounds like he had references in his registry that he initialized once, added to the game, and then they broke when he reset. And he fixed them by creating them in the state when he adds them to the state/group, and assigning it then.

VanDiest

  • Member
  • **
  • Posts: 21
  • Karma: +0/-0
    • View Profile
Re: error when FlxG.resetGame()
« Reply #2 on: Tue, Apr 29, 2014 »
Not always the case, but usually the most common in this case. Sounds like he had references in his registry that he initialized once, added to the game, and then they broke when he reset. And he fixed them by creating them in the state when he adds them to the state/group, and assigning it then.

I understand that something is trying to access something else that becomes null after I try to reset but I cannot figure out what it is. Everything is added on the playstate and the variables are set within their own classes. Here is my playstate (its the only state in the game right now)

Code: [Select]
package
{
import org.flixel.*;
import org.flixel.plugin.photonstorm.FlxWeapon;

public class PlayState extends FlxState
{
private var score:FlxText;
private var weapon:FlxWeapon;
private var starfield:StarField;

public function PlayState():void
{

}

override public function create():void
{
FlxG.framerate = 60;
FlxG.flashFramerate = 60;
FlxG.worldBounds.make(0, 0, 450, 480);

starfield = new StarField(-90, 35);
add(starfield);

add(Registry.rocks);
add(Registry.smallRocks);
add(Registry.satellites);
add(Registry.effects);
add(Registry.player);

weapon = new FlxWeapon("weapon", Registry.player, "x", "y");
weapon.makeAnimatedBullet(20, Sources.ImgBullet, 10, 10, [1], 8, true, 7, 0);
weapon.setBulletDirection(FlxWeapon.BULLET_UP, 300);
weapon.setFireRate(150);
add(weapon.group);

score = new FlxText(0, 0, FlxG.width, "");
score.setFormat(null, 8, 0xFFFFFFFF, "center", 0xFF000000);
add(score);
}

override public function update():void
{
FlxG.score++;
score.text = FlxG.score.toString();
if (FlxG.mouse.pressed()) weapon.fire();

FlxG.overlap(weapon.group, Registry.satellites, Registry.satellites.bulletHitEnemy);
FlxG.overlap(weapon.group, Registry.rocks, Registry.rocks.bulletHitRock);
FlxG.overlap(weapon.group, Registry.smallRocks, Registry.smallRocks.bulletHitRock);
//if (Registry.player.overlaps(Registry.satellites)) FlxG.resetGame();

super.update();
}
}
}

Arkeus

  • Contributor
  • ****
  • Posts: 321
  • Karma: +1/-0
    • View Profile
    • I, Arkeus
Re: error when FlxG.resetGame()
« Reply #3 on: Tue, Apr 29, 2014 »
Code: [Select]
add(Registry.rocks);
add(Registry.smallRocks);
add(Registry.satellites);
add(Registry.effects);
add(Registry.player);

Here you're adding objects in your registry. When you reset, these objects are destroyed, but then you add them to the new playstate (the destroyed versions). You need to create the objects any time you add them, because anything you have added to a state is destroyed when you change states/reset, but you'll still be pointing at the destroyed ones. You want to get rid of any reference to anything that's been added to a state whenever you change states/reset.

VanDiest

  • Member
  • **
  • Posts: 21
  • Karma: +0/-0
    • View Profile
Re: error when FlxG.resetGame()
« Reply #4 on: Wed, Apr 30, 2014 »
Here you're adding objects in your registry. When you reset, these objects are destroyed, but then you add them to the new playstate (the destroyed versions). You need to create the objects any time you add them, because anything you have added to a state is destroyed when you change states/reset, but you'll still be pointing at the destroyed ones. You want to get rid of any reference to anything that's been added to a state whenever you change states/reset.

So how exactly do I go about doing this? Do I need a new way to create the objects in the Registry? are the references the FlxG.overlap lines? Im sorry I dont fully understand what to do

Arkeus

  • Contributor
  • ****
  • Posts: 321
  • Karma: +1/-0
    • View Profile
    • I, Arkeus
Re: error when FlxG.resetGame()
« Reply #5 on: Wed, Apr 30, 2014 »
The best way would be to not have any references to objects in your registry. Get rid of all those, and create these objects in your state's create, every time your state is created. Things work much better if you never reuse objects between states.

Then if you need references to everything, keep a reference to your state in your registry. In your playstates create, do Registry.state = this; as the first thing. Then if you want to reference these objects, do Registry.state.rocks or whatever.

VanDiest

  • Member
  • **
  • Posts: 21
  • Karma: +0/-0
    • View Profile
Re: error when FlxG.resetGame()
« Reply #6 on: Wed, Apr 30, 2014 »
The best way would be to not have any references to objects in your registry. Get rid of all those, and create these objects in your state's create, every time your state is created. Things work much better if you never reuse objects between states.

Then if you need references to everything, keep a reference to your state in your registry. In your playstates create, do Registry.state = this; as the first thing. Then if you want to reference these objects, do Registry.state.rocks or whatever.

ok I just removed the Registry entirely.
now I just send the objects that are being referenced through parameters in whatever I need it (ex: enemy(player); )
I've read that a registry isn't good programming practice, is that true? and is this the way it 'should' be?

Arkeus

  • Contributor
  • ****
  • Posts: 321
  • Karma: +1/-0
    • View Profile
    • I, Arkeus
Re: error when FlxG.resetGame()
« Reply #7 on: Wed, Apr 30, 2014 »
People say its a bad programming practice because it introduces a lot of problems (as you saw), because it allows you to access things that might not be valid. So I guess the quick answer is that it can be considered bad because it allows you to do a lot of bad things. For example, you might realize "oh I can just access the player from this random menu panel code, that'll make this easy to display how much money you have!", so you do it, and it causes hard to debug problems down the line because you change your menu to be available on the title screen when there is no player, so when it goes to access it everything breaks. Sometimes that's easy to figure, and sometimes it's a black hole that sucks up all your time trying to find out what's wrong.

If you're careful with using it, it can be extremely helpful. Often times it can become extremely cumbersome to pass around references to everything you might need access to. If you're working on a small project, usually you can save a lot of time and code by having a registry. However, you have to be aware of what can go wrong, and take care when using it.

For larger projects it becomes worse because the bigger the project, the more places things can go wrong. And problems due to accessing global state can be very hard to track down, which can suck up a lot more time than you save when working on a large project. It makes things harder to test by having global state, and is better to use dependency injection, for example.

That said, in all my projects I use a registry, but extremely limited. I usually keep access only to singleton classes (typically data such as party info, inventories, etc) and the states, rather than the contents (with some exceptions for something that is used very often), and since I've fell in all the pitfalls of a registry back when I was learning flash, I'm careful how I use it, and only when necessary. I find it super helpful, but everyone has their own opinion.

VanDiest

  • Member
  • **
  • Posts: 21
  • Karma: +0/-0
    • View Profile
Re: error when FlxG.resetGame()
« Reply #8 on: Thu, May 1, 2014 »
That said, in all my projects I use a registry, but extremely limited. I usually keep access only to singleton classes (typically data such as party info, inventories, etc) and the states, rather than the contents (with some exceptions for something that is used very often), and since I've fell in all the pitfalls of a registry back when I was learning flash, I'm careful how I use it, and only when necessary. I find it super helpful, but everyone has their own opinion.

thanks alot dude!