rust/mapgen/src/lib.rs
branchtransitional_engine
changeset 15903 230dc46487ea
parent 15828 44b49f255e31
child 15914 c571d4b8879c
equal deleted inserted replaced
15902:9b73594ac986 15903:230dc46487ea
     1 pub mod theme;
     1 pub mod theme;
     2 
     2 
     3 use self::theme::Theme;
     3 use self::theme::Theme;
     4 use integral_geometry::{Point, Rect, Size};
     4 use integral_geometry::{Point, Rect, Size};
     5 use land2d::Land2D;
     5 use land2d::Land2D;
     6 use landgen::outline_template::OutlineTemplate;
     6 use landgen::{outline_template::OutlineTemplate, LandGenerationParameters};
     7 use rand::{thread_rng, Rng};
       
     8 use serde_derive::Deserialize;
     7 use serde_derive::Deserialize;
     9 use serde_yaml;
     8 use serde_yaml;
    10 use std::{borrow::Borrow, collections::hash_map::HashMap, mem::replace};
     9 use std::{borrow::Borrow, collections::hash_map::HashMap, mem::replace};
    11 use vec2d::Vec2D;
    10 use vec2d::Vec2D;
       
    11 use rand::{Rng, seq::SliceRandom};
    12 
    12 
    13 #[derive(Deserialize)]
    13 #[derive(Deserialize)]
    14 struct PointDesc {
    14 struct PointDesc {
    15     x: u32,
    15     x: u32,
    16     y: u32,
    16     y: u32,
   109                 )
   109                 )
   110             })
   110             })
   111             .collect();
   111             .collect();
   112     }
   112     }
   113 
   113 
   114     pub fn get_template(&self, template_type: &str) -> Option<&OutlineTemplate> {
   114     pub fn get_template<R: Rng>(&self, template_type: &str, rng: &mut R) -> Option<&OutlineTemplate> {
   115         self.templates
   115         self.templates
   116             .get(template_type)
   116             .get(template_type)
   117             .and_then(|t| thread_rng().choose(t))
   117             .and_then(|t| t.as_slice().choose(rng))
   118     }
   118     }
   119 
   119 
   120     pub fn make_texture<LandT>(&self, land: &Land2D<LandT>, theme: &Theme) -> Vec2D<u32>
   120     pub fn make_texture<LandT>(
       
   121         &self,
       
   122         land: &Land2D<LandT>,
       
   123         parameters: &LandGenerationParameters<LandT>,
       
   124         theme: &Theme,
       
   125     ) -> Vec2D<u32>
   121     where
   126     where
   122         LandT: Copy + Default + PartialEq,
   127         LandT: Copy + Default + PartialEq,
   123     {
   128     {
   124         let mut texture = Vec2D::new(land.size().size(), 0);
   129         let mut texture = Vec2D::new(land.size().size(), 0);
   125 
   130 
   129                 let sprite_row = land_sprite.get_row(row_index % land_sprite.height());
   134                 let sprite_row = land_sprite.get_row(row_index % land_sprite.height());
   130                 let mut x_offset = 0;
   135                 let mut x_offset = 0;
   131                 while sprite_row.len() < land.width() - x_offset {
   136                 while sprite_row.len() < land.width() - x_offset {
   132                     let copy_range = x_offset..x_offset + sprite_row.len();
   137                     let copy_range = x_offset..x_offset + sprite_row.len();
   133                     tex_row_copy(
   138                     tex_row_copy(
       
   139                         parameters.basic(),
   134                         &land_row[copy_range.clone()],
   140                         &land_row[copy_range.clone()],
   135                         &mut tex_row[copy_range],
   141                         &mut tex_row[copy_range],
   136                         sprite_row,
   142                         sprite_row,
   137                     );
   143                     );
   138 
   144 
   140                 }
   146                 }
   141 
   147 
   142                 if x_offset < land.width() {
   148                 if x_offset < land.width() {
   143                     let final_range = x_offset..land.width();
   149                     let final_range = x_offset..land.width();
   144                     tex_row_copy(
   150                     tex_row_copy(
       
   151                         parameters.basic(),
   145                         &land_row[final_range.clone()],
   152                         &land_row[final_range.clone()],
   146                         &mut tex_row[final_range],
   153                         &mut tex_row[final_range],
   147                         &sprite_row[..land.width() - x_offset],
   154                         &sprite_row[..land.width() - x_offset],
   148                     );
   155                     );
   149                 }
   156                 }
   156             let border_sprite = border_sprite.to_tiled();
   163             let border_sprite = border_sprite.to_tiled();
   157 
   164 
   158             let mut offsets = vec![255u8; land.width()];
   165             let mut offsets = vec![255u8; land.width()];
   159 
   166 
   160             land_border_pass(
   167             land_border_pass(
       
   168                 parameters.basic(),
   161                 land.rows().rev().zip(texture.rows_mut().rev()),
   169                 land.rows().rev().zip(texture.rows_mut().rev()),
   162                 &mut offsets,
   170                 &mut offsets,
   163                 border_width,
   171                 border_width,
   164                 |x, y| {
   172                 |x, y| {
   165                     border_sprite
   173                     border_sprite
   168             );
   176             );
   169 
   177 
   170             offsets.iter_mut().for_each(|v| *v = 255);
   178             offsets.iter_mut().for_each(|v| *v = 255);
   171 
   179 
   172             land_border_pass(
   180             land_border_pass(
       
   181                 parameters.basic(),
   173                 land.rows().zip(texture.rows_mut()),
   182                 land.rows().zip(texture.rows_mut()),
   174                 &mut offsets,
   183                 &mut offsets,
   175                 border_width,
   184                 border_width,
   176                 |x, y| border_sprite.get_pixel(x % border_sprite.width(), y),
   185                 |x, y| border_sprite.get_pixel(x % border_sprite.width(), y),
   177             );
   186             );
   220     let green = lerp(target.green(), source.green(), source.alpha());
   229     let green = lerp(target.green(), source.green(), source.alpha());
   221     let blue = lerp(target.blue(), source.blue(), source.alpha());
   230     let blue = lerp(target.blue(), source.blue(), source.alpha());
   222     (red as u32) << 0 | (green as u32) << 8 | (blue as u32) << 16 | (alpha as u32) << 24
   231     (red as u32) << 0 | (green as u32) << 8 | (blue as u32) << 16 | (alpha as u32) << 24
   223 }
   232 }
   224 
   233 
   225 fn land_border_pass<'a, LandT, T, F>(rows: T, offsets: &mut [u8], border_width: u8, pixel_getter: F)
   234 fn land_border_pass<'a, LandT, T, F>(
   226 where
   235     basic_value: LandT,
       
   236     rows: T,
       
   237     offsets: &mut [u8],
       
   238     border_width: u8,
       
   239     pixel_getter: F,
       
   240 ) where
   227     LandT: Default + PartialEq + 'a,
   241     LandT: Default + PartialEq + 'a,
   228     T: Iterator<Item = (&'a [LandT], &'a mut [u32])>,
   242     T: Iterator<Item = (&'a [LandT], &'a mut [u32])>,
   229     F: (Fn(usize, usize) -> u32),
   243     F: (Fn(usize, usize) -> u32),
   230 {
   244 {
   231     for (land_row, tex_row) in rows {
   245     for (land_row, tex_row) in rows {
   233             .iter()
   247             .iter()
   234             .zip(tex_row.iter_mut())
   248             .zip(tex_row.iter_mut())
   235             .zip(offsets.iter_mut())
   249             .zip(offsets.iter_mut())
   236             .enumerate()
   250             .enumerate()
   237         {
   251         {
   238             *offset_v = if *land_v == LandT::default() {
   252             *offset_v = if *land_v == basic_value {
   239                 if *offset_v < border_width {
   253                 if *offset_v < border_width {
   240                     *tex_v = blend(pixel_getter(x, *offset_v as usize), *tex_v)
   254                     *tex_v = blend(pixel_getter(x, *offset_v as usize), *tex_v)
   241                 }
   255                 }
   242                 offset_v.saturating_add(1)
   256                 offset_v.saturating_add(1)
   243             } else {
   257             } else {
   245             }
   259             }
   246         }
   260         }
   247     }
   261     }
   248 }
   262 }
   249 
   263 
   250 fn tex_row_copy<LandT>(land_row: &[LandT], tex_row: &mut [u32], sprite_row: &[u32])
   264 fn tex_row_copy<LandT>(
   251 where
   265     basic_value: LandT,
       
   266     land_row: &[LandT],
       
   267     tex_row: &mut [u32],
       
   268     sprite_row: &[u32],
       
   269 ) where
   252     LandT: Default + PartialEq,
   270     LandT: Default + PartialEq,
   253 {
   271 {
   254     for ((land_v, tex_v), sprite_v) in land_row.iter().zip(tex_row.iter_mut()).zip(sprite_row) {
   272     for ((land_v, tex_v), sprite_v) in land_row.iter().zip(tex_row.iter_mut()).zip(sprite_row) {
   255         *tex_v = if *land_v == LandT::default() {
   273         *tex_v = if *land_v == basic_value { *sprite_v } else { 0 }
   256             *sprite_v
       
   257         } else {
       
   258             0
       
   259         }
       
   260     }
   274     }
   261 }
   275 }
   262 
   276 
   263 #[cfg(test)]
   277 #[cfg(test)]
   264 mod tests {
   278 mod tests {