use canvas as light map
parent
3a9d2044e1
commit
3b7ee96f62
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
@ -0,0 +1,80 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, watch, computed } from 'vue'
|
||||
import { BLOCK_SIZE, STAGE_WIDTH, STAGE_HEIGHT } from './level/def'
|
||||
|
||||
export interface Props {
|
||||
x: number,
|
||||
y: number,
|
||||
tx: number,
|
||||
ty: number,
|
||||
lightBarrier: number[],
|
||||
time: number,
|
||||
}
|
||||
const props = defineProps<Props>()
|
||||
|
||||
// TODO: use OffscreenCanvas and a WebWorker?
|
||||
const lightMapEl = ref<HTMLCanvasElement | undefined>(undefined)
|
||||
const W = ((STAGE_WIDTH + 2) * BLOCK_SIZE) / 2
|
||||
const H = ((STAGE_HEIGHT + 2) * BLOCK_SIZE) / 2
|
||||
|
||||
const playerX = (W - BLOCK_SIZE) / 4
|
||||
const playerY = H / 4 - BLOCK_SIZE / 2
|
||||
const playerLightSize = BLOCK_SIZE / 3
|
||||
|
||||
function drawPlayerLight(ctx: CanvasRenderingContext2D) {
|
||||
|
||||
const playerLight = ctx.createRadialGradient(
|
||||
playerX - props.tx / 4, playerY - props.ty / 4, 0,
|
||||
playerX - props.tx / 4, playerY - props.ty / 4, playerLightSize
|
||||
)
|
||||
|
||||
// Add three color stops
|
||||
playerLight.addColorStop(0.0, "#FFFF");
|
||||
playerLight.addColorStop(1, "#F0F0");
|
||||
|
||||
// Set the fill style and draw a rectangle
|
||||
ctx.fillStyle = playerLight;
|
||||
ctx.fillRect(0, 0, W, H)
|
||||
}
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
const canvas = lightMapEl.value
|
||||
const ctx = canvas?.getContext('2d')
|
||||
if (!ctx) return
|
||||
|
||||
watch(props, () => {
|
||||
const t = props.time
|
||||
|
||||
if (t > 900 || t < 100) {
|
||||
ctx.fillStyle = `hsl(0, 0%, 20%)`
|
||||
} else if (t < 250) {
|
||||
const s = Math.round((t - 100) / 1.5) // 0-100%
|
||||
const l = Math.round((t - 100) / 1.875) + 20 // 20-100%
|
||||
ctx.fillStyle = `hsl(0, ${s}%, ${l}%)`
|
||||
// } else if (t < 700) {
|
||||
// ctx.fillStyle = `hsl(0, ${}%, ${}%)`
|
||||
} else {
|
||||
ctx.fillStyle = `hsl(0, 0%, 100%)`
|
||||
}
|
||||
ctx.fillRect(0, 0, W, H)
|
||||
drawPlayerLight(ctx)
|
||||
})
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<canvas ref="lightMapEl" :style="{transform: `translate(${tx}px, ${ty}px)`}" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
canvas {
|
||||
position: absolute;
|
||||
top: -64px;
|
||||
left: -64px;
|
||||
width: calc(100% + 128px);
|
||||
height: calc(100% + 128px);
|
||||
mix-blend-mode: multiply;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,44 @@
|
||||
import { BLOCK_SIZE, STAGE_WIDTH, STAGE_HEIGHT } from '../level/def'
|
||||
|
||||
export default function useLightMap(ctx: CanvasRenderingContext2D) {
|
||||
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 drawPlayerLight(tx: number, ty: number) {
|
||||
const playerLight = ctx.createRadialGradient(
|
||||
playerX - tx, playerY - ty, 0,
|
||||
playerX - tx, playerY - ty, playerLightSize
|
||||
)
|
||||
|
||||
// Add three color stops
|
||||
playerLight.addColorStop(0.0, "#FFCF");
|
||||
playerLight.addColorStop(1, "#FFC0");
|
||||
|
||||
// Set the fill style and draw a rectangle
|
||||
ctx.fillStyle = playerLight;
|
||||
ctx.fillRect(0, 0, W, H)
|
||||
}
|
||||
|
||||
// TODO: support light barrier
|
||||
function draw(x:number, y:number, tx:number, ty:number, time:number) {
|
||||
if (time > 900 || time < 100) {
|
||||
ctx.fillStyle = `hsl(0, 0%, 20%)`
|
||||
} else if (time < 250) {
|
||||
const s = Math.round((time - 100) / 1.5) // 0-100%
|
||||
const l = Math.round((time - 100) / 1.875) + 20 // 20-100%
|
||||
ctx.fillStyle = `hsl(0, ${s}%, ${l}%)`
|
||||
// } else if (t < 700) {
|
||||
// ctx.fillStyle = `hsl(0, ${}%, ${}%)`
|
||||
} else {
|
||||
ctx.fillStyle = `hsl(0, 0%, 100%)`
|
||||
}
|
||||
ctx.fillRect(0, 0, W, H)
|
||||
drawPlayerLight(tx, ty)
|
||||
}
|
||||
|
||||
return { draw }
|
||||
}
|
Loading…
Reference in New Issue