[PROGRESS]
To assist others and offer inspiration, I will share how I approached this project. I would greatly appreciate any feedback or suggestions for improving my code.
Game State Management System Overview
Introduction
This post aims to illustrate and explain the architecture and mechanisms involved in the game state management of our self-hosted game. By detailing our approach, we hope to inspire others and welcome feedback to enhance our implementation.
Architecture
Our system architecture is organized as follows:
The game is self-hosted, and the interaction between these components is crucial for maintaining a smooth user experience.
Game State Configuration
The game state is dynamically constructed based on NPC dialogues and the initiation and conclusion of mini-games. Here’s how we manage the state across different phases of gameplay:
Constraints
- User Authentication: Users must log in to play the game.
- State Persistence: The backend must save the game state persistently.
- Achievement Trigger: Key player actions should trigger achievements.
- Achievement Recording: Achievements must be recorded in the backend.
- Social Display: Achievements should be visible in the social components of the game.
While the first constraint is straightforward, managing the game state (Constraint 2) is more involved and critical for the gameplay experience.
Initialization of Game State
Here is how we initialize and manage the game state:
GameStateController.prototype.initialize = function() {
if (!window.gameStateLoaded) window.gameStateLoaded = false;
this.app.on("game:save", this.saveGameState.bind(this));
if (!window.gameStateLoaded)
this.loadGameState();
if (!window.bobState)
window.bobState = {
predio1: "predio1",
predio2: "predio2",
predio3: "predio3",
predio6: "predio6",
predio7: "predio7",
predio9: "predio9",
};
if (!window.playerState)
window.playerState = {
predio1: 0,
predio2: 0,
predio3: 0,
predio6: 0,
predio7: 0,
predio9: 0,
entryName: undefined,
currentScene: "Campus",
scenePosition: undefined,
miniGames: {},
seenConversations: {},
completedMiniGames: {
predio1: [],
predio2: [],
predio3: [],
predio6: [],
predio7: [],
predio9: [],
}
};
const building = window.bobState[this.entity.getPlayerBuilding()];
if (window.playerState.currentScene.toLowerCase() === (building ? building.toLowerCase() : "")) {
const bob = this.app.root.findByName("Bob");
if (bob) bob.enabled = true;
}
};
Loading and Saving Game State
The game state is loaded from local storage at the start and saved back both periodically and at the end of game sessions. This ensures that the player’s progress is not lost and that the game can be resumed seamlessly.
GameStateController.prototype.loadGameState = function() {
window.gameStateLoaded = true;
const gameStateString = localStorage.getItem('gameState');
if (!gameStateString) return;
const gameState = JSON.parse(gameStateString);
window.bobState = gameState.bobState || window.bobState;
window.playerState = gameState.playerState || window.playerState;
this.app.scenes.changeScene(window.playerState.currentScene, (err, entity) => {
if (err) {
console.error(err);
return;
}
this.useGameState(window.playerState.scenePosition, entity);
});
};
GameStateController.prototype.useGameState = function(position, root) {
const player = root.findByName("player");
if (!window.playerState || !position) return;
player.rigidbody.teleport(new pc.Vec3(position.x, position.y, position.z));
};
GameStateController.prototype.saveGameState = function() {
const gameState = {
bobState: { ...window.bobState },
playerState: { ...window.playerState }
};
delete gameState.playerState.entryName;
const gameStateString = JSON.stringify(gameState);
localStorage.setItem('gameState', gameStateString);
console.log("Game state saved!");
};
Interaction Between Components
- Backend to Frontend: The backend communicates with the frontend via API.
- Frontend to Game: The frontend passes data to the game using local storage, ensuring that game state is consistent and up-to-date.
Future Considerations
Further developments will focus on integrating achievements more deeply within the game’s ecosystem, including their triggers, recording, and display within the social components of the game.
Conclusion
This system has proven effective for our needs, providing a robust framework for game state management. We are open to suggestions and hope this documentation assists others in their projects.