Changing/reseting the world isn't really working 100% [SOLVED]


(John Andersson) #1

Okay, so I have ice levels and normal levels.

All the levels also have a backdrop of a sky image. I have some code that resets the game world if you die (duh). If you die on a level and lose the last life ,you get respawned a few levels back.

However, when this happens, the game world doesn’t really update perfectly. I’ve noticed that if I die at, let say, lvl 15 which is a normal level, then go back to 12 (ice level) since my lives ran out, then the level doesn’t skin the entities within the game to be that of an ice version. Also, there is no backdrop anymore!!

Death code in the player class (reset world)

FP.world = new GameWorld(Maps.TILESET);
FP.world.recycle(this)

game world code…

	public static var isNormalLevel:Boolean = false;
	public static var isIceLevel:Boolean = false;

	public function GameWorld(tileset:Class)
	{
		_tileset = tileset
		
		//Reset statics
		Surv_Area.activated = false;
		Surv_Area2.activated = false;
		Surv_Area3.activated = false;
		Surv_Gate.opened = false;
		Surv_Gate2.opened = false;
		Surv_Gate3.opened = false;
		
		isNormalLevel = false;
		isIceLevel = false;
		
		if (currentLevel < 13) isNormalLevel = true;
		else isIceLevel = true;
	}


override public function begin():void
	{
		isNormalLevel = false;
		isIceLevel = false;
		
		if (currentLevel < 13) isNormalLevel = true;
		else isIceLevel = true;
		
		FP.volume = 1;
		super.begin();
		
		Music.main_theme.stop();


  // THIS IS THE BACKDROP CODE ----------------------------------------------
	
      if (currentLevel != 4 && currentLevel != 8 && currentLevel != 9 && currentLevel != 10 && currentLevel != 11) FP.world.add(skyone);

		
		//HUD
		add(hud);
		
		//Level
			//Set checkpoint
			trace ("Current level: " + currentLevel);
		
		//Cam
		HeroStats.camCanMove = true;
		
		if (GameWorld.currentLevel < 9) FP.screen.color = 0x4A8EFF;
		if (GameWorld.currentLevel >= 9 && GameWorld.currentLevel <= 12) FP.screen.color = 0x100F15;
		if (GameWorld.currentLevel >= 13 && GameWorld.currentLevel <= 15) FP.screen.color = 0x4A8EFF;
		if (GameWorld.currentLevel >= 17 && GameWorld.currentLevel <= 19) FP.screen.color = 0x000000;
		if (GameWorld.currentLevel >= 21 && GameWorld.currentLevel <= 23) FP.screen.color = 0x2E142E;
		
		//Reset lives
		if (HeroStats.lives == 0) 
		{
			if (currentLevel <13)
			{
                                   _tileset
			}			
			
			if (currentLevel >= 13 && currentLevel <= 15)
			{
				loadLevel(Maps.LEVEL_13, Maps.TILESET_ICE);
				
				currentLevel = 13;
			}
			
			HeroStats.lives = 3;

		}else {
			if(currentLevel == 1) loadLevel(Maps.LEVEL_1, _tileset);
			if(currentLevel == 2) loadLevel(Maps.LEVEL_2, _tileset);
			if(currentLevel == 3) loadLevel(Maps.LEVEL_3, _tileset);
			if(currentLevel == 4) loadLevel(Maps.LEVEL_4, _tileset);
			if (currentLevel == 5) loadLevel(Maps.LEVEL_5,_tileset);
			if (currentLevel == 6) loadLevel(Maps.LEVEL_6, _tileset);
			if (currentLevel == 7) loadLevel(Maps.LEVEL_7,  _tileset);
			if (currentLevel == 8) loadLevel(Maps.LEVEL_8,  _tileset);
			if (currentLevel == 9) loadLevel(Maps.LEVEL_9, _tileset);
			if (currentLevel == 10) loadLevel(Maps.LEVEL_10, _tileset);
			if (currentLevel == 11) loadLevel(Maps.LEVEL_11, _tileset);
			if (currentLevel == 12) loadLevel(Maps.LEVEL_12, _tileset);		
			if (currentLevel == 13) loadLevel(Maps.LEVEL_13, Maps.TILESET_ICE);
			if (currentLevel == 14) loadLevel(Maps.LEVEL_14, Maps.TILESET_ICE);
			if (currentLevel == 15) loadLevel(Maps.LEVEL_15, Maps.TILESET_ICE);
		}
		
		//Music	
		 Music.main_theme.loop();
		
		//Rain
		if(currentLevel == 9) SoundFX.rain.loop();
		
		if (currentLevel == 10) FP.camera.y = 1;
		else if (currentLevel == 11) FP.camera.y = 1;
		else FP.camera.y = 76;
		GameStats.fireRingSoundPlaying = false;
	}

As you can see, I added

		isNormalLevel = false;
		isIceLevel = false;
		
		if (currentLevel < 13) isNormalLevel = true;
		else isIceLevel = true;

both in the first normal function, but also in the begin() function. If I don’t do this, then the ice/normal level checking/setting doesn’t work properly. This is evidence of how shitty of a programmer I am.


(Jacob Albano) #2

For real, John, stop talking smack about yourself. It doesn’t add anything to the discussion and it sounds like you’ve given up already. You’re not a terrible programmer, you just think you are because you run into problems. Guess what? Everyone runs into problems. Including those of us who have been programming for years.

I’m running out the door on the way to work, so I can’t give you a comprehensive answer yet. Should be back in a few hours.


(John Andersson) #3

Haha, I must admit I said that only to get sympathy help, eagerly awaiting your help!! :blush:


(Jacob Albano) #4

Frankly, my first instinct when I see stuff like that is to ignore it entirely. Don’t do it again please. It’s manipulative and I don’t have the energy to deal with it.

Now, the issue.

This code is another great example of why I always recommend against using static variables. The bottom line is that if you do this:

new GameWorld();
new GameWorld();

…and those two objects aren’t identical, you’re doing something (likely wrong) with global scope. And since your world logic depends on variables from all over your project, it’s impossible to isolate any one piece of code and test it to see what’s going on. Now, due to these dependencies, I can’t simply take your code and play with it until it works. The best I can do is guess, so here are some guesses.

Firstly, you’re falling into the common trap of using FP.world for more than assignment. When you assign to it, you’re not changing that property itself – rather, you’re telling the engine to switch to the new world on the next frame. So what’s actually happening is this:

// FP.world is the currently updating world

// set it to a new instance, but it's a trap!
// FP.world will still return the same value. It hasn't changed yet.
FP.world = new GameWorld(Maps.TILESET);

// you think you're recycling the player to the newly created world
// but he ends up recycled into the world he's already in
FP.world.recycle(this);

If this isn’t the behavior you want, change it to read like this:

var world:World = new GameWorld(Maps.TILESET);
world.recycle(this);
FP.world = world;

Onward.

You can cut out 99% of your level loading code with these few lines:

// check level bounds
if (currentLevel == 0 || currentLevel > 15) throw new Error("Invalid level number: " + currentLevel);

// assign tilesets appropriately
var tileset:Object = _tileset;
if (currentLevel >= 13 && currentLevel <= 15) tileset = Maps.TILESET_ICE;

// use reflection to get the right map by its name
loadLevel(Maps["LEVEL_" + currentLevel], Maps.TILESET_ICE);

I don’t see anything in here that could be causing your problem, and I think you just need to buckle down and reduce the number of static variables. At least one of them isn’t getting reset, I’m sure of it. Check on all your conditionals (if (), while(), ect) and see what they’re making decisions based on. Decide whether you need all those “Surv_” variables to be static if you’re resetting them all to false every time anyway. Maybe even add a property to your levels to determine whether they’re supposed to be regular or ice (if you’re using Ogmo, that is), instead of basing that decision on the level number.

Beyond that I don’t think I can help you.


(John Andersson) #5

Thank you, I’ll reduce the static variables as soon as I can access the world’s variables from other entities normally…

And ps, I was actually hammering myself, I just felt so ashamed after reading your reply that I tried acting all different :stuck_out_tongue:

It is just so frustrating to run into errors after almost every line of code I write. But I’ll get better, I guess!

EDIT: Forgot saying that I solved the problem, it was because I handled the “reset checkpoints and starting level when lives get down to 0”-code AFTER setting the ice-themes and backdrop!