diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..a55e7a1
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/engine/world_generation/src/heightmap.rs b/engine/world_generation/src/heightmap.rs
index 0676b16..9b0d792 100644
--- a/engine/world_generation/src/heightmap.rs
+++ b/engine/world_generation/src/heightmap.rs
@@ -6,30 +6,24 @@ pub fn generate_heightmap(height: usize, width: usize, cfg: &GenerationConfig, s
let mut chunks: Vec = Vec::with_capacity(height * width);
for z in 0..height {
for x in 0..width {
- chunks.push(generate_chunk(x as f64, z as f64, 32, cfg, seed));
+ chunks.push(generate_chunk(x as f64, z as f64, cfg, seed));
}
}
return Map {
- chunks: chunks,
- height: height,
- width: width,
+ chunks,
+ height,
+ width,
};
}
-pub fn generate_chunk(
- chunk_x: f64,
- chunk_z: f64,
- size: usize,
- cfg: &GenerationConfig,
- seed: u32,
-) -> Chunk {
- let mut result: Vec = Vec::with_capacity(size * size);
+pub fn generate_chunk(chunk_x: f64, chunk_z: f64, cfg: &GenerationConfig, seed: u32) -> Chunk {
+ let mut result: Vec = Vec::with_capacity(Chunk::SIZE * Chunk::SIZE);
let noise = SuperSimplex::new(seed);
- for z in 0..size {
- for x in 0..size {
+ for z in 0..Chunk::SIZE {
+ for x in 0..Chunk::SIZE {
result.push(sample_point(
- x as f64 + chunk_x * size as f64,
- z as f64 + chunk_z * size as f64,
+ x as f64 + chunk_x * Chunk::SIZE as f64,
+ z as f64 + chunk_z * Chunk::SIZE as f64,
&cfg,
&noise,
));
@@ -37,7 +31,6 @@ pub fn generate_chunk(
}
return Chunk {
points: result,
- size: size,
chunk_offset: IVec2::new(chunk_x as i32, chunk_z as i32),
};
}
diff --git a/engine/world_generation/src/hex_utils.rs b/engine/world_generation/src/hex_utils.rs
index 0e8a09d..13e01a5 100644
--- a/engine/world_generation/src/hex_utils.rs
+++ b/engine/world_generation/src/hex_utils.rs
@@ -1,9 +1,162 @@
+use crate::prelude::Chunk;
use bevy::prelude::*;
pub const OUTER_RADIUS: f32 = 1.;
pub const INNER_RADIUS: f32 = OUTER_RADIUS * 0.866025404;
-pub fn to_hex_pos(pos: Vec3) -> Vec3 {
- let x = (pos.x + pos.z * 0.5 - (pos.z / 2.).floor()) * (INNER_RADIUS * 2.);
- return Vec3::new(x, pos.y, pos.z * OUTER_RADIUS * 1.5);
+pub fn offset3d_to_world(offset: Vec3) -> Vec3 {
+ let x = (offset.x + offset.z * 0.5 - (offset.z / 2.).floor()) * (INNER_RADIUS * 2.);
+ return Vec3::new(x, offset.y, offset.z * OUTER_RADIUS * 1.5);
+}
+
+pub fn offset_to_world(offset: IVec2) -> Vec3 {
+ let x = (offset.x as f32 + offset.y as f32 * 0.5 - (offset.y as f32 / 2.).floor())
+ * (INNER_RADIUS * 2.);
+ return Vec3::new(x, 0., offset.y as f32 * OUTER_RADIUS * 1.5);
+}
+
+pub fn offset_to_hex(offset: IVec2) -> IVec3 {
+ return IVec3 {
+ x: offset.x,
+ y: offset.y,
+ z: -offset.x - offset.y,
+ };
+}
+
+pub fn snap_to_hex_grid(world_pos: Vec3) -> Vec3 {
+ return offset_to_world(world_to_offset_pos(world_pos));
+}
+
+pub fn world_to_offset_pos(world_pos: Vec3) -> IVec2 {
+ let offset = world_pos.z / (OUTER_RADIUS * 3.);
+ let x = (world_pos.x / (INNER_RADIUS * 2.)) - offset;
+ let z = -world_pos.x - offset;
+
+ let ix = x.round() as i32;
+ let iz = z.round() as i32;
+ let ox = ix + iz / 2;
+ let oz = iz;
+ return IVec2::new(ox, oz);
+}
+
+pub fn tile_to_world_distance(dist: i32) -> f32 {
+ return dist as f32 * (2. * INNER_RADIUS);
+}
+
+pub fn get_tile_count(radius: i32)->i32{
+ return 1 + 3 * (radius + 1) * radius;
+}
+
+#[derive(Default, Clone, Copy)]
+pub struct HexCoord {
+ pub hex: IVec3,
+ pub offset: IVec2,
+ pub world: Vec3,
+}
+
+impl PartialEq for HexCoord {
+ fn eq(&self, other: &Self) -> bool {
+ return self.offset == other.offset;
+ }
+}
+
+impl Eq for HexCoord {}
+
+impl HexCoord {
+ pub const DIRECTIONS: [IVec3; 6] = [
+ IVec3::new(1, -1, 0),
+ IVec3::new(1, 0, -1),
+ IVec3::new(0, 1, -1),
+ IVec3::new(-1, 1, 0),
+ IVec3::new(-1, 0, 1),
+ IVec3::new(0, -1, 1),
+ ];
+
+ pub const ZERO: HexCoord = HexCoord {
+ offset: IVec2::ZERO,
+ hex: IVec3::ZERO,
+ world: Vec3::ZERO,
+ };
+
+ pub fn new(x: i32, z: i32) -> Self {
+ return Self::from_offset(IVec2::new(x, z));
+ }
+ pub fn from_grid_pos(x: usize, z: usize) -> Self {
+ return HexCoord::new(x as i32, z as i32);
+ }
+ pub fn from_offset(offset_pos: IVec2) -> Self {
+ return HexCoord {
+ offset: offset_pos,
+ hex: offset_to_hex(offset_pos),
+ world: offset3d_to_world(offset_pos.extend(0).xzy().as_vec3()),
+ };
+ }
+
+ pub fn to_chunk_pos(&self) -> IVec2 {
+ return IVec2 {
+ x: (self.offset.x as f32 / Chunk::SIZE as f32).floor() as i32,
+ y: (self.offset.y as f32 / Chunk::SIZE as f32).floor() as i32,
+ };
+ }
+
+ pub fn to_chunk_index(&self, width: usize) -> usize {
+ let pos = self.to_chunk_pos();
+ return pos.x as usize + pos.y as usize * width;
+ }
+
+ pub fn distance(&self, other: &HexCoord) -> i32 {
+ return (self.hex.x - other.hex.x).abs()
+ + (self.hex.y - other.hex.y).abs()
+ + (self.hex.z - other.hex.z).abs();
+ }
+
+ pub fn rotate_around(&self, center: &HexCoord, angle: i32) -> HexCoord {
+ if self == center || angle == 0 {
+ return self.clone();
+ }
+
+ let mut a = angle % 6;
+ let mut pc = self.hex - center.hex;
+
+ if a > 0 {
+ for _ in 0..a {
+ pc = Self::slide_right(pc);
+ }
+ } else {
+ a = a.abs();
+ for _ in 0..a {
+ pc = Self::slide_left(pc);
+ }
+ }
+ return HexCoord::from_offset(pc.xy() + center.hex.xy());
+ }
+
+ fn slide_left(hex: IVec3) -> IVec3 {
+ return (hex * -1).yzx();
+ }
+
+ fn slide_right(hex: IVec3) -> IVec3 {
+ return (hex * -1).zxy();
+ }
+
+ pub fn scale(&self, dir: i32, radius: i32)-> HexCoord{
+ let s = Self::DIRECTIONS[dir % 6] * radius;
+ return Self::from_offset(self.hex.xy() + s.xy());
+ }
+
+ pub fn get_neighbor(&self, dir: i32)-> HexCoord{
+ let d = Self::DIRECTIONS[dir % 6];
+ return Self::from_offset(self.hex.xy() + d.xy());
+ }
+
+ pub fn get_neighbors(&self) -> [HexCoord; 6]{
+ return [
+ self.get_neighbor(0),
+ self.get_neighbor(1),
+ self.get_neighbor(2),
+ self.get_neighbor(3),
+ self.get_neighbor(4),
+ self.get_neighbor(5),
+ ]
+ }
}
diff --git a/engine/world_generation/src/lib.rs b/engine/world_generation/src/lib.rs
index 134f288..e4c6c42 100644
--- a/engine/world_generation/src/lib.rs
+++ b/engine/world_generation/src/lib.rs
@@ -20,9 +20,12 @@ pub mod prelude {
}
pub struct Chunk {
pub points: Vec,
- pub size: usize,
pub chunk_offset: IVec2,
}
+
+ impl Chunk {
+ pub const SIZE: usize = 32;
+ }
pub struct Map {
pub chunks: Vec,
pub height: usize,
diff --git a/engine/world_generation/src/mesh_generator.rs b/engine/world_generation/src/mesh_generator.rs
index e04f619..1c275df 100644
--- a/engine/world_generation/src/mesh_generator.rs
+++ b/engine/world_generation/src/mesh_generator.rs
@@ -1,5 +1,5 @@
use crate::{
- hex_utils::{to_hex_pos, INNER_RADIUS, OUTER_RADIUS},
+ hex_utils::{offset3d_to_world, INNER_RADIUS, OUTER_RADIUS},
prelude::*,
};
use bevy::{
@@ -20,17 +20,17 @@ const HEX_CORNERS: [Vec3; 6] = [
];
pub fn generate_chunk_mesh(chunk: &Chunk) -> Mesh {
- let vertex_count: usize = chunk.size * chunk.size;
+ let vertex_count: usize = Chunk::SIZE * Chunk::SIZE;
let mut verts = Vec::with_capacity(vertex_count);
let mut uvs = Vec::with_capacity(vertex_count);
let mut normals = Vec::with_capacity(vertex_count);
let mut indices = Vec::with_capacity(vertex_count);
- for z in 0..chunk.size {
- for x in 0..chunk.size {
- let height = chunk.points[x + z * chunk.size];
+ for z in 0..Chunk::SIZE {
+ for x in 0..Chunk::SIZE {
+ let height = chunk.points[x + z * Chunk::SIZE];
let off_pos = Vec3::new(x as f32, height, z as f32);
- let grid_pos = to_hex_pos(off_pos);
+ let grid_pos = offset3d_to_world(off_pos);
create_tile(grid_pos, &mut verts, &mut uvs, &mut normals, &mut indices);
}
}
diff --git a/game/camera_system/src/lib.rs b/game/camera_system/src/lib.rs
index 0a9c980..15ffe97 100644
--- a/game/camera_system/src/lib.rs
+++ b/game/camera_system/src/lib.rs
@@ -19,7 +19,7 @@ pub struct PhosCameraPlugin;
impl Plugin for PhosCameraPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, setup)
- .add_systems(Update, (update_camera, grab_mouse));
+ .add_systems(Update, (update_camera, grab_mouse, update_camera_mouse));
}
}
@@ -84,14 +84,15 @@ fn update_camera_mouse(
let (mut pitch, mut yaw, _) = transform.rotation.to_euler(EulerRot::XYZ);
- pitch -= cam_rot.y.to_radians() ;
- yaw -= cam_rot.x.to_radians() ;
+ pitch -= cam_rot.y.to_radians();
+ yaw -= cam_rot.x.to_radians();
pitch = pitch.clamp(-1.54, 1.54);
// if rot_x > PI && cam_rot.x < 2. * PI {
// rot_x = PI;
// }
- transform.rotation = Quat::from_axis_angle(Vec3::Y, yaw) * Quat::from_axis_angle(Vec3::X, pitch);
+ transform.rotation =
+ Quat::from_axis_angle(Vec3::Y, yaw) * Quat::from_axis_angle(Vec3::X, pitch);
}
fn grab_mouse(
diff --git a/game/main/src/phos.rs b/game/main/src/phos.rs
index 0694660..e76b494 100644
--- a/game/main/src/phos.rs
+++ b/game/main/src/phos.rs
@@ -1,10 +1,12 @@
use bevy::{pbr::CascadeShadowConfig, prelude::*};
use camera_system::PhosCameraPlugin;
use iyes_perf_ui::prelude::*;
+use world_generation::hex_utils::offset_to_world;
use world_generation::{
- heightmap::generate_heightmap, hex_utils::to_hex_pos, mesh_generator::generate_chunk_mesh,
- prelude::*,
+ heightmap::generate_heightmap, hex_utils::offset3d_to_world,
+ mesh_generator::generate_chunk_mesh, prelude::*,
};
+
pub struct PhosGamePlugin;
impl Plugin for PhosGamePlugin {
@@ -74,10 +76,7 @@ fn create_map(
for chunk in heightmap.chunks {
let mesh = generate_chunk_mesh(&chunk);
- let pos = to_hex_pos(
- Vec3::new(chunk.chunk_offset.x as f32, 0., chunk.chunk_offset.y as f32)
- * chunk.size as f32,
- );
+ let pos = offset_to_world(chunk.chunk_offset * Chunk::SIZE as i32);
commands.spawn(PbrBundle {
mesh: meshes.add(mesh),
material: debug_material.clone(),