very basic worldgen
This commit is contained in:
parent
7ac86cbc11
commit
f3b8d44034
3 changed files with 218 additions and 19 deletions
4
build.rs
4
build.rs
|
@ -75,14 +75,14 @@ impl AssetsWriter {
|
||||||
for asset_name in root.assets.keys() {
|
for asset_name in root.assets.keys() {
|
||||||
writeln!(
|
writeln!(
|
||||||
file,
|
file,
|
||||||
"{indent}\t{}: comfy::TextureHandle,",
|
"pub {indent}\t{}: comfy::TextureHandle,",
|
||||||
asset_name.to_snake_case()
|
asset_name.to_snake_case()
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
for group_name in root.groups.keys() {
|
for group_name in root.groups.keys() {
|
||||||
writeln!(
|
writeln!(
|
||||||
file,
|
file,
|
||||||
"{indent}\t{group_name}: &'static {group_name}::Assets,"
|
"pub {indent}\t{group_name}: &'static {group_name}::Assets,"
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
writeln!(file, "{indent}}}")?;
|
writeln!(file, "{indent}}}")?;
|
||||||
|
|
|
@ -7,7 +7,7 @@ pub mod worldgen;
|
||||||
pub fn draw(state: &crate::State, _engine: &comfy::EngineContext<'_>) {
|
pub fn draw(state: &crate::State, _engine: &comfy::EngineContext<'_>) {
|
||||||
draw_circle(vec2(0.0, 0.0), 0.5, GREEN, 0);
|
draw_circle(vec2(0.0, 0.0), 0.5, GREEN, 0);
|
||||||
for (coords, tile) in state.overworld.iter_tiles() {
|
for (coords, tile) in state.overworld.iter_tiles() {
|
||||||
for (i, texture) in tile.textures.iter().rev().enumerate() {
|
for (i, texture) in tile.textures().iter().rev().enumerate() {
|
||||||
let i = i as i32;
|
let i = i as i32;
|
||||||
draw_sprite(
|
draw_sprite(
|
||||||
*texture,
|
*texture,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
use crate::assets::ASSETS;
|
||||||
use comfy::{IVec2, TextureHandle, UVec2};
|
use comfy::{IVec2, TextureHandle, UVec2};
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub enum MovementCost {
|
pub enum MovementCost {
|
||||||
|
@ -13,12 +13,66 @@ pub enum MovementCost {
|
||||||
Obstacle
|
Obstacle
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct Tile {
|
pub enum Tile {
|
||||||
pub textures: Vec<TextureHandle>
|
Grass,
|
||||||
|
|
||||||
|
Path {
|
||||||
|
left: bool,
|
||||||
|
right: bool,
|
||||||
|
top: bool,
|
||||||
|
bottom: bool
|
||||||
|
},
|
||||||
|
|
||||||
|
House {
|
||||||
|
texture: TextureHandle,
|
||||||
|
door: bool
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tile {
|
impl Tile {
|
||||||
|
pub fn textures(&self) -> Vec<TextureHandle> {
|
||||||
|
match self {
|
||||||
|
Self::Grass => vec![ASSETS.overworld.grass],
|
||||||
|
|
||||||
|
Self::Path {
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
top,
|
||||||
|
bottom
|
||||||
|
} => {
|
||||||
|
let path_texture = match (left, right, top, bottom) {
|
||||||
|
(true, true, false, false) => ASSETS.overworld.path_horiz,
|
||||||
|
(false, false, true, true) => ASSETS.overworld.path_vert,
|
||||||
|
|
||||||
|
(true, false, true, false) => ASSETS.overworld.path_top_left,
|
||||||
|
(true, false, false, true) => ASSETS.overworld.path_bottom_left,
|
||||||
|
(false, true, true, false) => ASSETS.overworld.path_top_right,
|
||||||
|
(false, true, false, true) => ASSETS.overworld.path_bottom_right,
|
||||||
|
|
||||||
|
(true, true, true, false) => ASSETS.overworld.path_top_left_right,
|
||||||
|
(true, true, false, true) => ASSETS.overworld.path_bottom_left_right,
|
||||||
|
(true, false, true, true) => ASSETS.overworld.path_top_left_bottom,
|
||||||
|
(false, true, true, true) => ASSETS.overworld.path_top_right_bottom,
|
||||||
|
|
||||||
|
(true, true, true, true) => ASSETS.overworld.path_crossing,
|
||||||
|
|
||||||
|
(true, false, false, false)
|
||||||
|
| (false, true, false, false)
|
||||||
|
| (false, false, true, false)
|
||||||
|
| (false, false, false, true) => panic!("We don't have no dead ends"),
|
||||||
|
(false, false, false, false) => panic!("I think you meant grass?!?")
|
||||||
|
};
|
||||||
|
|
||||||
|
vec![ASSETS.overworld.grass, path_texture]
|
||||||
|
},
|
||||||
|
|
||||||
|
Self::House { texture, .. } => {
|
||||||
|
vec![ASSETS.overworld.grass, *texture]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn can_stand_inside(&self) -> bool {
|
pub fn can_stand_inside(&self) -> bool {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
@ -45,6 +99,7 @@ const CHUNK_SIZE: u32 = 100;
|
||||||
|
|
||||||
/// Chunks
|
/// Chunks
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct Chunk {
|
pub struct Chunk {
|
||||||
/// All tiles within this chunk.
|
/// All tiles within this chunk.
|
||||||
tiles: [Tile; (CHUNK_SIZE * CHUNK_SIZE) as usize],
|
tiles: [Tile; (CHUNK_SIZE * CHUNK_SIZE) as usize],
|
||||||
|
@ -59,6 +114,137 @@ pub struct Chunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Chunk {
|
impl Chunk {
|
||||||
|
pub fn generate_chunk() -> Self {
|
||||||
|
// TODO real worldgen
|
||||||
|
// for the time being we just copy this pre-made house block into the chunk
|
||||||
|
|
||||||
|
fn path(left: bool, right: bool, top: bool, bottom: bool) -> Tile {
|
||||||
|
Tile::Path {
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
top,
|
||||||
|
bottom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn house(texture: TextureHandle) -> Tile {
|
||||||
|
Tile::House {
|
||||||
|
texture,
|
||||||
|
door: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let path_horiz = path(true, true, false, false);
|
||||||
|
let path_vert = path(false, false, true, true);
|
||||||
|
let path_crossing = path(true, true, true, true);
|
||||||
|
let grass = Tile::Grass;
|
||||||
|
|
||||||
|
let block = [
|
||||||
|
[
|
||||||
|
path_crossing,
|
||||||
|
path_horiz,
|
||||||
|
path_horiz,
|
||||||
|
path_horiz,
|
||||||
|
path_horiz,
|
||||||
|
path_horiz,
|
||||||
|
path_horiz,
|
||||||
|
path_horiz,
|
||||||
|
path_horiz,
|
||||||
|
path_horiz,
|
||||||
|
path_crossing
|
||||||
|
],
|
||||||
|
[
|
||||||
|
path_vert,
|
||||||
|
grass,
|
||||||
|
grass,
|
||||||
|
grass,
|
||||||
|
house(ASSETS.overworld.house_roof_top),
|
||||||
|
grass,
|
||||||
|
grass,
|
||||||
|
grass,
|
||||||
|
grass,
|
||||||
|
grass,
|
||||||
|
path_vert
|
||||||
|
],
|
||||||
|
[
|
||||||
|
path_vert,
|
||||||
|
grass,
|
||||||
|
grass,
|
||||||
|
house(ASSETS.overworld.house_roof_mid_left),
|
||||||
|
house(ASSETS.overworld.house_mid_window),
|
||||||
|
house(ASSETS.overworld.house_roof_mid_right),
|
||||||
|
grass,
|
||||||
|
grass,
|
||||||
|
grass,
|
||||||
|
grass,
|
||||||
|
path_vert
|
||||||
|
],
|
||||||
|
[
|
||||||
|
path_vert,
|
||||||
|
grass,
|
||||||
|
house(ASSETS.overworld.house_roof_left),
|
||||||
|
house(ASSETS.overworld.house_mid_window),
|
||||||
|
house(ASSETS.overworld.house_mid),
|
||||||
|
house(ASSETS.overworld.house_mid_window),
|
||||||
|
house(ASSETS.overworld.house_roof_right),
|
||||||
|
grass,
|
||||||
|
grass,
|
||||||
|
grass,
|
||||||
|
path_vert
|
||||||
|
],
|
||||||
|
[
|
||||||
|
path_vert,
|
||||||
|
grass,
|
||||||
|
house(ASSETS.overworld.house_bottom_left),
|
||||||
|
house(ASSETS.overworld.house_bottom_door),
|
||||||
|
house(ASSETS.overworld.house_bottom_window),
|
||||||
|
house(ASSETS.overworld.house_bottom_window),
|
||||||
|
house(ASSETS.overworld.house_bottom_right),
|
||||||
|
grass,
|
||||||
|
grass,
|
||||||
|
grass,
|
||||||
|
path_vert
|
||||||
|
],
|
||||||
|
[
|
||||||
|
path_vert,
|
||||||
|
grass,
|
||||||
|
grass,
|
||||||
|
path(false, true, true, false),
|
||||||
|
path_horiz,
|
||||||
|
path_horiz,
|
||||||
|
path_horiz,
|
||||||
|
path_horiz,
|
||||||
|
path_horiz,
|
||||||
|
path_horiz,
|
||||||
|
path(true, false, true, true)
|
||||||
|
],
|
||||||
|
[
|
||||||
|
path_vert, grass, grass, grass, grass, grass, grass, grass, grass, grass,
|
||||||
|
path_vert
|
||||||
|
],
|
||||||
|
[
|
||||||
|
path_vert, grass, grass, grass, grass, grass, grass, grass, grass, grass,
|
||||||
|
path_vert
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
// and then we copy this pre-made block into our chunk
|
||||||
|
let mut tiles = [Tile::Grass; (CHUNK_SIZE * CHUNK_SIZE) as usize];
|
||||||
|
for y in 0 .. CHUNK_SIZE {
|
||||||
|
for x in 0 .. CHUNK_SIZE {
|
||||||
|
let row = block[y as usize % block.len()];
|
||||||
|
tiles[(y * CHUNK_SIZE + x) as usize] = row[x as usize % row.len()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
tiles,
|
||||||
|
paths_left: vec![],
|
||||||
|
paths_right: vec![],
|
||||||
|
paths_bottom: vec![],
|
||||||
|
paths_top: vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_tile(&self, local_chunk_coords: UVec2) -> Option<&Tile> {
|
pub fn get_tile(&self, local_chunk_coords: UVec2) -> Option<&Tile> {
|
||||||
self.tiles
|
self.tiles
|
||||||
.get((local_chunk_coords.y * CHUNK_SIZE + local_chunk_coords.x) as usize)
|
.get((local_chunk_coords.y * CHUNK_SIZE + local_chunk_coords.x) as usize)
|
||||||
|
@ -78,25 +264,38 @@ pub struct Overworld {
|
||||||
chunks: HashMap<IVec2, Chunk>
|
chunks: HashMap<IVec2, Chunk>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn world_to_chunk_and_local_coords(world_coords: IVec2) -> (IVec2, UVec2) {
|
||||||
|
let chunk_coords = IVec2 {
|
||||||
|
x: world_coords.x.div_euclid(CHUNK_SIZE as _),
|
||||||
|
y: world_coords.y.div_euclid(CHUNK_SIZE as _)
|
||||||
|
};
|
||||||
|
let local_chunk_coords = UVec2 {
|
||||||
|
x: world_coords.x.rem_euclid(CHUNK_SIZE as _) as _,
|
||||||
|
y: world_coords.y.rem_euclid(CHUNK_SIZE as _) as _
|
||||||
|
};
|
||||||
|
(chunk_coords, local_chunk_coords)
|
||||||
|
}
|
||||||
|
|
||||||
impl Overworld {
|
impl Overworld {
|
||||||
/// Return a [`Tile`] at the given world coordinates, or `None` if that tile has not
|
/// Return a [`Tile`] at the given world coordinates, or `None` if that tile has not
|
||||||
/// been generated yet.
|
/// been generated yet.
|
||||||
pub fn get_tile(&self, world_coords: IVec2) -> Option<&Tile> {
|
pub fn get_tile(&self, world_coords: IVec2) -> Option<&Tile> {
|
||||||
let tile_coords = IVec2 {
|
let (chunk_coords, local_chunk_coords) =
|
||||||
x: world_coords.x.div_euclid(CHUNK_SIZE as _),
|
world_to_chunk_and_local_coords(world_coords);
|
||||||
y: world_coords.y.div_euclid(CHUNK_SIZE as _)
|
|
||||||
};
|
|
||||||
let local_coords = UVec2 {
|
|
||||||
x: world_coords.x.rem_euclid(CHUNK_SIZE as _) as _,
|
|
||||||
y: world_coords.y.rem_euclid(CHUNK_SIZE as _) as _
|
|
||||||
};
|
|
||||||
|
|
||||||
let chunk = self.chunks.get(&tile_coords)?;
|
let chunk = self.chunks.get(&chunk_coords)?;
|
||||||
chunk.get_tile(local_coords)
|
chunk.get_tile(local_chunk_coords)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_or_generate_tile(&self, world_coords: IVec2) -> &Tile {
|
fn get_or_generate_tile(&mut self, world_coords: IVec2) -> &Tile {
|
||||||
unimplemented!()
|
let (chunk_coords, local_chunk_coords) =
|
||||||
|
world_to_chunk_and_local_coords(world_coords);
|
||||||
|
|
||||||
|
let chunk = self
|
||||||
|
.chunks
|
||||||
|
.entry(chunk_coords)
|
||||||
|
.or_insert_with(Chunk::generate_chunk);
|
||||||
|
chunk.get_tile(local_chunk_coords).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// iterate over all tiles and its global coords
|
/// iterate over all tiles and its global coords
|
||||||
|
|
Loading…
Reference in a new issue