time-related brightness controlled by light-map
This commit is contained in:
parent
3b7ee96f62
commit
d75f862380
5 changed files with 45 additions and 59 deletions
10
src/App.vue
10
src/App.vue
|
@ -11,13 +11,13 @@ import useInput from './util/useInput'
|
|||
import usePlayer from './util/usePlayer'
|
||||
import useLightMap from './util/useLightMap'
|
||||
|
||||
const { updateTime, time, clock } = useTime()
|
||||
const { updateTime, time, timeOfDay, clock } = useTime()
|
||||
const { player, direction, dx, dy } = usePlayer()
|
||||
const { inputX, inputY, running, paused, help, inventory } = useInput()
|
||||
const level = createLevel(STAGE_WIDTH + 2, STAGE_HEIGHT + 2)
|
||||
|
||||
const lightMapEl = ref<HTMLCanvasElement | undefined>(undefined)
|
||||
let lightMap: ReturnType<typeof useLightMap>
|
||||
let updateLightMap: ReturnType<typeof useLightMap>
|
||||
|
||||
player.inventory.push(
|
||||
{ name: 'Shovel', type: 'tool', icon: 'shovel', quality: 'bronze', amount: 1 },
|
||||
|
@ -144,7 +144,7 @@ const move = (thisTick: number): void => {
|
|||
y.value += dy_ * fallMultiplier
|
||||
}
|
||||
|
||||
lightMap.draw(floorX.value, floorY.value, tx.value, ty.value, time.value)
|
||||
updateLightMap()
|
||||
lastTick = thisTick
|
||||
}
|
||||
|
||||
|
@ -171,14 +171,14 @@ onMounted(() => {
|
|||
canvas.width = (BLOCK_SIZE + 2) * STAGE_WIDTH
|
||||
const ctx = canvas.getContext('2d')!
|
||||
|
||||
lightMap = useLightMap(ctx)
|
||||
updateLightMap = useLightMap(ctx, floorX, floorY, tx, ty, time, lightBarrier)
|
||||
lastTick = performance.now()
|
||||
move(lastTick)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div id="field">
|
||||
<div id="field" :class="timeOfDay">
|
||||
|
||||
<div id="blocks" :style="{transform: `translate(${tx}px, ${ty}px)`}">
|
||||
<template v-for="(row, y) in rows">
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
.block, #player {
|
||||
transition: filter .5s linear;
|
||||
}
|
||||
.block {
|
||||
flex: 0 0 auto;
|
||||
width: var(--block-size);
|
||||
|
@ -42,44 +45,15 @@
|
|||
.block.cave { background-color: #000; }
|
||||
#field .block:hover { outline: 1px solid white; z-index: 10; }
|
||||
|
||||
.block.sun-3 { filter: brightness(1.0); }
|
||||
.block.sun-2 { filter: brightness(0.4); }
|
||||
.block.sun-1 { filter: brightness(0.2); }
|
||||
.block.sun-0 { filter: brightness(0.0); }
|
||||
.morning0 .block, .morning0 #player {filter: saturate(50%); }
|
||||
.morning1 .block, .morning1 #player { filter: saturate(100%); }
|
||||
.morning2 .block, .morning2 #player { filter: saturate(120%); }
|
||||
|
||||
.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); }
|
||||
.evening0 .block, .evening0 #player { filter: saturate(90%); }
|
||||
.evening1 .block, .evening1 #player { filter: saturate(70%); }
|
||||
.evening2 .block, .evening2 #player { filter: saturate(50%); }
|
||||
|
||||
.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%); }
|
||||
|
||||
.block.sun-0,
|
||||
.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); }
|
||||
.night .block, .night #player { filter: saturate(30%); }
|
||||
|
||||
#blocks {
|
||||
position: absolute;
|
||||
|
@ -98,4 +72,5 @@
|
|||
width: calc(100% + var(--block-size) * 2);
|
||||
height: calc(100% + var(--block-size) * 2);
|
||||
mix-blend-mode: multiply;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ export type Block = {
|
|||
walkable: boolean,
|
||||
climbable?: boolean,
|
||||
transparent?: boolean,
|
||||
illuminated?: boolean,
|
||||
}
|
||||
|
||||
export type BlockType =
|
||||
|
@ -22,7 +23,7 @@ export type BlockType =
|
|||
| 'bedrock' | 'cave'
|
||||
|
||||
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 },
|
||||
|
||||
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'
|
||||
|
||||
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 H = ((STAGE_HEIGHT + 2) * BLOCK_SIZE)
|
||||
|
||||
|
@ -8,15 +17,15 @@ export default function useLightMap(ctx: CanvasRenderingContext2D) {
|
|||
const playerY = H / 2 - BLOCK_SIZE / 2
|
||||
const playerLightSize = BLOCK_SIZE * 1.8
|
||||
|
||||
function drawPlayerLight(tx: number, ty: number) {
|
||||
function drawPlayerLight(sizeMul:number) {
|
||||
const playerLight = ctx.createRadialGradient(
|
||||
playerX - tx, playerY - ty, 0,
|
||||
playerX - tx, playerY - ty, playerLightSize
|
||||
playerX - tx.value, playerY - ty.value, 0,
|
||||
playerX - tx.value, playerY - ty.value, playerLightSize * sizeMul
|
||||
)
|
||||
|
||||
// Add three color stops
|
||||
playerLight.addColorStop(0.0, "#FFCF");
|
||||
playerLight.addColorStop(1, "#FFC0");
|
||||
playerLight.addColorStop(0.0, "#FFFF");
|
||||
playerLight.addColorStop(1, "#FFF0");
|
||||
|
||||
// Set the fill style and draw a rectangle
|
||||
ctx.fillStyle = playerLight;
|
||||
|
@ -24,21 +33,22 @@ export default function useLightMap(ctx: CanvasRenderingContext2D) {
|
|||
}
|
||||
|
||||
// TODO: support light barrier
|
||||
function draw(x:number, y:number, tx:number, ty:number, time:number) {
|
||||
if (time > 900 || time < 100) {
|
||||
return function update() {
|
||||
const t = time.value
|
||||
|
||||
if (t > 900 || t < 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%
|
||||
} 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 if (t > 700) {
|
||||
const s = 100 - Math.round((t - 700) / 2.5) // 100-20%
|
||||
ctx.fillStyle = `hsl(245, ${s}%, ${s}%)`
|
||||
} else {
|
||||
ctx.fillStyle = `hsl(0, 0%, 100%)`
|
||||
}
|
||||
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() {
|
||||
// the day is split in 1000 parts, so we start in the morning
|
||||
const time = ref(250)
|
||||
const time = ref(230)
|
||||
|
||||
function updateTime() {
|
||||
time.value = (time.value + 0.1) % 1000
|
||||
|
|
Loading…
Add table
Reference in a new issue