hex coords
This commit is contained in:
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
@@ -6,30 +6,24 @@ pub fn generate_heightmap(height: usize, width: usize, cfg: &GenerationConfig, s
|
|||||||
let mut chunks: Vec<Chunk> = Vec::with_capacity(height * width);
|
let mut chunks: Vec<Chunk> = Vec::with_capacity(height * width);
|
||||||
for z in 0..height {
|
for z in 0..height {
|
||||||
for x in 0..width {
|
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 {
|
return Map {
|
||||||
chunks: chunks,
|
chunks,
|
||||||
height: height,
|
height,
|
||||||
width: width,
|
width,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_chunk(
|
pub fn generate_chunk(chunk_x: f64, chunk_z: f64, cfg: &GenerationConfig, seed: u32) -> Chunk {
|
||||||
chunk_x: f64,
|
let mut result: Vec<f32> = Vec::with_capacity(Chunk::SIZE * Chunk::SIZE);
|
||||||
chunk_z: f64,
|
|
||||||
size: usize,
|
|
||||||
cfg: &GenerationConfig,
|
|
||||||
seed: u32,
|
|
||||||
) -> Chunk {
|
|
||||||
let mut result: Vec<f32> = Vec::with_capacity(size * size);
|
|
||||||
let noise = SuperSimplex::new(seed);
|
let noise = SuperSimplex::new(seed);
|
||||||
for z in 0..size {
|
for z in 0..Chunk::SIZE {
|
||||||
for x in 0..size {
|
for x in 0..Chunk::SIZE {
|
||||||
result.push(sample_point(
|
result.push(sample_point(
|
||||||
x as f64 + chunk_x * size as f64,
|
x as f64 + chunk_x * Chunk::SIZE as f64,
|
||||||
z as f64 + chunk_z * size as f64,
|
z as f64 + chunk_z * Chunk::SIZE as f64,
|
||||||
&cfg,
|
&cfg,
|
||||||
&noise,
|
&noise,
|
||||||
));
|
));
|
||||||
@@ -37,7 +31,6 @@ pub fn generate_chunk(
|
|||||||
}
|
}
|
||||||
return Chunk {
|
return Chunk {
|
||||||
points: result,
|
points: result,
|
||||||
size: size,
|
|
||||||
chunk_offset: IVec2::new(chunk_x as i32, chunk_z as i32),
|
chunk_offset: IVec2::new(chunk_x as i32, chunk_z as i32),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,162 @@
|
|||||||
|
use crate::prelude::Chunk;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
pub const OUTER_RADIUS: f32 = 1.;
|
pub const OUTER_RADIUS: f32 = 1.;
|
||||||
pub const INNER_RADIUS: f32 = OUTER_RADIUS * 0.866025404;
|
pub const INNER_RADIUS: f32 = OUTER_RADIUS * 0.866025404;
|
||||||
|
|
||||||
pub fn to_hex_pos(pos: Vec3) -> Vec3 {
|
pub fn offset3d_to_world(offset: Vec3) -> Vec3 {
|
||||||
let x = (pos.x + pos.z * 0.5 - (pos.z / 2.).floor()) * (INNER_RADIUS * 2.);
|
let x = (offset.x + offset.z * 0.5 - (offset.z / 2.).floor()) * (INNER_RADIUS * 2.);
|
||||||
return Vec3::new(x, pos.y, pos.z * OUTER_RADIUS * 1.5);
|
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<Self> 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),
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,12 @@ pub mod prelude {
|
|||||||
}
|
}
|
||||||
pub struct Chunk {
|
pub struct Chunk {
|
||||||
pub points: Vec<f32>,
|
pub points: Vec<f32>,
|
||||||
pub size: usize,
|
|
||||||
pub chunk_offset: IVec2,
|
pub chunk_offset: IVec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Chunk {
|
||||||
|
pub const SIZE: usize = 32;
|
||||||
|
}
|
||||||
pub struct Map {
|
pub struct Map {
|
||||||
pub chunks: Vec<Chunk>,
|
pub chunks: Vec<Chunk>,
|
||||||
pub height: usize,
|
pub height: usize,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
hex_utils::{to_hex_pos, INNER_RADIUS, OUTER_RADIUS},
|
hex_utils::{offset3d_to_world, INNER_RADIUS, OUTER_RADIUS},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
use bevy::{
|
use bevy::{
|
||||||
@@ -20,17 +20,17 @@ const HEX_CORNERS: [Vec3; 6] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
pub fn generate_chunk_mesh(chunk: &Chunk) -> Mesh {
|
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 verts = Vec::with_capacity(vertex_count);
|
||||||
let mut uvs = Vec::with_capacity(vertex_count);
|
let mut uvs = Vec::with_capacity(vertex_count);
|
||||||
let mut normals = Vec::with_capacity(vertex_count);
|
let mut normals = Vec::with_capacity(vertex_count);
|
||||||
let mut indices = Vec::with_capacity(vertex_count);
|
let mut indices = Vec::with_capacity(vertex_count);
|
||||||
|
|
||||||
for z in 0..chunk.size {
|
for z in 0..Chunk::SIZE {
|
||||||
for x in 0..chunk.size {
|
for x in 0..Chunk::SIZE {
|
||||||
let height = chunk.points[x + z * chunk.size];
|
let height = chunk.points[x + z * Chunk::SIZE];
|
||||||
let off_pos = Vec3::new(x as f32, height, z as f32);
|
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);
|
create_tile(grid_pos, &mut verts, &mut uvs, &mut normals, &mut indices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ pub struct PhosCameraPlugin;
|
|||||||
impl Plugin for PhosCameraPlugin {
|
impl Plugin for PhosCameraPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems(Startup, setup)
|
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);
|
let (mut pitch, mut yaw, _) = transform.rotation.to_euler(EulerRot::XYZ);
|
||||||
|
|
||||||
pitch -= cam_rot.y.to_radians() ;
|
pitch -= cam_rot.y.to_radians();
|
||||||
yaw -= cam_rot.x.to_radians() ;
|
yaw -= cam_rot.x.to_radians();
|
||||||
pitch = pitch.clamp(-1.54, 1.54);
|
pitch = pitch.clamp(-1.54, 1.54);
|
||||||
// if rot_x > PI && cam_rot.x < 2. * PI {
|
// if rot_x > PI && cam_rot.x < 2. * PI {
|
||||||
// rot_x = 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(
|
fn grab_mouse(
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
use bevy::{pbr::CascadeShadowConfig, prelude::*};
|
use bevy::{pbr::CascadeShadowConfig, prelude::*};
|
||||||
use camera_system::PhosCameraPlugin;
|
use camera_system::PhosCameraPlugin;
|
||||||
use iyes_perf_ui::prelude::*;
|
use iyes_perf_ui::prelude::*;
|
||||||
|
use world_generation::hex_utils::offset_to_world;
|
||||||
use world_generation::{
|
use world_generation::{
|
||||||
heightmap::generate_heightmap, hex_utils::to_hex_pos, mesh_generator::generate_chunk_mesh,
|
heightmap::generate_heightmap, hex_utils::offset3d_to_world,
|
||||||
prelude::*,
|
mesh_generator::generate_chunk_mesh, prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct PhosGamePlugin;
|
pub struct PhosGamePlugin;
|
||||||
|
|
||||||
impl Plugin for PhosGamePlugin {
|
impl Plugin for PhosGamePlugin {
|
||||||
@@ -74,10 +76,7 @@ fn create_map(
|
|||||||
|
|
||||||
for chunk in heightmap.chunks {
|
for chunk in heightmap.chunks {
|
||||||
let mesh = generate_chunk_mesh(&chunk);
|
let mesh = generate_chunk_mesh(&chunk);
|
||||||
let pos = to_hex_pos(
|
let pos = offset_to_world(chunk.chunk_offset * Chunk::SIZE as i32);
|
||||||
Vec3::new(chunk.chunk_offset.x as f32, 0., chunk.chunk_offset.y as f32)
|
|
||||||
* chunk.size as f32,
|
|
||||||
);
|
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn(PbrBundle {
|
||||||
mesh: meshes.add(mesh),
|
mesh: meshes.add(mesh),
|
||||||
material: debug_material.clone(),
|
material: debug_material.clone(),
|
||||||
|
|||||||
Reference in New Issue
Block a user