rust/mapgen/src/lib.rs
changeset 14170 a4c1a2d0ac24
parent 14164 1749961647b9
child 14175 76a52e8149e3
equal deleted inserted replaced
14169:e2c51c8e0b2e 14170:a4c1a2d0ac24
   106         self.templates.get(template_type).and_then(|t| thread_rng().choose(t))
   106         self.templates.get(template_type).and_then(|t| thread_rng().choose(t))
   107     }
   107     }
   108 
   108 
   109     pub fn make_texture(&self, land: &Land2D<u8>, theme: &Theme) -> Vec2D<u32> {
   109     pub fn make_texture(&self, land: &Land2D<u8>, theme: &Theme) -> Vec2D<u32> {
   110         let mut texture = Vec2D::new(land.size(), 0);
   110         let mut texture = Vec2D::new(land.size(), 0);
       
   111 
   111         if let Some(land_sprite) = theme.land_texture() {
   112         if let Some(land_sprite) = theme.land_texture() {
   112             for (row_index, (land_row, tex_row)) in land.rows()
   113             for (row_index, (land_row, tex_row)) in land.rows()
   113                 .zip(texture.rows_mut())
   114                 .zip(texture.rows_mut())
   114                 .enumerate()
   115                 .enumerate()
   115             {
   116             {
   134                         &sprite_row[..land.width() - x_offset]
   135                         &sprite_row[..land.width() - x_offset]
   135                     );
   136                     );
   136                 }
   137                 }
   137             }
   138             }
   138         }
   139         }
       
   140 
       
   141         if let Some(border_sprite) = theme.border_texture() {
       
   142             assert!(border_sprite.height() <= 512);
       
   143             let border_width = (border_sprite.height() / 2) as u8;
       
   144 
       
   145             let mut offsets = vec![255u8; land.width()];
       
   146 
       
   147             land_border_pass(
       
   148                 land.rows().rev().zip(texture.rows_mut().rev()),
       
   149                 &mut offsets,
       
   150                 border_width,
       
   151                 |x, y| border_sprite.get_pixel(
       
   152                     x % border_sprite.width(),
       
   153                     border_sprite.height() - 1 - y,
       
   154                 )
       
   155             );
       
   156 
       
   157             offsets.iter_mut().for_each(|v| *v = 255);
       
   158 
       
   159             land_border_pass(
       
   160                 land.rows().zip(texture.rows_mut()),
       
   161                 &mut offsets,
       
   162                 border_width,
       
   163                 |x, y| border_sprite.get_pixel(
       
   164                     x % border_sprite.width(),
       
   165                     y,
       
   166                 )
       
   167             );
       
   168         }
       
   169 
   139         texture
   170         texture
       
   171     }
       
   172 }
       
   173 
       
   174 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
       
   175 struct Color(u32);
       
   176 
       
   177 impl Color {
       
   178     #[inline]
       
   179     fn red(self) -> u8 {
       
   180         (self.0 >> 0 & 0xFF) as u8
       
   181     }
       
   182 
       
   183     #[inline]
       
   184     fn green(self) -> u8 {
       
   185         (self.0 >> 8 & 0xFF) as u8
       
   186     }
       
   187 
       
   188     #[inline]
       
   189     fn blue(self) -> u8 {
       
   190         (self.0 >> 16 & 0xFF) as u8
       
   191     }
       
   192 
       
   193     #[inline]
       
   194     fn alpha(self) -> u8 {
       
   195         (self.0 >> 24 & 0xFF) as u8
       
   196     }
       
   197 }
       
   198 
       
   199 #[inline]
       
   200 fn lerp(from: u8, to: u8, coef: u8) -> u8 {
       
   201     ((from as u16 * (256 - coef as u16) + to as u16 * coef as u16) / 256) as u8
       
   202 }
       
   203 
       
   204 #[inline]
       
   205 fn blend(source: u32, target: u32) -> u32 {
       
   206     let source = Color(source);
       
   207     let target = Color(target);
       
   208     let alpha = lerp(target.alpha(), 255, source.alpha());
       
   209     let red = lerp(target.red(), source.red(), source.alpha());
       
   210     let green = lerp(target.green(), source.green(), source.alpha());
       
   211     let blue = lerp(target.blue(), source.blue(), source.alpha());
       
   212     (red as u32) << 0 | (green as u32) << 8 | (blue as u32) << 16 | (alpha as u32) << 24
       
   213 }
       
   214 
       
   215 fn land_border_pass<'a, T, F>(rows: T, offsets: &mut [u8], border_width: u8, pixel_getter: F)
       
   216     where T: Iterator<Item = (&'a [u8], &'a mut [u32])>,
       
   217           F: (Fn(usize, usize) -> u32)
       
   218 {
       
   219     for (land_row, tex_row) in rows {
       
   220         for (x, ((land_v, tex_v), offset_v)) in land_row.iter()
       
   221             .zip(tex_row.iter_mut())
       
   222             .zip(offsets.iter_mut())
       
   223             .enumerate()
       
   224         {
       
   225             *offset_v = if *land_v == 0 {
       
   226                 if *offset_v < border_width {
       
   227                     *tex_v = blend(
       
   228                         pixel_getter(x, *offset_v as usize),
       
   229                         *tex_v,
       
   230                     )
       
   231                 }
       
   232                 offset_v.saturating_add(1)
       
   233             } else {
       
   234                 0
       
   235             }
       
   236         }
   140     }
   237     }
   141 }
   238 }
   142 
   239 
   143 fn tex_row_copy(land_row: &[u8], tex_row: &mut [u32], sprite_row: &[u32]) {
   240 fn tex_row_copy(land_row: &[u8], tex_row: &mut [u32], sprite_row: &[u32]) {
   144     for ((land_v, tex_v), sprite_v) in
   241     for ((land_v, tex_v), sprite_v) in