-
Notifications
You must be signed in to change notification settings - Fork 0
Using the Engine
Creating a New Project: Instructions for setting up a new game project using the engine.
The SpriteSparkEngine includes a powerful and flexible layer system, designed to manage different aspects of a game’s architecture efficiently. Below is an explanation of how the layer system works and how it can be utilized within your projects.
In SpriteSparkEngine, a Layer represents a distinct part of the game or application, such as gameplay, UI, or background processes. Each layer can manage its own set of entities, systems, and logic independently. This modular approach allows for better organization and separation of concerns within your game code.
Layers are defined by creating a class that inherits from the Layer base class. Within this custom class, you can override methods like OnInit, OnUpdate, and OnRender to implement the specific functionality of the layer.
For example:
class TestLayer : public Layer {
public:
TestLayer() : Layer("Test") {} // The layer is named "Test" for debugging purposes.
void OnInit(Camera& camera) override {
// Initialization code here
}
void OnUpdate(float deltaTime, Camera& camera) override {
// Update code here
}
void OnRender(FrameInfo& frameInfo) override {
// Render code here
}
};One useful feature of the layer system is the ability to name each layer. This is particularly helpful for debugging purposes, allowing developers to easily identify and manage different layers during the development process. In the example above, the layer is named "Test" by passing this string to the Layer constructor.
Layers can be added to the application using the PushLayer function. This function takes a pointer to a new instance of your custom layer class and adds it to the application’s layer stack.
For example:
TestApp() {
PushLayer(new TestLayer());
}-
OnInit(Camera& camera): This function is called when the layer is first initialized. It’s used to set up resources, load assets, and prepare the layer for use.
-
OnUpdate(float deltaTime, Camera& camera): This function is called every frame. It’s where the layer’s game logic is processed, such as handling input, updating entities, and managing physics.
-
OnRender(FrameInfo& frameInfo): This function is used to render the layer’s content to the screen. It’s called after
OnUpdateand is responsible for drawing sprites, UI elements, and other visuals.
The layer system in SpriteSparkEngine provides a structured way to manage different parts of your game or application. By defining custom layers, naming them for easy debugging, and adding them to the application with PushLayer, you can build complex, organized, and maintainable game architectures. Each layer independently handles initialization, updates, and rendering, making the engine both powerful and flexible for developers.
SpriteSparkEngine utilizes an Entity Component System (ECS) architecture to manage game entities and their behaviors. The ECS is designed for high performance and modularity, making it easy to extend the engine with new features and optimizations.
-
Entity: An entity is a unique identifier that can have multiple components attached to it. Entities are lightweight and represent objects in your game, such as players, enemies, or projectiles.
-
Component: A component is a plain data structure that holds information. Components are attached to entities to give them specific attributes or behaviors, like position, velocity, or health.
-
System: A system processes entities that have specific components. Systems contain the game logic, such as updating movement, handling collisions, or rendering sprites.
Entities in SpriteSparkEngine are created using the EntityManager. Here's an example of how to create an entity and add components to it:
EntityManager entityManager;
// Create an entity
Entity player = entityManager.createEntity();
// Add components to the entity
entityManager.addComponent(player, Transform{ {240.0f, 3194.0f}, {1.0f, 1.0f}, 0.0f });
entityManager.addComponent(player, RigidBody{});
entityManager.addComponent(player, Collision{ 0.0f, 0.0f, 16.0f, 32.0f, CollisionType::DYNAMIC });
entityManager.addComponent(player, Sprite{ playerSprite, {0.0f, 0.0f, 16.0f, 32.0f} });Systems are responsible for operating on entities that possess certain components. Here’s how you can create and update a system:
class PlayerMovementSystem : public System<PlayerMovementSystem> {
public:
void update(EntityManager& entities, Camera& camera, float dt) {
entities.each<Transform, RigidBody, Player>([&](Entity entity, Transform& transform, RigidBody& rigidBody, Player& player) {
// Movement logic here
});
}
};
To use the system, you instantiate it and call its update function in your game loop:
PlayerMovementSystem movementSystem;
movementSystem.update(entityManager, camera, deltaTime);Custom components can be created by defining simple data structures. For example, if you wanted to add a health component:
struct Health {
int currentHealth;
int maxHealth;
Health(int maxHealth) : currentHealth(maxHealth), maxHealth(maxHealth) {}
};You can then add this component to any entity:
entityManager.addComponent(player, Health{100});Custom systems are created by inheriting from the System class template. Here’s an example of a system that could handle health updates:
class HealthSystem : public System<HealthSystem> {
public:
void update(EntityManager& entities, float dt) {
entities.each<Health>([&](Entity entity, Health& health) {
if (health.currentHealth <= 0) {
// Handle entity death or respawn
}
});
}
};This system would iterate over all entities with a Health component and apply the necessary logic.
The ECS architecture in SpriteSparkEngine is designed to be intuitive and powerful. By separating data (components) from behavior (systems), the engine allows for easy management of game entities and logic. Developers can extend the engine by creating custom components and systems, making SpriteSparkEngine a flexible tool for various game development needs.
In SpriteSparkEngine, textures are managed using Vulkan and can be easily loaded and applied to entities using the Sprite component. Below is a step-by-step guide on how to load textures and use them with the Sprite component.
Textures in SpriteSparkEngine are loaded using the GlobalLoader class, which handles the Vulkan-specific operations required to create and manage textures. Here’s how you can load a texture:
std::unique_ptr<VulkanTexture> playerSprite = GlobalLoader::LoadTexture("Textures/vp_sptsht_player.png");This command loads a texture from the specified file path and returns a std::unique_ptr to a VulkanTexture object. The texture is now ready to be used in the engine.
Once the texture is loaded, you can create an entity and assign the Sprite component to it. The Sprite component requires a reference to the texture and a Rect that defines the portion of the texture to be used.
Entity player = entityManager.createEntity();
entityManager.addComponent(player, Sprite{ playerSprite, {0.0f, 0.0f, 16.0f, 32.0f} });In this example:
- Entity Creation: The entity manager creates a new entity.
- Sprite Component: The Sprite component is added to the entity, specifying the texture and the area (defined by the Rect) to be used from the texture.
If you are using a tileset, you can specify different portions of the texture for different entities. The Rect defines the coordinates and dimensions of the sprite within the texture:
Rect rec = { 0.0f, 0.0f, 16.0f, 32.0f };
entityManager.addComponent(player, Sprite{ playerSprite, rec });
or
entityManager.addComponent(player, Sprite{ playerSprite, {0.0f, 0.0f, 16.0f, 32.0f} });This allows you to use a single texture file (a spritesheet) for multiple entities, each displaying a different part of the texture.
SpriteSparkEngine also provides functionality to load sprites directly from a tileset JSON file. This is handled by the GlobalLoader::LoadSprites function, which automatically creates entities and sets up their Sprite components based on the tileset data.
globalloader::LoadSprites(entityManager, 3, tilemap, "Levels/vp_ts_metroidlevel.json", "Levels/vp_lv_metroidlevel.json");This method reads the tileset and map data from JSON files and creates the necessary entities with the appropriate sprites.
Loading and applying textures in SpriteSparkEngine is straightforward with the help of the GlobalLoader and Sprite components. You can load textures from files, set them to entities, and even manage complex tilesets with ease.
SpriteSparkEngine provides a straightforward way to load and manage sound files using the Sound class. This class utilizes OpenAL for audio processing, supporting various audio formats such as WAV, FLAC, and MP3. Below is a guide on how to load and use sounds in your projects.
To load a sound, you can create an instance of the Sound class and pass the file path of the audio file to its constructor. The Sound class handles the loading and buffering of the audio file automatically.
Sound backgroundMusic("Sound/Theme of Samus Aran, Space Warrior - Super Smash Bros. Ultimate.mp3");In this example, the sound file is loaded from the specified file path. The engine automatically detects the file format and processes it accordingly.
The Sound class supports the following audio formats:
- WAV
- FLAC
- MP3
These formats are handled internally using the dr_wav, dr_flac, and dr_mp3 libraries.
Once a sound is loaded, you can control its playback using several methods provided by the Sound class.
backgroundMusic.play(true); // Play the sound and loop it
backgroundMusic.setVolume(0.5f); // Set volume to 50%
if (Input::IsKeyPressed(Key::P)) {
backgroundMusic.pause(); // Pause the sound
}
if (Input::IsKeyPressed(Key::S)) {
backgroundMusic.stop(); // Stop the sound
}- play(bool loop = false): Plays the sound. If loop is set to true, the sound will loop continuously.
- pause(): Pauses the sound at the current position.
- stop(): Stops the sound and resets its position to the beginning.
- setVolume(float volume): Adjusts the volume of the sound. The volume is a float value between 0.0 (mute) and 1.0 (full volume).
You can check if a sound is currently playing using the isPlaying() method:
if (backgroundMusic.isPlaying()) {
// The sound is currently playing
}You can set or change the audio file for a Sound object at any time using the setFilepath method:
backgroundMusic.setFilepath("Sound/another_audio_file.wav");This will load the new audio file and prepare it for playback.
SpriteSparkEngine’s sound system makes it easy to incorporate audio into your game. By loading sounds through the Sound class and using its various playback controls, you can add dynamic and immersive audio experiences to your game.
- Loading Sounds: Use the Sound class to load audio files in formats like WAV, FLAC, and MP3.
- Controlling Playback: Play, pause, stop, and adjust the volume of sounds.
- Changing Audio Files: Easily switch the audio file for a Sound object during runtime.
This guide should help you effectively manage and utilize sounds within SpriteSparkEngine.
The input system in SpriteSparkEngine allows you to easily handle keyboard and mouse inputs within your game. This system is designed to detect key presses, key releases, mouse button actions, and mouse movement.
- Key Presses: Detect when a specific key is pressed down.
- Key Releases: Detect when a specific key is released.
- Mouse Button Actions: Detect when a mouse button is pressed or released.
- Mouse Movement: Track the current position of the mouse on the screen.
You can check if a specific key is pressed or released using the Input class. The Input class provides static methods that can be called to check the state of keys.
if (Input::IsKeyPressed(Key::W)) {
// Move the player up
}
if (Input::IsKeyPressed(Key::A)) {
// Move the player left
}
if (Input::IsKeyPressed(Key::D)) {
// Move the player right
}In this example, the game checks if the "W", "A", or "D" keys are pressed to move the player character accordingly.
if (Input::IsKeyReleased(Key::Escape)) {
// Pause the game or open the menu
}You can use IsKeyReleased to trigger an action when a key is released, such as opening a menu when the "Escape" key is released.
The input system also allows you to detect mouse button presses, releases, and track the mouse position.
if (Input::IsMouseButtonPressed(MouseButton::Left)) {
// Fire a weapon or select an object
}This example checks if the left mouse button is pressed, which could be used to fire a weapon or select an object in the game.
float mouseX = Input::GetMouseX();
float mouseY = Input::GetMouseY();The GetMouseX and GetMouseY methods provide the current position of the mouse cursor, which can be used for aiming, navigating menus, or other interactions.
The input system in SpriteSparkEngine is a powerful tool for handling user interactions. By using the provided methods, you can easily detect key presses, key releases, and mouse actions, allowing you to create responsive and interactive gameplay experiences.
- Key Presses and Releases: Use IsKeyPressed and sKeyReleased to detect keyboard input.
- Mouse Input: Use IsMouseButtonPressed and GetMouseX, GetMouseY to handle mouse interactions.
This guide should help you effectively implement input handling in your SpriteSparkEngine projects.
SpriteSparkEngine features a robust logging system that helps developers track the behavior of their application and engine components. The logging system provides various log levels and is designed to be easy to use while offering customization for output formatting and colors.
The logging system supports the following log levels:
- Trace: Detailed information, typically of interest only when diagnosing problems.
- Debug: Information useful to developers for debugging the application.
- Info: Informational messages that highlight the progress of the application at a high level.
- Warn: Potentially harmful situations that are not immediately problematic but could lead to issues.
- Error: Error events that might still allow the application to continue running.
- Critical: Severe error events that will presumably lead the application to abort.
Logging in SpriteSparkEngine is done using pre-defined macros that correspond to the different log levels. These macros make it easy to log messages from anywhere in your application or the engine.
SP_CORE_INFO("This is an informational message from the engine.");
SP_INFO("This is an informational message from the application.");In this example:
- SP_CORE_INFO is used for logging engine-related information.
- SP_INFO is used for logging application-related information.
SP_CORE_ERROR("An error occurred: ", errorMessage);
SP_ERROR("Application encountered an error: ", errorCode);This logs error messages with context, helping to diagnose issues.
The logging system automatically formats messages with timestamps and colors based on the log level. For example:
- Trace messages are displayed in white.
- Debug messages are displayed in cyan.
- Info messages are displayed in green.
- Warning messages are displayed in yellow.
- Error messages are displayed in red.
- Critical messages are displayed in magenta.

This makes it easier to identify the severity of messages at a glance.
The log system is designed to be customizable. For example, you can change how messages are formatted or adjust the colors used for different log levels by modifying the Log class methods such as SetConsoleColor and ResetConsoleColor.
To prevent logging in production builds, you can use the DIST preprocessor definition. When DIST is defined, all logging functions are disabled to optimize performance and avoid revealing internal information.
#ifdef DIST
#define SP_CORE_TRACE
#define SP_CORE_DEBUG
#define SP_CORE_INFO
#define SP_CORE_WARN
#define SP_CORE_ERROR
#define SP_CORE_CRITICAL
#define SP_TRACE
#define SP_DEBUG
#define SP_INFO
#define SP_WARN
#define SP_ERROR
#define SP_CRITICAL
#endifBy defining DIST, all logging macros are effectively disabled, ensuring that no log messages are output in your final build.
The logging system in SpriteSparkEngine is a vital tool for developers, offering detailed logging at various levels to help with debugging and monitoring the application. The system is easy to use, with simple macros for different log levels, and provides customizable output for better readability and analysis.
- Log Levels: Trace, Debug, Info, Warn, Error, Critical.
-
Logging: Use
SP_CORE_*for engine logs andSP_*for application logs. - Customization: Customize log colors and formatting as needed.
-
Distribution Builds: Disable logging in production with the
DISTpreprocessor definition.
This guide should help you effectively use the logging system in your SpriteSparkEngine projects.