You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

82 lines
2.3 KiB
TypeScript

import type { ComputedRef } from 'vue'
import { BLOCK_SIZE, STAGE_WIDTH, STAGE_HEIGHT } from '../level/def'
export default function useLightMap(
ctx: CanvasRenderingContext2D,
x: ComputedRef<number>,
y: ComputedRef<number>,
tx: ComputedRef<number>,
ty: ComputedRef<number>,
time: ComputedRef<number>,
lightBarrier: ComputedRef<number[]>,
) {
const W = ((STAGE_WIDTH + 2) * BLOCK_SIZE)
const H = ((STAGE_HEIGHT + 2) * BLOCK_SIZE)
const playerX = (W - BLOCK_SIZE) / 2 + BLOCK_SIZE / 4
const playerY = H / 2 - BLOCK_SIZE / 2
const playerLightSize = BLOCK_SIZE * 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 three color stops
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 drawShadows() {
const barrier = lightBarrier.value
ctx.fillStyle = '#000A'
for (let col = 0; col < W / BLOCK_SIZE; col++) {
const level = (barrier[col] - y.value) * BLOCK_SIZE
const sw = BLOCK_SIZE * 0.935
const sh = H - level
const sx = col * sw
const sy = level * 0.995
ctx.fillRect(sx, sy, sw, sh)
ctx.fillRect(sx, sy + 20, sw, sh)
ctx.fillRect(sx, sy + 40, sw, sh)
}
}
return function update() {
ctx.fillStyle = getAmbientLightColor()
ctx.fillRect(0, 0, W, H)
// TODO: switch from drawing shadows to drawing lights
drawShadows()
drawPlayerLight(1)
}
}