refactor(grid): make it a Plugin

This commit is contained in:
Kristofers Solo 2024-09-22 14:32:32 +03:00
parent f11b701ec3
commit 0ee94c826a
8 changed files with 36 additions and 243 deletions

View File

@ -1,98 +0,0 @@
use super::tile::{draw_walls, spawn_tiles};
use bevy::{
color::palettes::css::{BLACK, DARK_CYAN},
ecs::{system::RunSystemOnce, world::Command},
prelude::*,
};
use bevy_prototype_lyon::{
draw::{Fill, Stroke},
entity::ShapeBundle,
geometry::GeometryBuilder,
plugin::ShapePlugin,
prelude::RegularPolygon,
shapes::RegularPolygonFeature,
};
use hexx::{HexLayout, HexOrientation};
use std::time::Duration;
pub(super) fn plugin(app: &mut App) {
app.insert_resource(Msaa::Sample4);
app.add_plugins(ShapePlugin);
}
pub fn spawn_grid(world: &mut World) {
world.init_resource::<Grid>();
world.init_resource::<RotationTimer>();
GridSettings::default().apply(world);
}
#[derive(Debug, Reflect, Resource, Deref, DerefMut)]
#[reflect(Resource)]
struct RotationTimer(Timer);
impl Default for RotationTimer {
fn default() -> Self {
Self(Timer::new(Duration::from_secs_f32(0.5), TimerMode::Once))
}
}
#[derive(Debug, Reflect)]
pub struct GridSettings {
pub radius: u32,
}
impl Default for GridSettings {
fn default() -> Self {
Self { radius: 10 }
}
}
impl Command for GridSettings {
fn apply(self, world: &mut World) {
// world.run_system_once_with(self, spawn_tiles);
// world.run_system_once(draw_walls);
world.run_system_once(draw);
}
}
fn draw(mut commands: Commands) {
let shape = RegularPolygon {
sides: 6,
feature: RegularPolygonFeature::Radius(200.),
..default()
};
commands.spawn((
Name::new("Hexagon"),
ShapeBundle {
path: GeometryBuilder::build_as(&shape),
..default()
},
Fill::color(DARK_CYAN),
Stroke::new(BLACK, 10.),
));
}
#[derive(Debug, Reflect, Resource)]
#[reflect(Resource)]
pub struct Grid {
pub layout: HexLayout,
}
impl Default for Grid {
fn default() -> Self {
Self::new(20., HexOrientation::Flat)
}
}
impl Grid {
pub fn new(hex_size: f32, orientation: HexOrientation) -> Self {
Self {
layout: HexLayout {
hex_size: Vec2::splat(hex_size),
orientation,
..default()
},
}
}
}

View File

@ -1,8 +0,0 @@
use bevy::prelude::*;
pub mod direction;
pub mod grid;
pub mod tile;
pub(super) fn plugin(app: &mut App) {
app.add_plugins((direction::plugin, tile::plugin, grid::plugin));
}

View File

@ -1,128 +0,0 @@
use super::{
direction::HexDirection,
grid::{Grid, GridSettings},
};
use bevy::{
prelude::*,
render::{
mesh::{Indices, PrimitiveTopology},
render_asset::RenderAssetUsages,
},
utils::hashbrown::HashMap,
};
use bevy_prototype_lyon::{entity::ShapeBundle, geometry::GeometryBuilder, shapes::Line};
use hexx::{Hex, HexLayout, PlaneMeshBuilder};
use rand::{thread_rng, Rng};
pub(super) fn plugin(_app: &mut App) {}
#[derive(Debug, Reflect, Component, Default)]
#[reflect(Component)]
pub struct Tile {
pub position: Hex,
pub walls: HashMap<HexDirection, bool>,
}
pub fn spawn_tiles(
config: In<GridSettings>,
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
grid: Res<Grid>,
) {
let default_material = materials.add(Color::WHITE);
let mesh = hexagonal_plane(&grid.layout);
let mesh_handle = meshes.add(mesh);
let mut rng = thread_rng();
for hex_pos in Hex::ZERO.range(config.radius) {
let world_pos = grid.layout.hex_to_world_pos(hex_pos);
let mut walls = HashMap::new();
for dir in HexDirection::ALL {
walls.insert(dir, rng.gen_bool(0.5));
}
commands.spawn((
Name::new(format!("Tile: ({}, {})", world_pos.x, world_pos.y)),
ColorMesh2dBundle {
mesh: mesh_handle.clone().into(),
transform: Transform::from_xyz(world_pos.x, world_pos.y, 0.),
material: default_material.clone(),
..default()
},
Tile {
position: hex_pos,
walls,
},
));
}
}
fn hexagonal_plane(hex_layout: &HexLayout) -> Mesh {
let mesh_info = PlaneMeshBuilder::new(hex_layout)
.facing(Vec3::Z)
.center_aligned()
.build();
Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetUsages::RENDER_WORLD,
)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, mesh_info.vertices)
.with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, mesh_info.normals)
.with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, mesh_info.uvs)
.with_inserted_indices(Indices::U16(mesh_info.indices))
}
fn hex_corner_positions(layout: &HexLayout, hex: Hex) -> [Vec2; 6] {
let center = layout.hex_to_world_pos(hex);
let mut corners = [Vec2::ZERO; 6];
for (idx, corner) in corners.iter_mut().enumerate() {
let andgle_deg = 60. * idx as f32; // FIX:
let andgle_rad = andgle_deg.to_radians();
let size = layout.hex_size;
*corner = center + Vec2::new(size.x * andgle_rad.cos(), size.y * andgle_rad.sin());
}
corners
}
pub fn draw_walls(
mut commands: Commands,
tile_query: Query<(Entity, &Tile)>,
mut materials: ResMut<Assets<ColorMaterial>>,
grid: Res<Grid>,
) {
let default_material = materials.add(Color::BLACK);
for (entity, tile) in tile_query.iter() {
let corners = hex_corner_positions(&grid.layout, tile.position);
for (dir, has_wall) in &tile.walls {
if *has_wall {
let direction_idx = *dir as usize;
let cornder1 = direction_idx;
let cornder2 = (direction_idx + 1) % 6;
let start_pos = corners[cornder1];
let end_pos = corners[cornder2];
let line = Line(start_pos, end_pos);
let wall_entity = commands
.spawn((
Name::new("Wall"),
ShapeBundle {
path: GeometryBuilder::build_as(&line),
material: default_material.clone(),
..default()
},
))
.id();
commands.entity(entity).add_child(wall_entity);
}
}
}
}

View File

@ -8,12 +8,16 @@ use bevy_prototype_lyon::{
};
use rand::{thread_rng, Rng};
pub(super) fn plugin(app: &mut App) {
pub struct HexGrid;
impl Plugin for HexGrid {
fn build(&self, app: &mut App) {
app.add_plugins(ShapePlugin);
app.add_systems(Startup, setup_system);
}
}
fn setup_system(mut commands: Commands) {
pub(super) fn setup_system(mut commands: Commands) {
let radius = 5;
let hex_positions = generate_hex_grix(radius);

25
src/hexgrid/mod.rs Normal file
View File

@ -0,0 +1,25 @@
use bevy::{
ecs::{system::RunSystemOnce, world::Command},
prelude::*,
};
use bevy_prototype_lyon::plugin::ShapePlugin;
use grid::setup_system;
pub mod grid;
pub struct HexGrid;
impl Plugin for HexGrid {
fn build(&self, app: &mut App) {
app.add_plugins(ShapePlugin);
}
}
impl Command for HexGrid {
fn apply(self, world: &mut World) {
world.run_system_once(setup_system);
}
}
pub fn spawn_grid(world: &mut World) {
HexGrid.apply(world);
}

View File

@ -5,8 +5,7 @@ mod demo;
#[cfg(feature = "dev")]
mod dev_tools;
#[cfg(not(feature = "demo"))]
mod grid;
mod hex;
mod hexgrid;
mod screens;
mod theme;
@ -64,8 +63,7 @@ impl Plugin for AppPlugin {
#[cfg(feature = "demo")]
demo::plugin,
#[cfg(not(feature = "demo"))]
// grid::plugin,
hex::plugin,
hexgrid::HexGrid,
screens::plugin,
theme::plugin,
));

View File

@ -5,7 +5,7 @@ use bevy::{input::common_conditions::input_just_pressed, prelude::*};
#[cfg(feature = "demo")]
use crate::demo::level::spawn_level as spawn_level_command;
#[cfg(not(feature = "demo"))]
use crate::grid::grid::spawn_grid as spawn_level_command;
use crate::hexgrid::spawn_grid as spawn_level_command;
use crate::{asset_tracking::LoadResource, audio::Music, screens::Screen};
pub(super) fn plugin(app: &mut App) {