Prettier town houses

This commit is contained in:
James Melkonian 2021-09-16 21:26:35 -07:00
parent 42fdf0818d
commit 485b057d60
3 changed files with 1969 additions and 122 deletions

View File

@ -24,6 +24,11 @@ pub enum Primitive {
aabb: Aabb<i32>,
inset: i32,
},
Ramp {
aabb: Aabb<i32>,
inset: i32,
dir: u8,
},
Gable {
aabb: Aabb<i32>,
inset: i32,
@ -34,6 +39,8 @@ pub enum Primitive {
Cone(Aabb<i32>),
Sphere(Aabb<i32>),
Plane(Aabr<i32>, Vec3<i32>, Vec2<f32>),
/// A line segment from start to finish point
Segment(LineSegment3<i32>),
/// A sampling function is always a subset of another primitive to avoid
/// needing infinite bounds
Sampling(Id<Primitive>, Box<dyn Fn(Vec3<i32>) -> bool>),
@ -75,6 +82,34 @@ impl Fill {
Primitive::Empty => false,
Primitive::Aabb(aabb) => aabb_contains(*aabb, pos),
Primitive::Ramp { aabb, inset, dir } => {
let inset = (*inset).max(aabb.size().reduce_min());
let inner = match dir {
0 => Aabr {
min: Vec2::new(aabb.min.x - 1 + inset, aabb.min.y),
max: Vec2::new(aabb.max.x, aabb.max.y),
},
1 => Aabr {
min: Vec2::new(aabb.min.x, aabb.min.y),
max: Vec2::new(aabb.max.x - inset, aabb.max.y),
},
2 => Aabr {
min: Vec2::new(aabb.min.x, aabb.min.y - 1 + inset),
max: Vec2::new(aabb.max.x, aabb.max.y),
},
_ => Aabr {
min: Vec2::new(aabb.min.x, aabb.min.y),
max: Vec2::new(aabb.max.x, aabb.max.y - inset),
},
};
aabb_contains(*aabb, pos)
&& (inner.projected_point(pos.xy()) - pos.xy())
.map(|e| e.abs())
.reduce_max() as f32
/ (inset as f32)
< 1.0
- ((pos.z - aabb.min.z) as f32 + 0.5) / (aabb.max.z - aabb.min.z) as f32
},
Primitive::Pyramid { aabb, inset } => {
let inset = (*inset).max(aabb.size().reduce_min());
let inner = Aabr {
@ -102,14 +137,14 @@ impl Fill {
max: Vec2::new(aabb.max.x, aabb.max.y - inset),
}
};
aabb_contains(*aabb, pos) &&
(inner.projected_point(pos.xy()) - pos.xy())
.map(|e| e.abs())
.reduce_max() as f32
/ (inset as f32)
< 1.0
aabb_contains(*aabb, pos)
&& (inner.projected_point(pos.xy()) - pos.xy())
.map(|e| e.abs())
.reduce_max() as f32
/ (inset as f32)
< 1.0
- ((pos.z - aabb.min.z) as f32 + 0.5) / (aabb.max.z - aabb.min.z) as f32
}
},
Primitive::Cylinder(aabb) => {
(aabb.min.z..aabb.max.z).contains(&pos.z)
&& (pos
@ -145,6 +180,12 @@ impl Fill {
.as_()
.dot(*gradient) as i32)
},
Primitive::Segment(segment) => {
(segment.start.x..segment.end.x).contains(&pos.x)
&& (segment.start.y..segment.end.y).contains(&pos.y)
&& (segment.start.z..segment.end.z).contains(&pos.z)
&& segment.as_().distance_to_point(pos.map(|e| e as f32)) < 0.75
},
Primitive::Sampling(a, f) => self.contains_at(tree, *a, pos) && f(pos),
Primitive::Prefab(p) => !matches!(p.get(pos), Err(_) | Ok(StructureBlock::None)),
Primitive::And(a, b) => {
@ -228,6 +269,7 @@ impl Fill {
Primitive::Aabb(aabb) => *aabb,
Primitive::Pyramid { aabb, .. } => *aabb,
Primitive::Gable { aabb, .. } => *aabb,
Primitive::Ramp { aabb, .. } => *aabb,
Primitive::Cylinder(aabb) => *aabb,
Primitive::Cone(aabb) => *aabb,
Primitive::Sphere(aabb) => *aabb,
@ -248,6 +290,10 @@ impl Fill {
};
aabb.made_valid()
},
Primitive::Segment(segment) => Aabb {
min: segment.start,
max: segment.end,
},
Primitive::Sampling(a, _) => self.get_bounds_inner(tree, *a)?,
Primitive::Prefab(p) => p.get_bounds(),
Primitive::And(a, b) => or_zip_with(

View File

@ -192,6 +192,7 @@ enum RoomKind {
Fight,
Boss,
Miniboss,
#[allow(dead_code)]
LavaPlatforming,
}
@ -202,7 +203,7 @@ pub struct Room {
area: Rect<i32, i32>,
height: i32,
pillars: Option<i32>, // Pillars with the given separation
pits: Option<i32>, // Pits filled with lava
pits: Option<i32>, // Pits filled with lava
difficulty: u32,
}
@ -514,17 +515,17 @@ impl Floor {
pits: None,
difficulty: self.difficulty,
}),
// Lava platforming room
1 => self.create_room(Room {
seed: ctx.rng.gen(),
loot_density: 0.0,
kind: RoomKind::LavaPlatforming,
area,
height: ctx.rng.gen_range(10..15),
pillars: None,
pits: Some(1),
difficulty: self.difficulty,
}),
//// Lava platforming room
//1 => self.create_room(Room {
// seed: ctx.rng.gen(),
// loot_density: 0.0,
// kind: RoomKind::LavaPlatforming,
// area,
// height: ctx.rng.gen_range(10..15),
// pillars: None,
// pits: Some(1),
// difficulty: self.difficulty,
//}),
// Fight room with enemies in it
_ => self.create_room(Room {
seed: ctx.rng.gen(),
@ -1259,6 +1260,7 @@ impl Floor {
}));
chests = Some((chest_sprite, chest_sprite_fill));
// If a room has pits, place them
if room.pits.is_some() {
// Make an air pit
let tile_pit = prim(Primitive::Aabb(aabr_with_z(
@ -1281,20 +1283,18 @@ impl Floor {
if room
.pits
.map(|pit_space| {
tile_pos
.map(|e| e.rem_euclid(pit_space) == 0)
.reduce_and()
tile_pos.map(|e| e.rem_euclid(pit_space) == 0).reduce_and()
})
.unwrap_or(false) {
.unwrap_or(false)
{
let platform = prim(Primitive::Aabb(Aabb {
min: (tile_center - Vec2::broadcast(pillar_thickness - 1))
.with_z(floor_z - 7),
max: (tile_center + Vec2::broadcast(pillar_thickness))
.with_z(floor_z),
max: (tile_center + Vec2::broadcast(pillar_thickness)).with_z(floor_z),
}));
fill(platform, Fill::Block(stone));
}
// If a room has pillars, the current tile aligns with the pillar spacing, and
// we're not too close to a wall (i.e. the adjacent tiles are rooms and not
// hallways/solid), place a pillar

File diff suppressed because it is too large Load Diff