use serde::{Deserialize, Serialize};
use std::fs;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Level {
pub name: String,
pub width: usize,
pub height: usize,
pub tile_width: u32,
pub tile_height: u32,
pub tileset_path: String,
pub tiles: Vec<Vec<Option<u32>>>,
pub objects: Vec<LevelObject>,
pub properties: LevelProperties,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LevelObject {
pub object_type: String,
pub x: f32,
pub y: f32,
pub properties: std::collections::HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LevelProperties {
pub gravity: f32,
pub background_color: [u8; 4],
pub music: Option<String>,
}
impl Level {
pub fn new(name: &str, width: usize, height: usize, tile_width: u32, tile_height: u32) -> Self {
Self {
name: name.to_string(),
width,
height,
tile_width,
tile_height,
tileset_path: String::new(),
tiles: vec![vec![None; width]; height],
objects: Vec::new(),
properties: LevelProperties {
gravity: 980.0,
background_color: [0x10, 0x10, 0x10, 0xFF],
music: None,
},
}
}
pub fn load_json(path: &str) -> Result<Self, String> {
let content = fs::read_to_string(path)
.map_err(|e| format!("Falha ao ler arquivo: {}", e))?;
serde_json::from_str(&content)
.map_err(|e| format!("Falha ao parsear JSON: {}", e))
}
pub fn save_json(&self, path: &str) -> Result<(), String> {
let content = serde_json::to_string_pretty(self)
.map_err(|e| format!("Falha ao serializar: {}", e))?;
fs::write(path, content)
.map_err(|e| format!("Falha ao escrever arquivo: {}", e))
}
pub fn load_toml(path: &str) -> Result<Self, String> {
let content = fs::read_to_string(path)
.map_err(|e| format!("Falha ao ler arquivo: {}", e))?;
toml::from_str(&content)
.map_err(|e| format!("Falha ao parsear TOML: {}", e))
}
pub fn save_toml(&self, path: &str) -> Result<(), String> {
let content = toml::to_string_pretty(self)
.map_err(|e| format!("Falha ao serializar: {}", e))?;
fs::write(path, content)
.map_err(|e| format!("Falha ao escrever arquivo: {}", e))
}
pub fn set_tile(&mut self, x: usize, y: usize, tile_id: Option<u32>) {
if x < self.width && y < self.height {
self.tiles[y][x] = tile_id;
}
}
pub fn get_tile(&self, x: usize, y: usize) -> Option<u32> {
if x < self.width && y < self.height {
self.tiles[y][x]
} else {
None
}
}
pub fn add_object(&mut self, object: LevelObject) {
self.objects.push(object);
}
}
impl Default for Level {
fn default() -> Self {
Self::new("Untitled", 20, 15, 32, 32)
}
}