Player Sessions

Otter provides a Session class which can be used for keeping track of a player in your game.  A Session can be named with a string or an Enum.  You can assign controls to a Session, and give it other misc data that can be easily imported and exported in a semi-encrypted format to keep players from messing with your secret save data (they can still mess with it if they're smart enough, though!)

Here's a quick example of how to create a simple two player scenario using Sessions.

using Otter;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PlayerSessions {
  class Program {
    static void Main(string[] args) {
      // Create a game
      var game = new Game("Player Sessions");
      // Name the game folder for exporting session data.
      game.GameFolder = "PlayerSessionDemo";

      // Add a new session to the game for Player 1.
      var session = game.AddSession("TestPlayer1");

      // Import any data. If no data found, none will be loaded.
      session.Data.Import();

      // Load data, or set default values.
      // Using strings for keys here, but you can also use Enums!
      session.Data.GetIntOrDefault("LevelsUnlocked", 0);
      session.Data.GetStringOrDefault("LeaderboardName", "Player");
      session.Data.GetBoolOrDefault("InvertedControls", false);
      session.Data.GetStringOrDefault("PlayerColor", "FF0000");
      session.Data.GetFloatOrDefault("StartPosition", 0.25f);

      // Export the data to a semi-encrypted file.
      session.Data.Export();

      // Configure the Controller for the player session.
      // Add a "Left" button
      session.Controller.AddButton("Left");
      // Set the button to respond to the A key.
      session.Controller.Button("Left").AddKey(Key.A);

      // Add a "Right" button
      session.Controller.AddButton("Right");
      // Set the button to respond to the D key.
      session.Controller.Button("Right").AddKey(Key.D);

      // Add a new session to the game for Player 2.
      session = game.AddSession("TestPlayer2");

      // Import any data. If no data found, none will be loaded.
      session.Data.Import();

      // Load data, or set default values.
      // Using strings for keys here, but you can also use Enums!
      session.Data.GetIntOrDefault("LevelsUnlocked", 0);
      session.Data.GetStringOrDefault("LeaderboardName", "Player");
      session.Data.GetBoolOrDefault("InvertedControls", false);
      session.Data.GetStringOrDefault("PlayerColor", "0000FF");
      session.Data.GetFloatOrDefault("StartPosition", 0.75f);

      // Export the data to a semi-encrypted file.
      session.Data.Export();

      // Configure the Controller for the player session.
      // Add a "Left" button
      session.Controller.AddButton("Left");
      // Set the button to respond to the Left key.
      session.Controller.Button("Left").AddKey(Key.Left);
      
      // Add a "Right" button
      session.Controller.AddButton("Right");
      // Set the button to respond to the Right key.
      session.Controller.Button("Right").AddKey(Key.Right);

      // Create a Scene.
      var scene = new Scene();
      // Add a Player Entity for each session.
      scene.Add(new Player(game.Session("TestPlayer1")));
      scene.Add(new Player(game.Session("TestPlayer2")));

      // Start the Game.
      game.Start(scene);
    }
  }

  class Player : Entity {
    // Create a test image.
    Image image = Image.CreateRectangle(40, Color.White);
    // The Session that this Entity will reference.
    Session session;

    public Player(Session session) : base() {
      // Keep track of the Session passed in by the constructor.
      this.session = session;

      // Set the starting position.
      // Using Game.Instance here because the Entity doesn't have a reference to the Game yet.
      X = Game.Instance.HalfWidth;
      Y = Game.Instance.Height * session.Data.GetFloat("StartPosition");

      // Add the image.
      AddGraphic(image);
      // Center the origin of the image.
      image.CenterOrigin();
      // Set the image color from the Session data. 
      // Using a string for the key, but you can also use Enum!
      image.Color = new Color(session.Data.GetString("PlayerColor"));
    }

    public override void Update() {
      base.Update();

      // Use the Session controller to control the movement.
      // Using a string for the key, but you can also use Enum!
      if (session.Controller.Button("Left").Down) {
        X -= 3;
      }
      if (session.Controller.Button("Right").Down) {
        X += 3;
      }
    }
  }
}

Here is the game loaded using two player Entities that are loading data from configured Sessions.

The exported data is saved into the My Documents folder on Windows.

The inside of one of these files looks like a mess of ascii characters.  This prevents the average player from messing with their save data, although a more advanced user can probably figure out how to tinker with it, so this is not a bullet proof solution for tampering with save data.

With Sessions you can create a near infinite number of save files for your players.  Simply have the players input a string to name their save data at the start of your game and all their data can be stored in one of these ".data" files with the name that they provided.

Examples