131 lines
3.7 KiB
Rust
131 lines
3.7 KiB
Rust
use crate::{
|
|
components::tile::{Grid, Tile, TileState},
|
|
config::GameConfig,
|
|
states::AppState,
|
|
};
|
|
use bevy::prelude::*;
|
|
use bevy_aseprite_ultra::prelude::AseSlice;
|
|
|
|
pub const TILE_SIZE: f32 = 32.0;
|
|
|
|
pub fn grid_start_x(grid_width: u32) -> f32 {
|
|
-(grid_width as f32 * TILE_SIZE) / 2.0 + TILE_SIZE / 2.0
|
|
}
|
|
pub fn grid_start_y(grid_height: u32) -> f32 {
|
|
-(grid_height as f32 * TILE_SIZE) / 2.0 + TILE_SIZE / 2.0
|
|
}
|
|
|
|
pub struct GridPlugin;
|
|
|
|
impl Plugin for GridPlugin {
|
|
fn build(&self, app: &mut App) {
|
|
app.add_systems(OnEnter(AppState::GameScreen), setup);
|
|
app.add_systems(OnExit(AppState::GameScreen), cleanup);
|
|
|
|
app.add_systems(
|
|
Update,
|
|
update_tile_colors.run_if(in_state(AppState::GameScreen)),
|
|
);
|
|
}
|
|
}
|
|
|
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>, config: Res<GameConfig>) {
|
|
let grid_width = config.grid_width;
|
|
let grid_height = config.grid_height;
|
|
let mut tiles = Vec::with_capacity(grid_width as usize);
|
|
|
|
for x in 0..grid_width {
|
|
let mut column = Vec::with_capacity(grid_height as usize);
|
|
|
|
for y in 0..grid_height {
|
|
let tile_entity = commands
|
|
.spawn((
|
|
Tile { x, y },
|
|
TileState::Unclaimed,
|
|
AseSlice {
|
|
name: "Unclaimed".into(),
|
|
aseprite: asset_server.load("tiles/tile-unclaimed.aseprite"),
|
|
},
|
|
Sprite::default(),
|
|
Transform::from_translation(grid_to_world_coords(
|
|
x,
|
|
y,
|
|
None,
|
|
grid_width,
|
|
grid_height,
|
|
)),
|
|
))
|
|
.id();
|
|
column.push(tile_entity);
|
|
}
|
|
tiles.push(column);
|
|
}
|
|
|
|
commands.insert_resource(Grid {
|
|
width: grid_width,
|
|
height: grid_height,
|
|
tiles,
|
|
});
|
|
}
|
|
|
|
fn cleanup(mut commands: Commands, tile_query: Query<Entity, With<Tile>>) {
|
|
for tile_entity in tile_query.iter() {
|
|
commands.entity(tile_entity).despawn();
|
|
}
|
|
commands.remove_resource::<Grid>();
|
|
}
|
|
|
|
fn update_tile_colors(
|
|
mut query: Query<(&TileState, &mut AseSlice)>,
|
|
asset_server: Res<AssetServer>,
|
|
) {
|
|
for (state, mut slice) in &mut query {
|
|
slice.name = match state {
|
|
TileState::Unclaimed => "Unclaimed",
|
|
TileState::Empty => "Empty",
|
|
TileState::Occupied => "Occupied",
|
|
}
|
|
.into();
|
|
|
|
slice.aseprite = match state {
|
|
TileState::Unclaimed => asset_server.load("tiles/tile-unclaimed.aseprite"),
|
|
TileState::Empty => asset_server.load("tiles/tile-empty.aseprite"),
|
|
TileState::Occupied => asset_server.load("tiles/tile-occupied.aseprite"),
|
|
};
|
|
}
|
|
}
|
|
|
|
pub fn world_to_grid_coords(world_pos: Vec3, grid_width: u32, grid_height: u32) -> (u32, u32) {
|
|
let start_x = grid_start_x(grid_width);
|
|
let start_y = grid_start_y(grid_height);
|
|
|
|
let x = ((world_pos.x - start_x + TILE_SIZE / 2.0) / TILE_SIZE).floor();
|
|
let y = ((world_pos.y - start_y + TILE_SIZE / 2.0) / TILE_SIZE).floor();
|
|
|
|
let mut x_u32 = x as u32;
|
|
let mut y_u32 = y as u32;
|
|
|
|
if x_u32 >= grid_width {
|
|
x_u32 = grid_width - 1;
|
|
}
|
|
if y_u32 >= grid_height {
|
|
y_u32 = grid_height - 1;
|
|
}
|
|
|
|
(x_u32, y_u32)
|
|
}
|
|
|
|
pub fn grid_to_world_coords(
|
|
grid_x: u32,
|
|
grid_y: u32,
|
|
z: Option<f32>,
|
|
grid_width: u32,
|
|
grid_height: u32,
|
|
) -> Vec3 {
|
|
Vec3::new(
|
|
grid_start_x(grid_width) + grid_x as f32 * TILE_SIZE,
|
|
grid_start_y(grid_height) + grid_y as f32 * TILE_SIZE,
|
|
z.unwrap_or(0.0),
|
|
)
|
|
}
|