Draw terrains within their relevant positions on the hex grid #22

Merged
savanni merged 3 commits from terrain-tiling into main 2023-02-12 03:24:54 +00:00
1 changed files with 52 additions and 68 deletions
Showing only changes of commit 8520b18629 - Show all commits

View File

@ -18,7 +18,7 @@ use gtk::{
gdk_pixbuf::Pixbuf, gio, prelude::*, subclass::prelude::*, Application, CompositeTemplate, gdk_pixbuf::Pixbuf, gio, prelude::*, subclass::prelude::*, Application, CompositeTemplate,
DrawingArea, Label, DrawingArea, Label,
}; };
use image::io::Reader as ImageReader; use image::{io::Reader as ImageReader, DynamicImage};
use std::{cell::RefCell, io::Cursor, rc::Rc}; use std::{cell::RefCell, io::Cursor, rc::Rc};
const APP_ID: &'static str = "com.luminescent-dreams.hex-grid"; const APP_ID: &'static str = "com.luminescent-dreams.hex-grid";
@ -27,7 +27,7 @@ const MAP_RADIUS: usize = 3;
const DRAWING_ORIGIN: (f64, f64) = (1024. / 2., 768. / 2.); const DRAWING_ORIGIN: (f64, f64) = (1024. / 2., 768. / 2.);
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
enum Tile { enum Terrain {
Empty, Empty,
Mountain, Mountain,
Grasslands, Grasslands,
@ -38,28 +38,13 @@ enum Tile {
Swamp, Swamp,
} }
impl Tile { impl Default for Terrain {
fn color(&self) -> (f64, f64, f64) {
match self {
Self::Empty => (0., 0., 0.),
Self::Mountain => (0.5, 0.5, 0.5),
Self::Grasslands => (0., 1., 0.),
Self::ShallowWater => (0.5, 0.5, 1.),
Self::DeepWater => (0., 0., 1.),
Self::Badlands => (0.5, 0.25, 0.),
Self::Desert => (1., 1., 0.),
Self::Swamp => (0., 0.25, 0.),
}
}
}
impl Default for Tile {
fn default() -> Self { fn default() -> Self {
Self::Empty Self::Empty
} }
} }
impl From<&str> for Tile { impl From<&str> for Terrain {
fn from(s: &str) -> Self { fn from(s: &str) -> Self {
match s { match s {
"m" => Self::Mountain, "m" => Self::Mountain,
@ -74,12 +59,43 @@ impl From<&str> for Tile {
} }
} }
impl From<String> for Tile { impl From<String> for Terrain {
fn from(s: String) -> Self { fn from(s: String) -> Self {
Self::from(s.as_ref()) Self::from(s.as_ref())
} }
} }
struct Tile {
terrain: Terrain,
image: Pixbuf,
}
impl Tile {
fn new(source: &DynamicImage, terrain: Terrain) -> Tile {
let image = match terrain {
Terrain::DeepWater => pixbuf_from_image_tile(source.clone().crop(0, 0, 100, 88)),
Terrain::ShallowWater => pixbuf_from_image_tile(source.clone().crop(100, 0, 100, 88)),
Terrain::Grasslands => pixbuf_from_image_tile(source.clone().crop(200, 0, 100, 88)),
Terrain::Desert => pixbuf_from_image_tile(source.clone().crop(300, 0, 100, 88)),
Terrain::Mountain => pixbuf_from_image_tile(source.clone().crop(0, 88, 100, 88)),
Terrain::Badlands => pixbuf_from_image_tile(source.clone().crop(100, 88, 100, 88)),
Terrain::Swamp => pixbuf_from_image_tile(source.clone().crop(0, 176, 100, 88)),
Terrain::Empty => pixbuf_from_image_tile(source.clone().crop(300, 176, 100, 88)),
};
Tile { terrain, image }
}
fn render_on_context(&self, context: &Context, translate_x: f64, translate_y: f64) {
context.save().unwrap();
context.append_path(&hexagon_path(context, translate_x, translate_y, 100., 88.));
context.clip();
context.set_source_pixbuf(&self.image, translate_x, translate_y);
context.paint().expect("paint should succeed");
context.restore().unwrap();
}
}
fn main() { fn main() {
gio::resources_register_include!("com.luminescent-dreams.hex-grid.gresource") gio::resources_register_include!("com.luminescent-dreams.hex-grid.gresource")
.expect("Failed to register resources"); .expect("Failed to register resources");
@ -133,7 +149,7 @@ impl ObjectImpl for HexGridWindowPrivate {
.expect("map should be in the bundle") .expect("map should be in the bundle")
.to_vec(); .to_vec();
let hex_map = parse_data::<Tile>(String::from_utf8(map_text_resource).unwrap().lines()); let hex_map = parse_data::<Terrain>(String::from_utf8(map_text_resource).unwrap().lines());
let terrain_data = resources_lookup_data( let terrain_data = resources_lookup_data(
"/com/luminescent-dreams/hex-grid/terrain.ppm", "/com/luminescent-dreams/hex-grid/terrain.ppm",
@ -143,27 +159,15 @@ impl ObjectImpl for HexGridWindowPrivate {
let reader = ImageReader::new(Cursor::new(terrain_data)) let reader = ImageReader::new(Cursor::new(terrain_data))
.with_guessed_format() .with_guessed_format()
.unwrap(); .unwrap();
let image = reader.decode().unwrap(); let image = reader.decode().unwrap();
let deep_water = Tile::new(&image, Terrain::DeepWater);
let image_deep_water = pixbuf_from_image_tile(image.clone().crop(0, 0, 100, 88)); let shallow_water = Tile::new(&image, Terrain::ShallowWater);
let image_shallow_water = pixbuf_from_image_tile(image.clone().crop(100, 0, 100, 88)); let grasslands = Tile::new(&image, Terrain::Grasslands);
let image_grasslands = pixbuf_from_image_tile(image.clone().crop(200, 0, 100, 88)); let desert = Tile::new(&image, Terrain::Desert);
let image_desert = pixbuf_from_image_tile(image.clone().crop(300, 0, 100, 88)); let mountain = Tile::new(&image, Terrain::Mountain);
let image_mountain = pixbuf_from_image_tile(image.clone().crop(0, 88, 100, 88)); let badlands = Tile::new(&image, Terrain::Badlands);
let image_badlands = pixbuf_from_image_tile(image.clone().crop(100, 88, 100, 88)); let swamp = Tile::new(&image, Terrain::Swamp);
let image_swamp = pixbuf_from_image_tile(image.clone().crop(0, 176, 100, 88));
/*
let image_pb = Pixbuf::from_bytes(
&glib::Bytes::from(image.as_bytes()),
gtk::gdk_pixbuf::Colorspace::Rgb,
false,
8,
image.width() as i32,
image.height() as i32,
image.to_rgb8().sample_layout().height_stride as i32,
);
*/
let motion_controller = gtk::EventControllerMotion::new(); let motion_controller = gtk::EventControllerMotion::new();
{ {
@ -197,34 +201,14 @@ impl ObjectImpl for HexGridWindowPrivate {
context.set_line_width(2.); context.set_line_width(2.);
context.save().unwrap(); deep_water.render_on_context(&context, 0., 0.);
context.append_path(&hexagon_path(context, 0., 0., 100., 88.)); shallow_water.render_on_context(&context, 150., 0.);
context.clip(); grasslands.render_on_context(&context, 300., 0.);
context.set_source_pixbuf(&image_deep_water, 0., 0.); desert.render_on_context(&context, 450., 0.);
context.paint().expect("paint should succeed"); mountain.render_on_context(&context, 0., 100.);
context.restore().unwrap(); badlands.render_on_context(&context, 150., 100.);
swamp.render_on_context(&context, 0., 200.);
context.save().unwrap();
context.append_path(&hexagon_path(context, 150., 0., 100., 88.));
context.clip();
context.set_source_pixbuf(&image_shallow_water, 150., 0.);
context.paint().expect("paint should succeed");
context.restore().unwrap();
context.set_source_pixbuf(&image_grasslands, 300., 0.);
context.paint().expect("paint should succeed");
context.set_source_pixbuf(&image_desert, 450., 0.);
context.paint().expect("paint should succeed");
context.set_source_pixbuf(&image_mountain, 0., 100.);
context.paint().expect("paint should succeed");
context.set_source_pixbuf(&image_badlands, 150., 100.);
context.paint().expect("paint should succeed");
context.set_source_pixbuf(&image_swamp, 0., 200.);
context.paint().expect("paint should succeed");
/* /*
for coordinate in vec![AxialAddr::origin()] for coordinate in vec![AxialAddr::origin()]
.into_iter() .into_iter()