Skip to content

Instantly share code, notes, and snippets.

@nrkn
Created March 7, 2022 09:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nrkn/9a71bc5255833265e4e5d827e61a2560 to your computer and use it in GitHub Desktop.
Save nrkn/9a71bc5255833265e4e5d827e61a2560 to your computer and use it in GitHub Desktop.
Kowloon Walled City Pixel Mapper for Scapeshop
const firstFloor = 0
const maxFloors = 12
const groundDensity = 0.7
const roofDensity = 0.8
export const pixelMapper = ({ r, g, b }) => {
if (r === 0 && g === 0 && b === 0) return []
const floor = r / 255
const middleDensity = g / 255
const height = b / 255
let floors = Math.floor(height * maxFloors) + 1
const voxels = []
for (let i = 0; i < floors; i++) {
const h = i + firstFloor
const isBase = h === 0
const isGroundFloor = h > 0 && h <= 2
const isRoof = i === floors - 1
const isMiddle = h > 2 && !isRoof
if (isBase) {
if (floor > 0) {
voxels.push({ t: 15, h: 0 })
}
continue
}
const district = Math.floor(height * (colorSchemes.length - 1))
const t = getColor(district)
if (isGroundFloor) {
const isBuilding = floor > 0.66
if (isBuilding) {
if (h > 1 && Math.random() > groundDensity) continue
voxels.push({ t, h })
}
continue
}
if (isMiddle) {
if (middleDensity === 0) continue
if (Math.random() > middleDensity) continue
voxels.push({ t, h })
continue
}
if (isRoof) {
if (Math.random() > roofDensity) continue
voxels.push({ t, h })
continue
}
}
return voxels
}
// color schemes
const ANY = -1
const ORANGE_D = 0
const ORANGE = 1
const ORANGE_B = 2
const YELLOW_D = 2
const YELLOW = 3
const YELLOW_B = 4
const GREEN_D = 5
const GREEN = 6
const GREEN_B = 7
const BLUE_D = 8
const BLUE = 9
const BLUE_B = 10
const TEAL_D = 6
const TEAL = 7
const TEAL_B = 8
const WHITE_D = 12
const WHITE = 13
const WHITE_B = 14
const cs = (value, size) => ({ value, size })
const standardMix = (color, dark, bright) => [
cs(color, 6),
cs(dark, 1),
cs(bright, 1)
]
const repeatStop = ({ value, size }, repeat) => ({ value, size: size * repeat })
const repeatStops = (stops, repeat) => stops.map(s => repeatStop(s, repeat))
const combineStops = (...stops) => {
const map = new Map()
for (const colorMix of stops) {
for (const mix of colorMix) {
const { value, size } = mix
let c = map.get(value)
if (c === undefined) {
c = 0
map.set(value, 0)
}
map.set(value, size + c)
}
}
return [...map.entries()].map(([value, size]) => ({ value, size }))
}
const sumSize = (size, stop) => size + stop.size
const totalSize = (stops) => stops.reduce(sumSize, 0)
const sample = (stops, x) => {
if (stops.length === 0)
throw Error('Empty array')
const total = totalSize(stops)
const target = total * x
// 0..1
x = Math.min(Math.max(x, 0), 1)
let size = 0
let i
for (i = 0; i < stops.length; i++) {
if (size >= target && i > 0) {
break
}
size += stops[i].size
}
const targetItem = stops[i - 1]
if (targetItem) {
return targetItem.value
}
throw Error(`Expected target, ${JSON.stringify({ total, target, size, i })}`)
}
const getColor = district => {
if (Math.random() < 0.02) return Math.floor(Math.random() * 15)
return sample(colorSchemes[district], Math.random())
}
const whiteMix = standardMix(WHITE, WHITE_D, WHITE_B)
const tealMix = standardMix(TEAL, TEAL_D, TEAL_B)
const orangeMix = standardMix(ORANGE, ORANGE_D, ORANGE_B)
const greenMix = standardMix(GREEN, GREEN_D, GREEN_B)
const yellowMix = standardMix(YELLOW, YELLOW_D, YELLOW_B)
const blueOrangeMix = [
{ value: BLUE, size: 1 },
{ value: BLUE_D, size: 1 },
{ value: ORANGE, size: 2 }
]
const strongMix = (a, b, c) => combineStops(
repeatStops(a, 80),
repeatStops(b, 15),
repeatStops(c, 5)
)
const midMix = (a, b, c) => combineStops(
repeatStops(a, 60),
repeatStops(b, 30),
repeatStops(c, 10)
)
const whiteStrongMix = strongMix(whiteMix, tealMix, orangeMix)
const whiteMidMix = midMix(whiteMix, tealMix, orangeMix)
const tealStrongMix = strongMix(tealMix, greenMix, whiteMix)
const tealMidMix = midMix(tealMix, greenMix, whiteMix)
const orangeStrongMix = strongMix(orangeMix, yellowMix, whiteMix)
const orangeMidMix = midMix(orangeMix, yellowMix, whiteMix)
const greenStrongMix = strongMix(greenMix, tealMix, whiteMix)
const greenMidMix = midMix(greenMix, tealMix, whiteMix)
const yellowStrongMix = strongMix(yellowMix, orangeMix, whiteMix)
const yellowMidMix = midMix(yellowMix, orangeMix, whiteMix)
const blueOrangeStrongMix = strongMix(blueOrangeMix, tealMix, orangeMix)
const blueOrangeMidMix = midMix(blueOrangeMix, tealMix, orangeMix)
const colorSchemes = [
whiteStrongMix,
whiteMidMix,
tealStrongMix,
whiteMidMix,
whiteStrongMix,
whiteMidMix,
tealMidMix,
whiteMidMix,
whiteStrongMix,
whiteMidMix,
orangeMidMix,
whiteMidMix,
whiteStrongMix,
whiteMidMix,
orangeStrongMix,
whiteMidMix,
whiteStrongMix,
whiteMidMix,
greenMidMix,
whiteMidMix,
whiteStrongMix,
whiteMidMix,
greenStrongMix,
whiteMidMix,
whiteStrongMix,
whiteMidMix,
yellowMidMix,
whiteMidMix,
whiteStrongMix,
whiteMidMix,
yellowStrongMix,
whiteMidMix,
whiteStrongMix,
whiteMidMix,
blueOrangeMidMix,
whiteMidMix,
whiteStrongMix,
whiteMidMix,
blueOrangeStrongMix,
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment