| Crates.io | shards_of_aether |
| lib.rs | shards_of_aether |
| version | 0.1.3 |
| created_at | 2025-11-12 03:30:14.125622+00 |
| updated_at | 2025-11-12 04:28:19.229175+00 |
| description | A text-based adventure RPG built in Rust. |
| homepage | |
| repository | https://github.com/SafiaNassiri/ShardsOfAether-RustPoject |
| max_upload_size | |
| id | 1928748 |
| size | 66,609 |
A text-based adventure RPG written in Rust, featuring exploration, turn-based combat, and dynamic world progression through multiple JSON-defined maps.
Shards of Aether is a command-line adventure game where the player explores interconnected levels, battles enemies, collects relics, and uncovers the fate of a fractured world.
Each area is defined in structured JSON files that load dynamically, allowing smooth transitions between levels while preserving the player’s progress and inventory. The gameplay emphasizes strategic combat choices, exploration, and resource management.
JSON-Based World System
Every level (map) is defined as a JSON file containing rooms, items, exits, and enemies. The engine dynamically loads and unloads these maps when transitioning between levels.
Rooms have coordinates (x, y) that allow for future map rendering and procedural expansion.
Turn-Based Combat System
Engage enemies using simple text commands:
attack / heal / defend / run
The system is turn-driven — enemies only attack after a valid player move, preventing damage from typos or invalid input.
Each victory grants XP, scaling with enemy strength, and lets the player progress further into the world.
Command Parsing & Input Handling
The command system parses raw text input into structured enums like Command::Go, Command::Use, Command::Look, etc.
This structure allows easily adding new commands or interactions (e.g. puzzles, special actions).
Player Progress & Inventory System
The player’s data — health, inventory, XP, and current room — is stored persistently between levels.
Items are typed (Healing, Weapon, Quest, Utility) to enable flexible in-game effects.
Level Transitions via JSON Loading
When entering certain rooms (like “Sanctum”), the game seamlessly loads the next map file and repositions the player.
Player inventory, health, and XP remain intact across transitions.
Dynamic Map Rendering
The world map is generated by reading the x and y coordinates of each room, then printing a simplified ASCII minimap showing where the player currently is.
This approach uses computed bounds (min_x, max_x, etc.) to scale automatically for any map layout.
You are standing in a grand hall with a glittering chandelier.
Exits: north → library, east → kitchen
> go north
You move north.
🧍 You have entered: river_bridge
river_bridge
A fragile wooden bridge spans the river. You hear rustling in the bushes.
Exits: west, south
⚠️ You sense danger nearby... (Goblin)
⚔️ A wild Goblin appears!
⚔️ You encounter a Goblin!
A sneaky little creature with a rusty dagger.
❤️ Your HP: 4 | 💀 Goblin’s HP: 20
Choose an action (attack / heal / defend / run):
> defend
🛡️ You brace yourself!
The Goblin attacks you for 4 damage!
If your HP reaches 0, the game displays a death ASCII art screen and exits dramatically:
💀 You have been defeated!
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⠀⠀⠀⣶⡆⠀⣰⣿⠇⣾⡿⠛⠉⠁
⠀⣠⣴⠾⠿⠿⠀⢀⣾⣿⣆⣀⣸⣿⣷⣾⣿⡿⢸⣿⠟⢓⠀⠀
⣴⡟⠁⣀⣠⣤⠀⣼⣿⠾⣿⣻⣿⠃⠙⢫⣿⠃⣿⡿⠟⠛⠁⠀
⢿⣝⣻⣿⡿⠋⠾⠟⠁⠀⠹⠟⠛⠀⠀⠈⠉⠀⠉⠀⠀⠀⠀⠀
⠀⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⡀⠀⠀⣀⢀⣠⣤⣴⣤⣄⠀
⠀⠀⠀⠀⣀⣤⣤⢶⣤⠀⠀⢀⣴⢃⣿⠟⠋⢹⣿⣣⣴⡿⠋⠀
⠀⠀⣰⣾⠟⠉⣿⡜⣿⡆⣴⡿⠁⣼⡿⠛⢃⣾⡿⠋⢻⣇⠀⠀
⠀⠐⣿⡁⢀⣠⣿⡇⢹⣿⡿⠁⢠⣿⠷⠟⠻⠟⠀⠀⠈⠛⠀⠀
⠀⠀⠙⠻⠿⠟⠋⠀⠀⠙⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Game Over. Thanks for playing Adventurer!
Another shall be sent to complete what you have failed in.
Each level file (level1.json, sanctum.json, etc.) follows this structure:
{
"rooms": {
"hall": {
"id": "hall",
"description": "You are standing in a grand hall with a glittering chandelier.",
"items": [
{
"name": "rusty key",
"description": "An old, rusty key. I wonder what it opens."
}
],
"exits": { "north": "library", "east": "kitchen" },
"x": 0,
"y": 0
}
}
}
The engine deserializes these into Room structs using serde:
#[derive(Serialize, Deserialize, Clone)]
pub struct Room {
pub id: String,
pub description: String,
#[serde(default)] pub items: Vec<Item>,
#[serde(default)] pub exits: HashMap<String, String>,
#[serde(default)] pub enemy: Option<String>,
#[serde(default)] pub x: i32,
#[serde(default)] pub y: i32,
}
This makes missing fields safe by using #[serde(default)], avoiding crashes from incomplete JSON.
git clone https://github.com/yourusername/shards_of_aether.git
cd shards_of_aether
cargo build
cargo run
go north
look
inventory
use potion
save
load
quit
This project is licensed under the MIT License.