Skip to content
Flecs v4.1
script/20_city_grid

  • Flecs Script

    View on GitHub

    using flecs.script
    const PI = 3.1415926
    struct Position(x: f32, y: f32, z: f32)
    struct Rotation(x: f32, y: f32, z: f32)
    struct Box(x: f32, y: f32, z: f32)
    struct Rgb(r: u8, g: u8, b: u8)
    const stone: Rgb = {236, 224, 200}
    const stoneDark: Rgb = {212, 196, 168}
    const trim: Rgb = {250, 246, 236}
    const zinc: Rgb = {104, 116, 130}
    const iron: Rgb = {44, 48, 54}
    const glass: Rgb = {138, 178, 196}
    const wood: Rgb = {74, 52, 40}
    const brass: Rgb = {222, 184, 96}
    const asphalt: Rgb = {72, 72, 78}
    const paint: Rgb = {232, 232, 226}
    const pavement: Rgb = {188, 182, 170}
    const granite: Rgb = {132, 130, 128}
    const awningRed: Rgb = {186, 62, 58}
    const awningGreen: Rgb = {58, 110, 86}
    interface {
    template Road {
    prop size: f32 = 3
    prop width: f32 = 1
    }
    template Intersection {
    prop width: f32 = 1
    }
    template Facade {
    prop width: f32 = 4
    prop height: f32 = 2
    prop depth: f32 = 0.25
    }
    template Building {
    prop width: f32 = 3
    prop floors: i32 = 3
    prop ground_facade: template interface.Facade
    prop floor_facade: template interface.Facade
    prop roof_facade: template interface.Facade
    }
    template Block {
    prop x: i32 = 1
    prop z: i32 = 1
    prop size: i32 = 1
    prop building: template interface.Building
    }
    }
    template SquareLayout {
    prop object: template
    prop size = 1.0
    const offset = size / 2
    for i in 0..4 {
    const angle = i * PI / 2
    {
    object
    Position: {offset * math.cos(angle), 0, -offset * math.sin(angle)}
    Rotation: {y: angle}
    }
    }
    }
    template SideWalk {
    prop width = 1
    prop length = 8
    prop height = 0.12
    const curb = 0.12
    const slabHeight = height - 0.03
    {
    Position: {-curb / 2, slabHeight / 2, (width - curb) / 2}
    Box: {width - curb, slabHeight, length - width - curb}
    Rgb: pavement
    }
    {
    Position: {(width - curb) / 2, height / 2, curb / 2}
    Box: {curb, height, length - curb}
    Rgb: granite
    }
    }
    template Road : interface.Road {
    Box: {width, 0.1, size}
    Rgb: asphalt
    const stripes: i32 = width / 0.5
    for end in 0..2 {
    for i in 0..stripes {
    {
    Position: {-width / 2 + (i + 0.5) * width / stripes, 0.01, (end * 2 - 1) * (size / 2 - 0.55)}
    Box: {0.22, 0.1, 0.7}
    Rgb: paint
    }
    }
    }
    }
    template Intersection : interface.Intersection {
    Box: {width, 0.1, width}
    Rgb: asphalt
    }
    template Block : interface.Block {
    prop sidewalkSize = 1
    SquareLayout(SideWalk(sidewalkSize, size), size - sidewalkSize)
    building(width: size - sidewalkSize * 2) { }
    }
    template Building : interface.Building {
    const groundHeight = 1.8
    const floorHeight = 1.4
    const roofHeight = 1.2
    SquareLayout(ground_facade(width, groundHeight), width - ground_facade.depth)
    for i in 1..floors {
    SquareLayout(floor_facade(width, floorHeight), width - floor_facade.depth) {
    Position: {y: groundHeight + (i - 1) * floorHeight}
    }
    }
    roof_facade(width, roofHeight) {
    Position: {y: groundHeight + (floors - 1) * floorHeight}
    }
    }
    template Window {
    prop width = 0.6
    prop height = 1.0
    prop wall = 0.25
    const x = wall / 2
    {
    Position: {x + 0.015, height / 2}
    Box: {0.03, height + 0.12, width + 0.12}
    Rgb: trim
    }
    {
    Position: {x + 0.035, height / 2}
    Box: {0.03, height, width}
    Rgb: glass
    }
    {
    Position: {x + 0.055, height / 2}
    Box: {0.02, height - 0.04, 0.04}
    Rgb: trim
    }
    {
    Position: {x + 0.06, 0.01}
    Box: {0.12, 0.06, width + 0.2}
    Rgb: stoneDark
    }
    {
    Position: {x + 0.1, 0.17}
    Box: {0.02, 0.3, width + 0.16}
    Rgb: iron
    }
    }
    template GroundFacade : interface.Facade {
    const bays: i32 = width / 1.5
    const spacing = width / bays
    const x = depth / 2
    {
    Position: {0, height / 2, depth / 2}
    Box: {depth, height, width - depth}
    Rgb: stoneDark
    }
    {
    Position: {x + 0.09, height - 0.05, 0.09}
    Box: {0.18, 0.1, width + 0.18}
    Rgb: trim
    }
    {
    Position: {x + 0.16, height + 0.14, 0.01}
    Box: {0.02, 0.32, width + 0.32}
    Rgb: iron
    }
    {
    Position: {x + 0.16, height + 0.3, 0.02}
    Box: {0.04, 0.03, width + 0.32}
    Rgb: iron
    }
    for i in 0..bays {
    const z = -width / 2 + spacing * (i + 0.5)
    if i == bays / 2 {
    {
    Position: {x + 0.015, 0.65, z}
    Box: {0.03, 1.3, 0.84}
    Rgb: trim
    }
    {
    Position: {x + 0.04, 0.6, z}
    Box: {0.04, 1.2, 0.7}
    Rgb: wood
    }
    {
    Position: {x + 0.07, 0.6, z + 0.25}
    Box: {0.03, 0.06, 0.06}
    Rgb: brass
    }
    } else {
    {
    Position: {x + 0.015, 0.75, z}
    Box: {0.03, 1.1, spacing - 0.4}
    Rgb: wood
    }
    {
    Position: {x + 0.035, 0.75, z}
    Box: {0.03, 1.0, spacing - 0.5}
    Rgb: glass
    }
    }
    {
    Position: {x + 0.2, 1.42, z}
    Rotation: {z: -0.4}
    Box: {0.5, 0.03, spacing - 0.3}
    if i % 2 == 0 {
    Rgb: awningRed
    } else {
    Rgb: awningGreen
    }
    }
    }
    }
    template FloorFacade : interface.Facade {
    const bays: i32 = width / 1.5
    const spacing = width / bays
    {
    Position: {0, height / 2, depth / 2}
    Box: {depth, height, width - depth}
    Rgb: stone
    }
    {
    Position: {(depth + 0.1) / 2, 0, 0.05}
    Box: {0.1, 0.06, width + 0.1}
    Rgb: trim
    }
    for i in 0..bays {
    Window(0.6, height - 0.5, depth) {
    Position: {0, 0.25, -width / 2 + spacing * (i + 0.5)}
    }
    }
    }
    template DormerRow {
    prop width = 4.0
    const bays: i32 = width / 1.5
    const spacing = width / bays
    for i in 0..bays {
    const z = -width / 2 + spacing * (i + 0.5)
    {
    Position: {-0.1, 0.42, z}
    Box: {0.5, 0.55, 0.5}
    Rgb: stone
    }
    {
    Position: {-0.1, 0.71, z}
    Box: {0.6, 0.08, 0.6}
    Rgb: zinc
    }
    {
    Position: {0.165, 0.42, z}
    Box: {0.03, 0.4, 0.36}
    Rgb: trim
    }
    {
    Position: {0.185, 0.42, z}
    Box: {0.03, 0.3, 0.26}
    Rgb: glass
    }
    }
    }
    template RoofFacade : interface.Facade {
    const steps = 4
    const stepHeight = height * 0.6 / steps
    const inset = 0.14
    const base = width + 0.3
    {
    Position: {y: 0.06}
    Box: {width + 0.4, 0.12, width + 0.4}
    Rgb: trim
    }
    for i in 0..steps {
    {
    Position: {y: 0.12 + stepHeight * (i + 0.5)}
    Box: {base - inset * 2 * i, stepHeight, base - inset * 2 * i}
    Rgb: zinc
    }
    }
    SquareLayout(DormerRow(width), base) {
    Position: {y: 0.12}
    }
    }
    template City {
    prop width = 3
    prop depth = 3
    prop block : template interface.Block
    prop road : template interface.Road
    prop intersection : template interface.Intersection
    prop cellSize = 7
    prop roadWidth = 2
    const gridSize = cellSize + roadWidth
    {
    Position: {x: -(gridSize * (width - 1)) / 2, z: -(gridSize * (depth - 1)) / 2}
    for x in 0..width {
    for z in 0..depth {
    const gp: Position = {gridSize * x, 0, gridSize * z}
    block(x, z, cellSize) {
    Position: gp
    }
    if x < width - 1 {
    road(cellSize, roadWidth) {
    Position: {gp.x + gridSize / 2, 0, gp.z}
    }
    }
    if z < depth - 1 {
    road(cellSize, roadWidth) {
    Position: {gp.x, 0, gp.z + gridSize / 2}
    Rotation: {y: PI / 2}
    }
    }
    if x < width - 1 && z < depth - 1 {
    intersection(roadWidth) {
    Position: {gp.x + gridSize / 2, 0, gp.z + gridSize / 2}
    }
    }
    }
    }
    }
    }
    City(3, 3,
    block: Block(
    sidewalkSize: 1,
    building: Building(
    floors: 4,
    ground_facade: GroundFacade,
    floor_facade: FloorFacade,
    roof_facade: RoofFacade)),
    road: Road,
    intersection: Intersection)