multi step day night transition with CSS filters

This commit is contained in:
koehr 2018-05-14 16:31:12 +02:00
parent c7452ca130
commit c21e97e2ce
3 changed files with 61 additions and 13 deletions

View file

@ -8,11 +8,11 @@ import solarQuartet from './solar-quartet'
export default {
name: 'background',
props: {
x: Number
x: Number,
time: Number
},
data () {
return {
sunY: -50.0,
redraw: null
}
},
@ -30,11 +30,19 @@ export default {
canvas, canvas.getContext('2d'), canvasSize, canvasSize,
godraysCanvas, godraysCanvas.getContext('2d'), godraysSize, godraysSize,
)
this.redraw(this.x, this.sunY)
this.refresh()
},
watch: {
x (x) {
this.redraw(x, this.sunY)
computed: {
sunY () {
// time is between 0 and 1000
const p = Math.PI / 1000
return Math.sin(this.time * p) * -100
}
},
methods: {
refresh () {
this.redraw(this.x, this.sunY)
this.timeout = setTimeout(() => this.refresh(), 50)
}
}
}

View file

@ -1,5 +1,5 @@
<template>
<div id="field">
<div id="field" :class="daytimeClass">
<input v-keep-focussed type="text"
@keydown.up="player_velocity_y = -8"
@keydown.down="player_velocity_y = 8"
@ -10,19 +10,19 @@
@keyup.right="player_velocity_x = 0"
@keyup.left="player_velocity_x = 0"
/>
<mountain-background :x="128 + x / 8" />
<mountain-background :x="128 + x / 8" :time="time" />
<div id="wrap" :style="{transform: `translate(${tx}px, ${ty}px)`}">
<template v-for="row in rows">
<div v-for="block in row" class="block" :class="[block.type]" />
</template>
</div>
<div id="player" :class="[player_direction]" />
<div id="level-indicator">x:{{ floorX }}, y:{{ floorY }}</div>
<div id="level-indicator">x:{{ floorX }}, y:{{ floorY }} (@{{time}})</div>
</div>
</template>
<script>
import throttle from 'lodash/throttle'
// import throttle from 'lodash/throttle'
import Level from './level'
import MountainBackground from './Background'
@ -44,7 +44,8 @@ export default {
player_velocity_x: 0,
player_velocity_y: 9,
gravity: 8.0 / 20,
moving: false
moving: false,
time: 600
}
},
mounted () {
@ -76,10 +77,27 @@ export default {
floorY () { return Math.floor(this.y) },
tx () { return (this.x - this.floorX) * -BLOCK_SIZE },
ty () { return (this.y - this.floorY) * -BLOCK_SIZE },
rows () { return level.grid(this.floorX, this.floorY) }
rows () { return level.grid(this.floorX, this.floorY) },
daytimeClass () {
const t = this.time
if (t >= 900 || t < 80) return "night"
if (t >= 80 && t < 120) return "morning0"
if (t >= 120 && t < 150) return "morning1"
if (t >= 150 && t < 250) return "morning2"
if (t >= 700 && t < 800) return "evening0"
if (t >= 800 && t < 850) return "evening1"
if (t >= 850 && t < 900) return "evening2"
return "day"
}
},
methods: {
move () {
// set time of day in ticks
this.time = (this.time + 1) % 1000
const x = this.x
const y = this.y
@ -193,5 +211,15 @@ export default {
.block.stone { background-image: url(./assets/rock.png); }
.block.bedrock { background-image: url(./assets/bedrock.png); }
.block.cave { background-color: #000; }
.block:hover, .block.highlight { filter: brightness(1.4); }
#field .block:hover { outline: 1px solid white; z-index: 10; }
.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: 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%); }
.night .block, .night #player { filter: brightness(0.3) saturate(30%); }
</style>

View file

@ -29,8 +29,13 @@ export default function drawFrame (canvas, ctx, width, height, grCanvas, grCtx,
// so anything lighter will result in lots of white.
// If you're not space-bound you can add another stop or two, maybe fade out to black,
// but this actually looks good enough.
emissionGradient.addColorStop(.1, '#0C0804') // pixels in radius 0 to 4.4 (44 * .1).
emissionGradient.addColorStop(.2, '#060201') // everything past radius 8.8.
/* TODO: NIGHT
* emissionGradient.addColorStop(.1, '#000') // pixels in radius 0 to 4.4 (44 * .1).
* emissionGradient.addColorStop(.2, '#000') // everything past radius 8.8.
*/
// Now paint the gradient all over our godrays canvas.
grCtx.fillRect(0, 0, grWidth, grHeight)
@ -43,6 +48,10 @@ export default function drawFrame (canvas, ctx, width, height, grCanvas, grCtx,
const skyGradient = ctx.createLinearGradient(0, 0, 0, height)
skyGradient.addColorStop(0, '#2a3e55') // Blueish at the top.
skyGradient.addColorStop(.7, '#8d4835') // Reddish at the bottom.
/* TODO: NIGHT
* skyGradient.addColorStop(0, '#000') // Blueish at the top.
* skyGradient.addColorStop(.7, '#000') // Reddish at the bottom.
*/
ctx.fillStyle = skyGradient
ctx.fillRect(0, 0, width, height)
@ -60,6 +69,9 @@ export default function drawFrame (canvas, ctx, width, height, grCanvas, grCtx,
// Set the main canvas fillStyle to a shade of brown with variable lightness
// (darker at the front)
ctx.fillStyle = `hsl(7, 23%, ${23-i*6}%)`;
/* TODO: NIGHT
* ctx.fillStyle = `hsl(5, 23%, ${4-i}%)`;
*/
// For each column in our canvas...
for(let x = width; x--;) {