import type { ComputedRef } from 'vue' import { BLOCK_SIZE, STAGE_WIDTH, STAGE_HEIGHT } from '../level/def' export default function useLightMap( ctx: CanvasRenderingContext2D, x: ComputedRef, y: ComputedRef, tx: ComputedRef, ty: ComputedRef, time: ComputedRef, lightBarrier: ComputedRef, ) { const W = ((STAGE_WIDTH + 2) * BLOCK_SIZE) const H = ((STAGE_HEIGHT + 2) * BLOCK_SIZE) const B = BLOCK_SIZE - 4 // no idea why there is a difference, but it is 4px const playerX = (W - B) / 2 + B / 4 const playerY = H / 2 - B / 2 const playerLightSize = B * 1.8 function getAmbientLightColor() { const t = time.value // Night time (pale bluish dark: hslpicker.com/#2b293d ) if (t > 900 || t < 100) { return `hsl(245, 20%, 20%)` } // Morning hours (gradually more reddish hue) if (t < 250) { const s = Math.round((t - 100) / 1.5) // 0-100% const l = Math.round((t - 100) / 1.875) + 20 // 20-100% return `hsl(0, ${s}%, ${l}%)` } // Evening hours (from neutral white to bluish hue with low saturation) if (t > 700) { const s = 100 - Math.round((t - 700) / 2.5) // 100-20% return `hsl(245, ${s}%, ${s}%)` } // day (neutral white) return `hsl(0, 0%, 100%)` } function drawPlayerLight(sizeMul:number) { const playerLight = ctx.createRadialGradient( playerX - tx.value, playerY - ty.value, 0, playerX - tx.value, playerY - ty.value, playerLightSize * sizeMul ) // Add color stops: white in the center to transparent white playerLight.addColorStop(0.0, "#FFFF"); playerLight.addColorStop(1, "#FFF0"); // Set the fill style and draw a rectangle ctx.fillStyle = playerLight; ctx.fillRect(0, 0, W, H) } function drawLights() { // used for everything above ground const ambientLight = getAmbientLightColor() const surroundingLight = ambientLight.slice(-2) const barrier = lightBarrier.value ctx.fillStyle = ambientLight for (let col = 0; col < W / B; col++) { const level = (barrier[col] - y.value) * B const sw = B const sh = level const sx = col * sw const sy = 0 ctx.fillRect(sx, sy, sw, sh) } // make light columns wider to illuminate surrounding blocks const extra = Math.floor(B / 2) const reflectedLight = ambientLight.slice(0, -1) + ', 50%)' ctx.fillStyle = reflectedLight for (let col = 0; col < W / B; col++) { const level = (barrier[col] - y.value) * B const sw = B const sh = level const sx = col * sw const sy = 0 ctx.fillRect(sx - extra, sy - extra, sw + extra * 2, sh + extra * 2) } // TODO: draw light for candles and torches } return function update() { // first, throw the world in complete darkness ctx.fillStyle = '#000' ctx.fillRect(0, 0, W, H) // second, find and bring light into the world drawLights() // finally, draw the players light // with a size multiplicator which might be later used to // simulate greater illumination with candles or torches drawPlayerLight(1) } }