Jump to content

Persistent level state when exiting and re-entering (objects etc.)


Recommended Posts

Hello all,


I am pretty new to Phaser, and am trying to build a simple platformer game.

There is no live version yet (the code needs a lot of refactoring, and is in *many* files), but I made a quick screencast if you are curious:



The user can go back and forth between each level using doors. For now every time the user enter a level, all the objects (only monsters for now) are recreated.

I was planning to add coins (or diamonds etc.) in each level, and was wondering what would be the best approach if I would like to make the state of each level persistent: if the player has already collected all the coins, the level would now be empty.


What I had in mind

- on entering a level, parse the tilemap objects and retrieve all objects matching the type "coin"

- put all these in an array

- copy this array in a global object ('levelState'), with a reference to the level they come from

- when a player grabs a coin, delete the reference to this coin from the global object

- when the player re-enters the level, check if a reference to this level exists in 'levelState'

- if it exists, render the coins from the 'levelState' object rather from the tilemap data


Would this be the correct approach? Any potential issues?

Is there another way to do it?


Thank you!


Link to comment
Share on other sites

I am going to answer to myself, since I found a way that seems to work well enough – in case that's helpful for someone, or if maybe there is a better way :)


I started with the BasicGame object, which allows to keep things stored between different states. In the boot state, I created something looking like this:

BasicGame = {    visitedLevels: []};

Every time I load a new level, I check if the visitedLevels key is either empty, or matches something existing. 
If it is empty of there is not match, I set a value alreadyVisited to false, and create a new key:

BasicGame.visitedLevels.push({  levelName: 'theLevelName',  coins: []})

Now every time the player grabs a coin, I add its coordinates in the coins array:

for (var i=0; i<BasicGame.visitedLevels.length; i++){  if (BasicGame.visitedLevels[i].levelName == this.currentLevel) {    BasicGame.visitedLevels[i].coins.push(      {x: coin.cameraOffset.x, y:coin.cameraOffset.y}    );  }}

(not sure if using cameraOffset is the proper way, but that's the only value that matched the one I grabbed from the tilemap).


After a couple of coins collected, the BasicGame object starts to look like:

BasicGame = {  visitedLevels: [    {      levelName: 'theLevelName',      coins: [        {x: 2, y: 6},        {x: 100, y: 82}      ]    }  ]};

Then when I create my level and add the coins, I check first if alreadyVisited is false.

If it is true, I compare each coin coordinates with what I have stored in the BasicGame object for the current level. I only add the coin if there is no match.


There are a bunch of ugly loops, but the thing seems to work :) :

createCoins: function() {  this.coins = this.add.group();  var coinArr = this.findObjectsByType('coin', this.map, 'objectsLayer');  var coin;  coinArr.forEach(function(element) {    if (this.alreadyVisited){      var coinWasTaken = false;      for (var i=0; i<BasicGame.visitedLevels.length; i++) {        if (BasicGame.visitedLevels[i].levelName == this.currentLevel) {          for (var j=0; j<BasicGame.visitedLevels[i].coins.length; j++) {            console.log(BasicGame.visitedLevels[i].coins[j]);            if(BasicGame.visitedLevels[i].coins[j].x == element.x && BasicGame.visitedLevels[i].coins[j].y == element.y) {              coinWasTaken = true;            }          }        }      }      if (!coinWasTaken) {        coin = new Coin(this.game, element.x, element.y, this.map);        this.coins.add(coin);      }    } else {      coin = new Coin(this.game, element.x, element.y, this.map);      this.coins.add(coin);    }    //console.log(element);  }, this);}

It works, but I would be curious to know if there are other solutions, or maybe a more "standard" way to achieve the same thing.

I could probably make the whole thing more generic so it would work for different types of objects instead of being hardcoded in the createCoins() function...

Link to comment
Share on other sites

Thank you for your answer.


That's actually what I was planning to do at first (actually, a copy of only the objects array), then I wondered if storing only the differences (ie, the items that were picked only, instead of the whole level) wouldn't be easier on the memory.

Does it actually make a difference except from a code readability perspective?


A quick screencap of the thing for now:


Link to comment
Share on other sites

Well, the memory isn't a problem. As long as you don't have over 1k levels with 1k objects each, the save object won't be that big. But CPU performance is affected a bit if every time you create a new coin you check if it already exists (eg: you iterate through all possible objects instead of iterating directly through the ones you want to create).


It's ok doing it in the both ways, but actually removing the item once a player collects it seems like the cleaner way to do it.

Link to comment
Share on other sites


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...