time-related brightness controlled by light-map

main
Norman Köhring 1 year ago
parent 3b7ee96f62
commit d75f862380

@ -11,13 +11,13 @@ import useInput from './util/useInput'
import usePlayer from './util/usePlayer' import usePlayer from './util/usePlayer'
import useLightMap from './util/useLightMap' import useLightMap from './util/useLightMap'
const { updateTime, time, clock } = useTime() const { updateTime, time, timeOfDay, clock } = useTime()
const { player, direction, dx, dy } = usePlayer() const { player, direction, dx, dy } = usePlayer()
const { inputX, inputY, running, paused, help, inventory } = useInput() const { inputX, inputY, running, paused, help, inventory } = useInput()
const level = createLevel(STAGE_WIDTH + 2, STAGE_HEIGHT + 2) const level = createLevel(STAGE_WIDTH + 2, STAGE_HEIGHT + 2)
const lightMapEl = ref<HTMLCanvasElement | undefined>(undefined) const lightMapEl = ref<HTMLCanvasElement | undefined>(undefined)
let lightMap: ReturnType<typeof useLightMap> let updateLightMap: ReturnType<typeof useLightMap>
player.inventory.push( player.inventory.push(
{ name: 'Shovel', type: 'tool', icon: 'shovel', quality: 'bronze', amount: 1 }, { name: 'Shovel', type: 'tool', icon: 'shovel', quality: 'bronze', amount: 1 },
@ -144,7 +144,7 @@ const move = (thisTick: number): void => {
y.value += dy_ * fallMultiplier y.value += dy_ * fallMultiplier
} }
lightMap.draw(floorX.value, floorY.value, tx.value, ty.value, time.value) updateLightMap()
lastTick = thisTick lastTick = thisTick
} }
@ -171,14 +171,14 @@ onMounted(() => {
canvas.width = (BLOCK_SIZE + 2) * STAGE_WIDTH canvas.width = (BLOCK_SIZE + 2) * STAGE_WIDTH
const ctx = canvas.getContext('2d')! const ctx = canvas.getContext('2d')!
lightMap = useLightMap(ctx) updateLightMap = useLightMap(ctx, floorX, floorY, tx, ty, time, lightBarrier)
lastTick = performance.now() lastTick = performance.now()
move(lastTick) move(lastTick)
}) })
</script> </script>
<template> <template>
<div id="field"> <div id="field" :class="timeOfDay">
<div id="blocks" :style="{transform: `translate(${tx}px, ${ty}px)`}"> <div id="blocks" :style="{transform: `translate(${tx}px, ${ty}px)`}">
<template v-for="(row, y) in rows"> <template v-for="(row, y) in rows">

@ -1,3 +1,6 @@
.block, #player {
transition: filter .5s linear;
}
.block { .block {
flex: 0 0 auto; flex: 0 0 auto;
width: var(--block-size); width: var(--block-size);
@ -42,44 +45,15 @@
.block.cave { background-color: #000; } .block.cave { background-color: #000; }
#field .block:hover { outline: 1px solid white; z-index: 10; } #field .block:hover { outline: 1px solid white; z-index: 10; }
.block.sun-3 { filter: brightness(1.0); } .morning0 .block, .morning0 #player {filter: saturate(50%); }
.block.sun-2 { filter: brightness(0.4); } .morning1 .block, .morning1 #player { filter: saturate(100%); }
.block.sun-1 { filter: brightness(0.2); } .morning2 .block, .morning2 #player { filter: saturate(120%); }
.block.sun-0 { filter: brightness(0.0); }
.morning0 .block, .morning0 #player {filter: saturate(50%) brightness(0.6) hue-rotate(-10deg); }
.morning1 .block, .morning1 #player { filter: saturate(100%) brightness(0.8) hue-rotate(-20deg); }
.morning2 .block, .morning2 #player { filter: saturate(200%) hue-rotate(-30deg); }
.morning0 .block.sun-2 { filter: brightness(0); }
.morning1 .block.sun-2 { filter: saturate(100%) brightness(0.2) hue-rotate(-20deg); }
.morning2 .block.sun-2 { filter: saturate(200%) brightness(0.4) hue-rotate(-30deg); }
.morning0 .block.sun-1,
.morning1 .block.sun-1 { filter: brightness(0); }
.morning2 .block.sun-1 { filter: saturate(200%) brightness(0.2) hue-rotate(-30deg); }
.evening0 .block, .evening0 #player { filter: brightness(0.8) hue-rotate(-10deg); }
.evening1 .block, .evening1 #player { filter: brightness(0.6) hue-rotate(-20deg); }
.evening2 .block, .evening2 #player { filter: brightness(0.4) hue-rotate(-10deg) saturate(50%); }
.evening0 .block.sun-2 { filter: brightness(0.3) hue-rotate(-10deg); }
.evening1 .block.sun-2 { filter: brightness(0.2) hue-rotate(-20deg); }
.evening2 .block.sun-2 { filter: brightness(0); }
.evening0 .block.sun-1 { filter: brightness(0.2) hue-rotate(-10deg); }
.evening1 .block.sun-1, .evening2 .block.sun-1 { filter: brightness(0); }
.night .block, .night #player { filter: brightness(0.3) saturate(30%); } .evening0 .block, .evening0 #player { filter: saturate(90%); }
.evening1 .block, .evening1 #player { filter: saturate(70%); }
.evening2 .block, .evening2 #player { filter: saturate(50%); }
.block.sun-0, .night .block, .night #player { filter: saturate(30%); }
.morning0 .block.sun-0,
.morning1 .block.sun-0,
.morning2 .block.sun-0,
.evening0 .block.sun-0,
.evening1 .block.sun-0,
.evening2 .block.sun-0,
.night .block.sun-0 { filter: brightness(0); }
#blocks { #blocks {
position: absolute; position: absolute;
@ -98,4 +72,5 @@
width: calc(100% + var(--block-size) * 2); width: calc(100% + var(--block-size) * 2);
height: calc(100% + var(--block-size) * 2); height: calc(100% + var(--block-size) * 2);
mix-blend-mode: multiply; mix-blend-mode: multiply;
pointer-events: none;
} }

@ -13,6 +13,7 @@ export type Block = {
walkable: boolean, walkable: boolean,
climbable?: boolean, climbable?: boolean,
transparent?: boolean, transparent?: boolean,
illuminated?: boolean,
} }
export type BlockType = export type BlockType =
@ -22,7 +23,7 @@ export type BlockType =
| 'bedrock' | 'cave' | 'bedrock' | 'cave'
export const blockTypes: Record<BlockType, Block> = { export const blockTypes: Record<BlockType, Block> = {
air: { type: 'air', hp: Infinity, walkable: true, transparent: true }, air: { type: 'air', hp: Infinity, walkable: true, transparent: true, illuminated: true },
grass: { type: 'grass', hp: 5, walkable: false }, grass: { type: 'grass', hp: 5, walkable: false },
treeCrown: { type: 'treeCrown', hp: 1, walkable: true, transparent: true }, treeCrown: { type: 'treeCrown', hp: 1, walkable: true, transparent: true },

@ -1,6 +1,15 @@
import type { ComputedRef } from 'vue'
import { BLOCK_SIZE, STAGE_WIDTH, STAGE_HEIGHT } from '../level/def' import { BLOCK_SIZE, STAGE_WIDTH, STAGE_HEIGHT } from '../level/def'
export default function useLightMap(ctx: CanvasRenderingContext2D) { 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 W = ((STAGE_WIDTH + 2) * BLOCK_SIZE)
const H = ((STAGE_HEIGHT + 2) * BLOCK_SIZE) const H = ((STAGE_HEIGHT + 2) * BLOCK_SIZE)
@ -8,15 +17,15 @@ export default function useLightMap(ctx: CanvasRenderingContext2D) {
const playerY = H / 2 - BLOCK_SIZE / 2 const playerY = H / 2 - BLOCK_SIZE / 2
const playerLightSize = BLOCK_SIZE * 1.8 const playerLightSize = BLOCK_SIZE * 1.8
function drawPlayerLight(tx: number, ty: number) { function drawPlayerLight(sizeMul:number) {
const playerLight = ctx.createRadialGradient( const playerLight = ctx.createRadialGradient(
playerX - tx, playerY - ty, 0, playerX - tx.value, playerY - ty.value, 0,
playerX - tx, playerY - ty, playerLightSize playerX - tx.value, playerY - ty.value, playerLightSize * sizeMul
) )
// Add three color stops // Add three color stops
playerLight.addColorStop(0.0, "#FFCF"); playerLight.addColorStop(0.0, "#FFFF");
playerLight.addColorStop(1, "#FFC0"); playerLight.addColorStop(1, "#FFF0");
// Set the fill style and draw a rectangle // Set the fill style and draw a rectangle
ctx.fillStyle = playerLight; ctx.fillStyle = playerLight;
@ -24,21 +33,22 @@ export default function useLightMap(ctx: CanvasRenderingContext2D) {
} }
// TODO: support light barrier // TODO: support light barrier
function draw(x:number, y:number, tx:number, ty:number, time:number) { return function update() {
if (time > 900 || time < 100) { const t = time.value
if (t > 900 || t < 100) {
ctx.fillStyle = `hsl(0, 0%, 20%)` ctx.fillStyle = `hsl(0, 0%, 20%)`
} else if (time < 250) { } else if (t < 250) {
const s = Math.round((time - 100) / 1.5) // 0-100% const s = Math.round((t - 100) / 1.5) // 0-100%
const l = Math.round((time - 100) / 1.875) + 20 // 20-100% const l = Math.round((t - 100) / 1.875) + 20 // 20-100%
ctx.fillStyle = `hsl(0, ${s}%, ${l}%)` ctx.fillStyle = `hsl(0, ${s}%, ${l}%)`
// } else if (t < 700) { } else if (t > 700) {
// ctx.fillStyle = `hsl(0, ${}%, ${}%)` const s = 100 - Math.round((t - 700) / 2.5) // 100-20%
ctx.fillStyle = `hsl(245, ${s}%, ${s}%)`
} else { } else {
ctx.fillStyle = `hsl(0, 0%, 100%)` ctx.fillStyle = `hsl(0, 0%, 100%)`
} }
ctx.fillRect(0, 0, W, H) ctx.fillRect(0, 0, W, H)
drawPlayerLight(tx, ty) drawPlayerLight(1)
} }
return { draw }
} }

@ -2,7 +2,7 @@ import { ref, computed } from 'vue'
export default function useTime() { export default function useTime() {
// the day is split in 1000 parts, so we start in the morning // the day is split in 1000 parts, so we start in the morning
const time = ref(250) const time = ref(230)
function updateTime() { function updateTime() {
time.value = (time.value + 0.1) % 1000 time.value = (time.value + 0.1) % 1000

Loading…
Cancel
Save