Gable primitive and dungeon lava rooms

This commit is contained in:
James Melkonian 2021-07-29 18:20:53 -07:00
parent bc4455afe4
commit 42fdf0818d
3 changed files with 108 additions and 5 deletions

View File

@ -125,6 +125,14 @@ impl Block {
}
}
#[inline]
pub const fn lava(sprite: SpriteKind) -> Self {
Self {
kind: BlockKind::Lava,
attr: [sprite as u8, 0, 0],
}
}
#[inline]
pub const fn empty() -> Self { Self::air(SpriteKind::Empty) }

View File

@ -24,6 +24,12 @@ pub enum Primitive {
aabb: Aabb<i32>,
inset: i32,
},
Gable {
aabb: Aabb<i32>,
inset: i32,
// X axis parallel or Y axis parallel
dir: bool,
},
Cylinder(Aabb<i32>),
Cone(Aabb<i32>),
Sphere(Aabb<i32>),
@ -83,6 +89,27 @@ impl Fill {
< 1.0
- ((pos.z - aabb.min.z) as f32 + 0.5) / (aabb.max.z - aabb.min.z) as f32
},
Primitive::Gable { aabb, inset, dir } => {
let inset = (*inset).max(aabb.size().reduce_min());
let inner = if *dir {
Aabr {
min: Vec2::new(aabb.min.x - 1 + inset, aabb.min.y),
max: Vec2::new(aabb.max.x - inset, aabb.max.y),
}
} else {
Aabr {
min: Vec2::new(aabb.min.x, aabb.min.y - 1 + inset),
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::Cylinder(aabb) => {
(aabb.min.z..aabb.max.z).contains(&pos.z)
&& (pos
@ -200,6 +227,7 @@ impl Fill {
Primitive::Empty => return None,
Primitive::Aabb(aabb) => *aabb,
Primitive::Pyramid { aabb, .. } => *aabb,
Primitive::Gable { aabb, .. } => *aabb,
Primitive::Cylinder(aabb) => *aabb,
Primitive::Cone(aabb) => *aabb,
Primitive::Sphere(aabb) => *aabb,

View File

@ -192,6 +192,7 @@ enum RoomKind {
Fight,
Boss,
Miniboss,
LavaPlatforming,
}
pub struct Room {
@ -201,6 +202,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
difficulty: u32,
}
@ -393,6 +395,7 @@ impl Floor {
area: Rect::from((stair_tile - tile_offset - 1, Extent2::broadcast(3))),
height: STAIR_ROOM_HEIGHT,
pillars: None,
pits: None,
difficulty,
});
if final_level {
@ -407,6 +410,7 @@ impl Floor {
)),
height: height as i32,
pillars: Some(2),
pits: None,
difficulty,
});
} else {
@ -418,6 +422,7 @@ impl Floor {
area: Rect::from((new_stair_tile - tile_offset - 1, Extent2::broadcast(3))),
height: STAIR_ROOM_HEIGHT,
pillars: None,
pits: None,
difficulty,
});
this.tiles.set(
@ -506,6 +511,18 @@ impl Floor {
area,
height: ctx.rng.gen_range(15..20),
pillars: Some(ctx.rng.gen_range(2..=4)),
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,
}),
// Fight room with enemies in it
@ -520,6 +537,7 @@ impl Floor {
} else {
None
},
pits: None,
difficulty: self.difficulty,
}),
};
@ -631,7 +649,7 @@ impl Floor {
RoomKind::Boss => {
room.fill_boss_cell(supplement, tile_wcenter, wpos2d, tile_pos)
},
RoomKind::Peaceful => {},
RoomKind::Peaceful | RoomKind::LavaPlatforming => {},
}
}
}
@ -1018,8 +1036,22 @@ impl Floor {
};
let floor_prim = prim(Primitive::Aabb(floor_aabb));
// This is copied from `src/layer/mod.rs`. It should be moved into
// a util file somewhere
let noisy_color = |color: Rgb<u8>, factor: u32| {
let nz = RandomField::new(0).get(Vec3::new(floor_corner.x, floor_corner.y, floor_z));
color.map(|e| {
(e as u32 + nz % (factor * 2))
.saturating_sub(factor)
.min(255) as u8
})
};
// Declare the various kinds of blocks that will be used as fills
let vacant = Block::air(SpriteKind::Empty);
// FIXME: Lava and stone color hardcoded here, it is available in colors.ron
// but that file is not accessed from site2 yet
let lava = Block::new(BlockKind::Lava, noisy_color(Rgb::new(184, 39, 0), 8));
let stone = Block::new(BlockKind::Rock, Rgb::new(150, 150, 175));
let stone_purple = Block::new(BlockKind::GlowingRock, Rgb::new(96, 0, 128));
@ -1227,10 +1259,45 @@ impl Floor {
}));
chests = Some((chest_sprite, chest_sprite_fill));
// 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
if room.pits.is_some() {
// Make an air pit
let tile_pit = prim(Primitive::Aabb(aabr_with_z(
tile_aabr,
floor_z - 7..floor_z,
)));
let tile_pit = prim(Primitive::Diff(tile_pit, wall_contours));
fill(tile_pit, Fill::Block(vacant));
// Fill with lava
let tile_lava = prim(Primitive::Aabb(aabr_with_z(
tile_aabr,
floor_z - 7..floor_z - 5,
)));
let tile_lava = prim(Primitive::Diff(tile_lava, wall_contours));
//pits.push(tile_pit);
//pits.push(tile_lava);
fill(tile_lava, Fill::Block(lava));
}
if room
.pits
.map(|pit_space| {
tile_pos
.map(|e| e.rem_euclid(pit_space) == 0)
.reduce_and()
})
.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),
}));
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
if room
.pillars
.map(|pillar_space| {