More work on castles

This commit is contained in:
Synis 2021-03-06 17:21:03 +01:00 committed by Joshua Barretto
parent f7f7f12a38
commit c35780d05b
3 changed files with 196 additions and 35 deletions

View File

@ -5,7 +5,7 @@ mod tile;
use self::{
gen::{Fill, Primitive, Structure},
plot::{Plot, PlotKind},
tile::{HazardKind, Tile, TileGrid, TileKind, TILE_SIZE},
tile::{HazardKind, Tile, TileGrid, TileKind, KeepKind, Ori, TILE_SIZE},
};
use crate::{
site::SpawnRules,
@ -16,8 +16,7 @@ use common::{
astar::Astar,
lottery::Lottery,
spiral::Spiral2d,
store::{Id, Store},
terrain::{Block, BlockKind, SpriteKind, TerrainChunkSize},
store::{Id, Store}, terrain::{Block, BlockKind, SpriteKind, TerrainChunkSize},
vol::RectVolSize,
};
use hashbrown::hash_map::DefaultHashBuilder;
@ -405,12 +404,12 @@ impl Site {
// Walls
site.blit_aabr(aabr, Tile {
kind: TileKind::Wall,
kind: TileKind::Wall(Ori::North),
plot: Some(plot),
});
let tower = Tile {
kind: TileKind::Castle,
kind: TileKind::Tower,
plot: Some(plot),
};
site.tiles
@ -441,10 +440,25 @@ impl Site {
max: aabr.center() + 3,
},
Tile {
kind: TileKind::Castle,
kind: TileKind::Wall(Ori::North),
plot: Some(plot),
},
);
site.tiles.set(Vec2::new(aabr.center().x + 2, aabr.center().y + 2), tower.clone());
site.tiles.set(Vec2::new(aabr.center().x + 2, aabr.center().y - 3), tower.clone());
site.tiles.set(Vec2::new(aabr.center().x - 3, aabr.center().y + 2), tower.clone());
site.tiles.set(Vec2::new(aabr.center().x - 3, aabr.center().y - 3), tower.clone());
site.blit_aabr(
Aabr {
min: aabr.center() - 2,
max: aabr.center() + 2,
},
Tile {
kind: TileKind::Keep(tile::KeepKind::Middle),
plot: Some(plot),
},
);
castles += 1;
}

View File

@ -43,57 +43,182 @@ impl Structure for Castle {
let parapet_height = 2;
let parapet_width = 1;
let downwards = 40;
let tower_height = 12;
let keep_levels = 3;
let keep_level_height = 8;
let keep_height = wall_height + keep_levels * keep_level_height + 1;
for x in 0..self.tile_aabr.size().w {
for y in 0..self.tile_aabr.size().h {
let tile_pos = self.tile_aabr.min + Vec2::new(x, y);
let wpos_center = site.tile_center_wpos(tile_pos);
let wpos = site.tile_wpos(tile_pos);
let ori = if x == 0 || x == self.tile_aabr.size().w - 1 {
Vec2::new(1, 0)
} else {
Vec2::new(0, 1)
};
let ori_tower_x = if x == 0 {
Vec2::new(1, 0)
} else {
Vec2::new(0, 0)
};
let ori_tower_y = if y == 0 {
Vec2::new(0, 1)
} else {
Vec2::new(0, 0)
};
let ori_tower = ori_tower_x + ori_tower_y;
match site.tiles.get(tile_pos).kind.clone() {
TileKind::Wall => {
let ori = if x == 0 || x == self.tile_aabr.size().w - 1 {
Vec2::new(1, 0)
} else {
Vec2::new(0, 1)
};
TileKind::Wall(orientation) => {
let wall = prim(Primitive::Aabb(Aabb {
min: wpos.with_z(self.alt),
max: (wpos + 7).with_z(self.alt + wall_height + parapet_height),
max: (wpos + 6).with_z(self.alt + wall_height + parapet_height),
}));
let cut_path = prim(Primitive::Aabb(Aabb {
min: Vec3::new(
wpos.x + parapet_width * ori.x,
wpos.y + parapet_width * ori.y,
self.alt + wall_height,
),
max: Vec3::new(
wpos.x + (7 - parapet_width) * ori.x + 7 * ori.y,
wpos.y + (7 - parapet_width) * ori.y + 7 * ori.x,
self.alt + wall_height + parapet_height,
),
min: (wpos + (parapet_width * ori) as Vec2<i32>)
.with_z(self.alt + wall_height),
max: (wpos
+ (6 - parapet_width) * ori as Vec2<i32>
+ 6 * ori.yx() as Vec2<i32>)
.with_z(self.alt + wall_height + parapet_height),
}));
let cut_sides1 = prim(Primitive::Aabb(Aabb {
min: Vec3::new(wpos.x, wpos.y, self.alt + wall_height + 1),
max: Vec3::new(
wpos.x + 7 * ori.x + ori.y,
wpos.y + 7 * ori.y + ori.x,
wpos.x + 6 * ori.x + ori.y,
wpos.y + 6 * ori.y + ori.x,
self.alt + wall_height + parapet_height,
),
}));
let pillar_start = prim(Primitive::Aabb(Aabb {
min: Vec3::new(wpos.x, wpos.y - 1, self.alt),
max: Vec3::new(wpos.x + 1, wpos.y + 7, self.alt + wall_height),
}));
let pillar_end = prim(Primitive::Aabb(Aabb {
min: Vec3::new(wpos.x + 5, wpos.y - 1, self.alt),
max: Vec3::new(wpos.x + 6, wpos.y + 7, self.alt + wall_height),
}));
let pillars = prim(Primitive::Or(pillar_start, pillar_end));
fill(
prim(Primitive::Xor(wall, cut_path)),
prim(Primitive::Or(wall, pillars)),
Fill::Block(Block::new(BlockKind::Rock, Rgb::new(33, 33, 33))),
);
fill(cut_sides1, Fill::Block(Block::air(SpriteKind::Empty)));
fill(cut_path, Fill::Block(Block::empty()));
fill(cut_sides1, Fill::Block(Block::empty()));
},
_ => {
TileKind::Tower => {
let tower_lower = prim(Primitive::Aabb(Aabb {
min: wpos.with_z(self.alt),
max: (wpos + 6).with_z(self.alt + wall_height + tower_height),
}));
let tower_lower_inner_x = prim(Primitive::Aabb(Aabb {
min: Vec3::new(
wpos.x + 1 * ori_tower.x,
wpos.y + parapet_width,
self.alt + wall_height,
),
max: Vec3::new(
wpos.x + 6 + ori_tower.x - 1,
wpos.y + 6 - parapet_width,
self.alt + wall_height + tower_height / 3,
),
}));
let tower_lower_inner_y = prim(Primitive::Aabb(Aabb {
min: Vec3::new(
wpos.x + parapet_width,
wpos.y + 1 * ori_tower.y,
self.alt + wall_height,
),
max: Vec3::new(
wpos.x + 6 - parapet_width,
wpos.y + 6 + ori_tower.y - 1,
self.alt + wall_height + tower_height / 3,
),
}));
let tower_lower_inner =
prim(Primitive::Or(tower_lower_inner_x, tower_lower_inner_y));
fill(
prim(Primitive::Aabb(Aabb {
min: wpos_center.with_z(self.alt + 9),
max: (wpos_center + 1).with_z(self.alt + 10),
})),
Fill::Block(Block::new(BlockKind::Rock, Rgb::new(255, 255, 255))),
prim(Primitive::Xor(tower_lower, tower_lower_inner)),
Fill::Block(Block::new(BlockKind::Rock, Rgb::new(33, 33, 33))),
);
let tower_upper = prim(Primitive::Aabb(Aabb {
min: Vec3::new(
wpos.x - 1,
wpos.y - 1,
self.alt + wall_height + tower_height - 3 as i32,
),
max: Vec3::new(
wpos.x + 7,
wpos.y + 7,
self.alt + wall_height + tower_height - 1 as i32,
),
}));
let tower_upper2 = prim(Primitive::Aabb(Aabb {
min: Vec3::new(
wpos.x - 2,
wpos.y - 2,
self.alt + wall_height + tower_height - 1 as i32,
),
max: Vec3::new(
wpos.x + 8,
wpos.y + 8,
self.alt + wall_height + tower_height,
),
}));
fill(
prim(Primitive::Or(tower_upper, tower_upper2)),
Fill::Block(Block::new(BlockKind::Rock, Rgb::new(33, 33, 33))),
);
let roof_lip = 1;
let roof_height = 8 / 2 + roof_lip + 1;
// Roof
fill(
prim(Primitive::Pyramid {
aabb: Aabb {
min: (wpos - 2 - roof_lip)
.with_z(self.alt + wall_height + tower_height),
max: (wpos + 8 + roof_lip).with_z(
self.alt + wall_height + tower_height + roof_height,
),
},
inset: roof_height,
}),
Fill::Block(Block::new(BlockKind::Wood, Rgb::new(116, 20, 20))),
);
},
TileKind::Keep(kind) => {
match kind {
tile::KeepKind::Middle => {
for i in 0..keep_levels + 1 {
let height = keep_level_height * i;
fill(
prim(Primitive::Aabb(Aabb {
min: wpos.with_z(self.alt + height),
max: (wpos + 6).with_z(self.alt + height + 1),
})),
Fill::Block(Block::new(
BlockKind::Rock,
Rgb::new(89, 44, 14),
)),
);
}
},
tile::KeepKind::Corner => {},
tile::KeepKind::Wall(orientation) => {
for i in 0..keep_levels + 1 {
let height = keep_level_height * i;
// TODO clamp value in case of big heights
let window_height = keep_level_height - 3;
}
},
}
},
_ => {},
}
}
}

View File

@ -182,7 +182,9 @@ pub enum TileKind {
Road { a: u16, b: u16, w: u16 },
Building,
Castle,
Wall,
Wall(Ori),
Tower,
Keep(KeepKind),
}
#[derive(Clone, PartialEq)]
@ -209,7 +211,7 @@ impl Tile {
pub fn is_obstacle(&self) -> bool {
matches!(
self.kind,
TileKind::Hazard(_) | TileKind::Building | TileKind::Castle | TileKind::Wall
TileKind::Hazard(_) | TileKind::Building | TileKind::Castle | TileKind::Wall(_)
)
}
}
@ -219,3 +221,23 @@ pub enum HazardKind {
Water,
Hill { gradient: f32 },
}
#[derive(Copy, Clone, PartialEq)]
pub enum KeepKind {
Middle,
Corner,
Wall(Ori),
}
#[repr(u8)]
#[derive(Copy, Clone, PartialEq)]
pub enum Ori {
North = 0,
East = 1,
South = 2,
West = 3,
}
impl Ori {
pub fn dir(self) -> Vec2<i32> {CARDINALS[self as u8 as usize]}
}