[SOLVED] Use the same Player object across scenes

This may be a super simple and basic thing, so I apologize. What is the best way to go about utilizing my Player object from my initial scene throughout the entire game? I have a few things attached to my player that need to remain from level to level such as health, collected items, power-ups etc.

So I need the state of my player from the tutorial level to carry over to level 1 and so on.

I need:

this.player = new Player(this, 400, this.stoneGround.y - 80, "player1");

In my opening scene, to be re-used in every scene after. The RPG elements in my game won’t allow me to create a new player each level because my player must keep its state and all of the new values it obtains from level to level

Probably refactor to separate these.

Either make a pure Player class that can store and remove a game object (e.g., this.sprite) for each scene cycle or else have the class save and load its data somewhere else, like game.data, when switching scenes.

1 Like

I’m currently using a Player class and the arguments I’m passing are for the position of the player and the skin. (Will use different skins later). Is that what you’re referring to as a pure Class?

I’m currently using:

export default class Player {
     constructor() {

     }
}

So I’m currently testing local storage for the player.

localStorage.setItem("player", this.player);
    var testPlayer = localStorage.getItem("player");
    console.log(testPlayer);

Unfortunately in my console all I am getting is [object Object] and when I try to load local storage in my second scene, it acts like it has no idea what data I’m loading.

I just did a test and replaced my code above with a string as the value:

localStorage.setItem("player", "test");
var testPlayer = localStorage.getItem("player");
        console.log(testPlayer);

This worked just fine and even let me use it in my other scenes. For some reason I can’t store my player.

Hey Ben, it’s good practice to keep your data and your logic/objects separate. I would create a separate JSON object that would store all of the player data, for example:

{
    playerName: "Mr.Biggles",
    x: 100, y: 100,
    equipment: {
        hat: "Fedora",
        shoes: "Cowboy Boots"
    }
}

Then you can either create a static function which takes in the player configuration and returns your built player (aka, a factory). Or in the constructor of your player class, you can take in the config and assign all of the data there.

If you want to save your player’s session data, you can do the following:
localStorage.setItem("myPlayerData", JSON.stringify(playerData));

Note the JSON.stringify.

Hey Jake,

Thanks for the awesome response as usual. So just to make sure I’m understanding. In my first scene, instead of having a player Class, I would just build out the player in that first scene like this:

function createPlayer (scene, x, y, sprite) {
     let player = scene.add.image(x, y, sprite);
     player.setColliderWorldBounds(true);
     player.setScale(.75);
     return player;
}

And then I would just have my JSON file that would store powerups, collectibles, and the level the player is on. When the player changes level, or obtains a collectible, I would then update the JSON data and use that to load the data each scene? And then just store and load the createPlayer function each level since it isn’t storing data?

Almost. You’ll definitely still want a player class to handle all of your player logic. If you’re going the factory route, I would create a static function. Static functions are nice because they can be accessed anywhere in your code. The function would look something like the following:

export default class ObjectFactory
{
    static createPlayer(playerConfig)
    {
        let player = new Player();
        player.setPosition(playerConfig.x, playerConfig.y);
        player.setEquipment(playConfig.equipment);
        return player;
    }
}

Note: I believe static functions were implemented in es6. So if you are using es5, you’ll have to find an equivalent.

In your player class, you’ll probably want a saveData method, which would look something like:

playerData.name = this.name;
playerData.equipment = this.equipment;
localStorage.setItem("myPlayerData", JSON.stringify(playerData));

Call that method whenever you make changes to your player.

There are quite a few ways you could handle this whole saving PlayerData stuff, but this is what I would do for the time being until I happen upon a more convenient way of saving session data.

3 Likes

Thank you Jake,

Everything I’ve done up to this point has been pretty quick and I’ve been able to polish my tutorial level and menu screen quite well. Now the hard stuff begins. I’ll work with this over the next week and keep you updated on how it’s going.

Have a great day.

1 Like

No problem and good luck!

1 Like

This is too complicated for me. I don’t think I can do it. I created my PlayerFactory and it works fine but I still can’t load my player object into the next scene. I don’t even know what to paste in here to show you to help, it’s all so screwed up

hey! @Benstrocity, sorry to jump in the middle of this, but you do not need to give up yet.

First of all, I believe in your ability to get this to work.

Second, if I understand correctly, your first scene works nicely, right? If that is the case, I’d just make sure that:

  1. if you are using localStorage, clear it up now. Then at around the end of your first scene, make sure that you’ve stored there what you wanted. a console.log to check for it is ok.
  2. Next comes the part of loading the data you want when creating the player. In the createPlayer function, make sure you still have access to the data you want to use. If it is there, you are almost there, and can tell us what is going on.

Lastly, if it all fails, we can go back to square 0 and write a short prototype (with jsfiddle). I think many people would find such an example interesting, so I might end up writing it anyways.

Just don’t give up now! =D

[edit]: I made 2 jsfiddle’s to test out a couple of ideas.

The first one uses the registry to achieve what you want: link

The second one uses data you pass as you start/stop scenes: link.

I may make a third one, using a factory for player, just let me know.

[2nd edit]: Here’s another, perhaps more useful jsfiddle: link

2 Likes

Thank you, @Idd for your help and for bringing me back down to earth. I was actually able to figure it out using a JavaScript Object. I created a new PlayerData.js file with this content:

let playerData = {
memories: [],
lives: [],
special: {
    fly: false,
    doubleJump: false,
    superSpeed: false
}
}

export default playerData;

I then added a playerData argument to my Player class to pass in the playerData object. Then I imported my playerData variable from my new javascript file.

Now, I can create a new player each level and pass the playerData object to the player. All my player does now is render a sprite at a location and contain movement controls.

It works perfectly and now I can mess with giving users the option to save their game and then load it the next time they come back.

This is probably one of the more difficult things I’ve encountered in JavaScript (even though it may seem simple in hind sight). Thanks for the help guys.

2 Likes