Skip to content

Commit

Permalink
Map loader fix final (#11)
Browse files Browse the repository at this point in the history
* Added map loader

* Added map loader

* Fixed Map Loader issues

* Changes to formatting and to failing builds

* Fixed cargo check

---------

Co-authored-by: HikariIT <alice.it.mail@gmail.com>
  • Loading branch information
JakubG-git and HikariIT authored May 10, 2024
1 parent 2344062 commit 7388f7b
Show file tree
Hide file tree
Showing 16 changed files with 204 additions and 21 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
target
Cargo.lock

.idea/
.idea
logs/
Binary file added assets/maps/map.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion bdi_game/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ simplelog = "0.12.2"

config = "0.14.0"
thiserror = "1.0.57"
image = "0.25.1"

serde = { version = "1.0", features = ["derive"]}

priority-queue = "2.0.0"
chrono = "0.4.37"

18 changes: 18 additions & 0 deletions bdi_game/src/asset_manager/asset_manager.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
pub struct AssetManager {}

impl AssetManager {
const ASSET_DIR: &'static str = "assets";

const MAP_SUBDIR: &'static str = "maps";
const MAP_EXTENSION: &'static str = "png";

pub fn get_map_path(map_name: &str) -> String {
format!(
"{}/{}/{}.{}",
Self::ASSET_DIR,
Self::MAP_SUBDIR,
map_name,
Self::MAP_EXTENSION
)
}
}
1 change: 1 addition & 0 deletions bdi_game/src/asset_manager/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod asset_manager;
7 changes: 6 additions & 1 deletion bdi_game/src/game/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use std::time::{Duration, Instant};
use crate::{
display::game_display::GameDisplay,
input::Input,
simulation::{simulation::Simulation, world_state::WorldState},
simulation::{simulation::Simulation, world_grid::WorldGrid, world_state::WorldState},
terrain_manager::map_loader::MapLoader,
};

use super::logging::init_logging;
Expand All @@ -18,11 +19,15 @@ impl<D: GameDisplay> Game<D> {
pub fn init(display: D) -> Game<D> {
init_logging();

let map = MapLoader::map_from_image("map");

Game {
display,
simulation: Simulation {
state: WorldState {},
grid: WorldGrid { data: vec![] },
},
// grid: WorldGrid::from_height_map(map),
input: Input {},
}
}
Expand Down
52 changes: 39 additions & 13 deletions bdi_game/src/game/logging.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,41 @@
use simplelog::{ColorChoice, Config, TermLogger, TerminalMode};
use log::LevelFilter;
use simplelog::{ColorChoice, CombinedLogger, Config, TermLogger, TerminalMode, WriteLogger};

pub fn init_logging() {
TermLogger::init(
log::LevelFilter::Info,
Config::default(),
TerminalMode::Stderr,
ColorChoice::Auto,
)
.or_else(|err| {
eprintln!("Failed to initialize logging system: {}", err);
Ok::<(), ()>(())
})
.unwrap();
pub(crate) fn init_logging() {
// Create log directory if it doesn't exist
match std::fs::create_dir("logs") {
Ok(_) => (),
Err(e) => {
if e.kind() != std::io::ErrorKind::AlreadyExists {
eprintln!("Error while creating log directory: {}", e);
std::process::exit(1);
}
}
}

let current_time_string = chrono::Local::now().format("%Y-%m-%d_%H-%M-%S").to_string();
let log_file_name = format!("logs/{}.log", current_time_string);
let log_file = match std::fs::File::create(log_file_name.clone()) {
Ok(file) => file,
Err(e) => {
eprintln!("Error while creating log file: {}", e);
std::process::exit(1);
}
};

match CombinedLogger::init(vec![
TermLogger::new(
LevelFilter::Warn,
Config::default(),
TerminalMode::Mixed,
ColorChoice::Auto,
),
WriteLogger::new(LevelFilter::Debug, Config::default(), log_file),
]) {
Ok(_) => (),
Err(e) => {
eprintln!("Error while initializing logger: {}", e);
std::process::exit(1);
}
}
}
2 changes: 2 additions & 0 deletions bdi_game/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pub mod algorithms;
mod asset_manager;
pub mod display;
pub mod game;
mod input;
mod simulation;
pub mod terrain_manager;
7 changes: 6 additions & 1 deletion bdi_game/src/simulation/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pub struct Grid<T>
where
T: Default + Clone,
{
data: Vec<Vec<GridCell<T>>>,
pub(crate) data: Vec<Vec<GridCell<T>>>,
}

impl<T> Grid<T>
Expand Down Expand Up @@ -34,6 +34,11 @@ where
&self.data[y][x]
}

pub fn set_cell_data(&mut self, point: &GridPoint, data: T) {
let (x, y) = Self::get_cell_coord(point);
self.data[y][x] = GridCell { data };
}

fn get_cell_coord_unchecked(point: &GridPoint) -> (i64, i64) {
let x = (point.i + point.j / 2) as i64;
let y = point.j as i64;
Expand Down
2 changes: 2 additions & 0 deletions bdi_game/src/simulation/simulation.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use super::world_grid::WorldGrid;
use super::world_state::WorldState;

pub struct Simulation {
pub state: WorldState,
pub grid: WorldGrid,
}

impl Simulation {
Expand Down
36 changes: 33 additions & 3 deletions bdi_game/src/simulation/world_grid.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
use crate::simulation::grid::Grid;
use crate::simulation::grid::{Grid, GridPoint};
use crate::terrain_manager::sampler::Sampler2D;
use image::GrayImage;

struct WorldCellData {}
#[derive(Default, Clone)]
pub(crate) struct WorldCellData {
elevation: i32,
// ...
}

type WorldGrid = Grid<WorldCellData>;
pub(crate) type WorldGrid = Grid<WorldCellData>;

/*
impl WorldGrid {
pub fn from_height_map(height_map: GrayImage) -> WorldGrid {
let mut grid = WorldGrid::new(height_map.width() as usize);
let mut offset: i32 = 0;
let map_sampler = Sampler2D::new(height_map.clone(), height_map.width() as usize);
for r in 0..height_map.height() {
for q in -offset..height_map.width() as i32 - offset {
let elevation = map_sampler.sample_hexagonal_axial(q, r as i32);
let point = GridPoint::new(q, r as i32);
grid.set_cell_data(&point, WorldCellData { elevation });
}
if r % 2 == 0 {
offset += 1;
}
}
grid
}
}
*/
7 changes: 7 additions & 0 deletions bdi_game/src/terrain_manager/map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use image::GrayImage;

pub struct Map {
pub side_len: usize,
pub height_map: GrayImage,
pub height_modifiers: GrayImage,
}
36 changes: 36 additions & 0 deletions bdi_game/src/terrain_manager/map_loader.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use crate::asset_manager::asset_manager::AssetManager;
use image::io::Reader as ImageReader;
use image::GrayImage;
use log::{debug, info};

pub struct MapLoader {
map_asset_path: String,
}

impl MapLoader {
pub fn map_from_image(map_name: &str) -> GrayImage {
let map_path = AssetManager::get_map_path(map_name);

let img = match ImageReader::open(map_path) {
Ok(img) => img,
Err(e) => {
eprintln!("Error while loading map from file: {}", e);
return GrayImage::new(0, 0);
}
};

let img = match img.decode() {
Ok(img) => img,
Err(e) => {
eprintln!("Error while decoding map format: {}", e);
return GrayImage::new(0, 0);
}
};

info!("Map '{}' loaded successfully!", map_name);
debug!("Map format: {:?}", img.color());
debug!("Map dimensions: {}x{}", img.width(), img.height());

return img.into_luma8();
}
}
4 changes: 4 additions & 0 deletions bdi_game/src/terrain_manager/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mod map;
pub mod map_loader;
pub mod sampler;
mod world_object;
44 changes: 44 additions & 0 deletions bdi_game/src/terrain_manager/sampler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use image::GrayImage;

pub struct Sampler2D {
height_map: GrayImage,
side_len: usize,
}

impl Sampler2D {
pub fn new(height_map: GrayImage, side_len: usize) -> Sampler2D {
Sampler2D {
height_map,
side_len,
}
}

pub fn sample_hexagonal_axial(&self, q: i32, r: i32) -> i32 {
let scale = self.height_map.width() as f32 / self.side_len as f32;

let offset_q_x = scale * q as f32;
let offset_q_y = 0f32;

let offset_r_x = scale * 0.5 * r as f32;
let offset_r_y = scale * 3.0f32.sqrt() / 2.0 * r as f32;

let x = offset_q_x + offset_r_x;
let y = offset_q_y + offset_r_y;

// Linear interpolation
let x0 = x.floor() as u32;
let x1 = x.ceil() as u32;
let y0 = y.floor() as u32;
let y1 = y.ceil() as u32;

let x0y0 = self.height_map.get_pixel(x0, y0)[0] as f32;
let x1y0 = self.height_map.get_pixel(x1, y0)[0] as f32;
let x0y1 = self.height_map.get_pixel(x0, y1)[0] as f32;
let x1y1 = self.height_map.get_pixel(x1, y1)[0] as f32;

let x0y = x0y0 + (x0y1 - x0y0) * (y - y0 as f32);
let x1y = x1y0 + (x1y1 - x1y0) * (y - y0 as f32);

(x0y + (x1y - x0y) * (x - x0 as f32)) as i32
}
}
1 change: 1 addition & 0 deletions bdi_game/src/terrain_manager/world_object.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

0 comments on commit 7388f7b

Please sign in to comment.