diff --git a/crates/border-wars/assets/tiles/forest.png b/crates/border-wars/assets/tiles/forest.png new file mode 100644 index 0000000..d902377 Binary files /dev/null and b/crates/border-wars/assets/tiles/forest.png differ diff --git a/crates/border-wars/assets/tiles/grass.png b/crates/border-wars/assets/tiles/grass.png new file mode 100644 index 0000000..1969729 Binary files /dev/null and b/crates/border-wars/assets/tiles/grass.png differ diff --git a/crates/border-wars/assets/tiles/hill.png b/crates/border-wars/assets/tiles/hill.png new file mode 100644 index 0000000..0ac3d46 Binary files /dev/null and b/crates/border-wars/assets/tiles/hill.png differ diff --git a/crates/border-wars/src/main.rs b/crates/border-wars/src/main.rs index 909ac0a..b02c626 100644 --- a/crates/border-wars/src/main.rs +++ b/crates/border-wars/src/main.rs @@ -2,12 +2,14 @@ use bevy::prelude::*; use border_wars::camera::CameraPlugin; +use border_wars::map::renderer::RendererPlugin; use border_wars::scenes::ScenesPlugin; fn main() { App::new() .add_plugins(DefaultPlugins) .add_plugins(ScenesPlugin) + .add_plugins(RendererPlugin) .add_plugins(CameraPlugin) .run(); } diff --git a/crates/border-wars/src/map/mod.rs b/crates/border-wars/src/map/mod.rs index 5265d18..73d0c06 100644 --- a/crates/border-wars/src/map/mod.rs +++ b/crates/border-wars/src/map/mod.rs @@ -2,6 +2,7 @@ pub mod generation; pub mod hex; +pub mod renderer; use bevy::prelude::*; diff --git a/crates/border-wars/src/map/renderer.rs b/crates/border-wars/src/map/renderer.rs new file mode 100644 index 0000000..ca79ab6 --- /dev/null +++ b/crates/border-wars/src/map/renderer.rs @@ -0,0 +1,110 @@ +//! All functions related to the rendering of the map. + +use bevy::prelude::*; +use bevy::sprite::Anchor; + +use crate::map::{Tile, TilePosition}; + +/// A plugin to render the map. +pub struct RendererPlugin; + +impl Plugin for RendererPlugin { + fn build(&self, app: &mut App) { + app.add_systems(Startup, init_resources_for_rendering) + .add_systems( + Update, + render_map.run_if(in_state(crate::CurrentScene::Game)), + ); + } +} + +/// The gap between the center of the tiles in the map. +#[derive(Resource)] +struct TilesGap(Vec2); + +/// The size of the tiles in the map. +#[derive(Resource, Clone, Copy)] +struct TilesSize(Vec2); + +impl Tile { + /// Returns the handle of the image of the tile. + fn get_texture(&self, asset_server: &AssetServer) -> Handle { + match self { + Self::Grass => asset_server.load("tiles/grass.png"), + Self::Forest => asset_server.load("tiles/forest.png"), + Self::Hill => asset_server.load("tiles/hill.png"), + } + } + + /// Returns the size of the image of the tile. + /// + /// TODO: we are currently using temporary images that will modify + /// this function in the future. + const fn get_image_size(&self) -> Vec2 { + match self { + Self::Grass => Vec2 { + x: 1250.0, + y: 1000.0, + }, + Self::Forest => Vec2 { + x: 1250.0, + y: 1000.0, + }, + Self::Hill => Vec2 { + x: 1250.0, + y: 1300.0, + }, + } + } +} + +/// Init resources related to the rendering of the map. +fn init_resources_for_rendering(mut commands: Commands) { + commands.insert_resource(TilesGap(Vec2 { x: 70., y: 40. })); + commands.insert_resource(TilesSize(Vec2 { x: 125., y: 100. })) +} + +/// Renders the map. +fn render_map( + query: Query<(Entity, &TilePosition, &Tile), Changed>, + mut commands: Commands, + asset_server: Res, + tiles_gap: Res, + tiles_size: Res, +) { + for (entity, position, tile) in query.iter() { + let texture = tile.get_texture(&asset_server); + + let translation_2d = tiles_gap.0 * position.to_pixel_coordinates(); + let translation = Vec3::new( + translation_2d.x, + translation_2d.y, + z_position_from_y(translation_2d.y), + ); + + let scale_2d = tiles_size.0 / tile.get_image_size(); + + // the y scale is the same as the x scale to keep the aspect ratio. + let scale = Vec3::new(scale_2d.x, scale_2d.x, 1.0); + + commands.entity(entity).insert(SpriteBundle { + sprite: Sprite { + anchor: Anchor::BottomLeft, + ..default() + }, + texture, + transform: Transform { + translation, + scale, + ..Default::default() + }, + ..default() + }); + } +} + +/// A simple sigmoid function to convert y position to z position. +/// The return value is between 0 and 1. +fn z_position_from_y(y: f32) -> f32 { + -1.0 / (1.0 + (-y * 110_f64.powi(-3) as f32).exp()) +}