shine light from the sky

main
Norman Köhring 1 year ago
parent 5db90bb2f3
commit 811b6e5b78

@ -31,6 +31,7 @@ const floorY = computed(() => Math.floor(y.value))
const tx = computed(() => (x.value - floorX.value) * -BLOCK_SIZE)
const ty = computed(() => (y.value - floorY.value) * -BLOCK_SIZE)
const rows = computed(() => level.grid(floorX.value, floorY.value))
const lightBarrier = computed(() => level.sunLight(floorX.value))
const arriving = ref(true)
const walking = ref(false)
@ -125,10 +126,24 @@ const move = (thisTick: number): void => {
lastTick = thisTick
}
function calcBrightness(level: number, row: number) {
const barrier = lightBarrier.value[row]
let delta = barrier - level - (floorY.value - 3)
if (delta > 3) delta = 3
else if (delta < 0) delta = 0
return `sun-${delta}`
}
onMounted(() => {
lastTick = performance.now()
move(lastTick)
})
function log(...args: any[]) {
console.log(...args)
}
</script>
<template>
@ -136,7 +151,10 @@ onMounted(() => {
<div id="blocks" :style="{transform: `translate(${tx}px, ${ty}px)`}">
<template v-for="(row, y) in rows">
<div v-for="(block, x) in row" class="block" :class="[block.type]" />
<div v-for="(block, x) in row"
:class="['block', block.type, calcBrightness(y, x)]"
@click="log('block', x, y, block.type)"
/>
</template>
</div>

@ -1,20 +1,18 @@
.block.grass { background-image: url(/Tiles/dirt_grass.png); }
.block.treeTopLeft { background-image: url(/Tiles/leaves_transparent.png); }
.block.treeTopMiddle { background-image: url(/Tiles/leaves_transparent.png); }
.block.treeTopRight { background-image: url(/Tiles/leaves_transparent.png); }
.block.treeCrownLeft { background-image: url(/Tiles/leaves_transparent.png); }
.block.treeCrownMiddle { background-image: url(/Tiles/leaves_transparent.png); }
.block.treeCrownRight { background-image: url(/Tiles/leaves_transparent.png); }
.block {
flex: 0 0 auto;
width: var(--block-size);
height: var(--block-size);
background-color: transparent;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.block.treeTrunkLeft { background-image: url(/Tiles/leaves_transparent.png); }
.block.treeTrunkMiddle { background-image: url(/Tiles/trunk_mid.png); }
.block.treeTrunkRight { background-image: url(/Tiles/leaves_transparent.png); }
.block.grass { background-image: url(/Tiles/dirt_grass.png); }
.block.treeRootLeft { background-image: url(/Tiles/tree_root_left.png); }
.block.treeRootMiddle { background-image: url(/Tiles/trunk_bottom.png); }
.block.treeRootRight { background-image: url(/Tiles/tree_root_right.png); }
.block.treeCrown, .block.treeLeaves { background-image: url(/Tiles/leaves_transparent.png); }
.block.treeTrunk { background-image: url(/Tiles/trunk_mid.png); }
.block.treeRoot { background-image: url(/Tiles/trunk_bottom.png); }
.block.soil { background-image: url(/Tiles/dirt.png); }
.block.soilGravel { background-image: url(/Tiles/gravel_dirt.png); }
@ -24,25 +22,45 @@
.block.cave { background-color: #000; }
#field .block:hover { outline: 1px solid white; z-index: 10; }
.morning0 .block, .morning0 #player { filter: saturate(50%) brightness(0.6) hue-rotate(-10deg); }
.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%) 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%); }
.block {
flex: 0 0 auto;
width: var(--block-size);
height: var(--block-size);
background-color: transparent;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.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); }
#blocks {
position: absolute;
top: calc(var(--block-size) * (var(--spare-blocks) / -2));

@ -1,43 +1,50 @@
import type { NoiseFunction2D } from 'simplex-noise'
import {blockTypes as T, level as L, probability as P, type Block} from './def'
const TREE_ROOT = [T.treeRootLeft, T.treeRootMiddle, T.treeRootRight]
function trees(r: number, i: number, row: Block[], previousRow: Block[]) {
const max = row.length - 1
const h = i - 1
const j = i + 1
const current = row[i]
const above = previousRow[i]
const aboveLeft = previousRow[h]
const aboveRight = previousRow[j]
if (row[i] === T.treeTopMiddle) {
if (i) {
if (row[h] === T.treeTopRight) row[h] = T.treeTopLeftMixed
else row[h] = T.treeTopLeft
}
if (i < max) row[j] = T.treeTopRight
if (current === T.treeCrown) {
if (i > 0) row[h] = T.treeLeaves
if (i < max) row[j] = T.treeLeaves
} else if (previousRow[i] === T.treeTopMiddle) {
row[i] = T.treeCrownMiddle
if (i) {
if (row[h] === T.treeCrownRight) row[h] = T.treeCrownLeftMixed
else row[h] = T.treeCrownLeft
}
if (i < max) row[j] = T.treeCrownRight
} else if (previousRow[i] === T.treeCrownMiddle) {
row[i] = T.treeTrunkMiddle
if (i) {
if (row[h] === T.treeTrunkRight) row[h] = T.treeTrunkLeftMixed
else row[h] = T.treeTrunkLeft
}
if (i < max) row[j] = T.treeTrunkRight
} else if (previousRow[i] === T.treeTrunkMiddle) {
row[i] = T.treeRootMiddle
if (i) {
if (row[h] === T.treeRootRight) row[h] = T.treeRootLeftMixed
else row[h] = T.treeRootLeft
}
if (i < max) row[j] = T.treeRootRight
} else if (above === T.treeCrown) {
row[i] = T.treeLeaves
if (i > 0) row[h] = T.treeLeaves
if (i < max) row[j] = T.treeLeaves
} else if (above === T.treeLeaves && aboveLeft === T.treeLeaves && aboveRight === T.treeLeaves) {
row[i] = T.treeTrunk
if (i > 0) row[h] = T.treeLeaves
if (i < max) row[j] = T.treeLeaves
} else if (above === T.treeTrunk) {
if (current === T.air) row[i] = T.treeTrunk
else row[i] = T.treeRoot
} else if (above === T.treeRoot) {
row[i] = T.soil
if (i > 0) row[h] = T.treeRoot
if (i < max) row[j] = T.treeRoot
}
}
function ground(r: number, i: number, row: Block[], previousRow: Block[]) {
function ground(r: number, i: number, current: Block, above: Block) {
if (above === T.air) {
if (r < P.soilHole) return T.air
if (current === T.soil) return T.grass
}
return current
}
function ground_(r: number, i: number, row: Block[], previousRow: Block[]) {
const rootParts = [T.treeRootLeft, T.treeRootMiddle, T.treeRootRight]
const prevBlock = previousRow[i]
@ -49,25 +56,39 @@ function ground(r: number, i: number, row: Block[], previousRow: Block[]) {
}
}
function rock(r: number, i: number, row: Block[], previousRow: Block[]) {
if (previousRow[i] === T.soil && r < P.fray) row[i] = T.soil
function rock(r: number, i: number, current: Block, above: Block) {
if (above === T.soil && r < P.fray) return T.soil
return current
}
function underground(r: number, i: number, row: Block[], previousRow: Block[]) {
if (previousRow[i] === T.stone && r < P.fray) row[i] = T.stone
function underground(r: number, i: number, current: Block, above: Block) {
if (above === T.stone && r < P.fray) return T.stone
return current
}
export default function createBlockExtender(rand: NoiseFunction2D) {
function extendBlocks(level: number, column: number, row: Block[], previousRow: Block[]) {
for (let i = 0; i < row.length; i++) {
const r = rand(level, column + i)
if (level < L.ground) trees(r, i, row, previousRow)
else if (level < L.rock) ground(r, i, row, previousRow)
else if (level < L.underground) rock(r, i, row, previousRow)
else underground(r, i, row, previousRow)
function growTrees(level: number, column: number, offset: number, row: Block[], previousRow: Block[]) {
const r = rand(level, column + offset)
trees(r, column, row, previousRow)
}
function extendBlock(level: number, column: number, offset: number, current: Block, above: Block) {
const r = rand(level, column + offset)
if (level < L.rock) return ground(r, column, current, above)
if (level < L.underground) return rock(r, column, current, above)
return underground(r, column, current, above)
}
function extendRow(level: number, columnOffset: number, row: Block[], previousRow: Block[]) {
for (let column = 0; column < row.length; column++) {
if (level < L.ground) {
// growTrees(level, column, columnOffset, row, previousRow)
} else {
row[column] = extendBlock(level, column, columnOffset, row[column], previousRow[column])
}
}
}
return extendBlocks
return { extendBlock, extendRow }
}

@ -5,9 +5,7 @@ export default function createBlockGenerator(rand: NoiseFunction2D) {
// randomly generate a block
// level: number, smaller is "higher"
// column: number, the x-axis
// before: Block, the block type left of (before) this block
// above: Block, the block type above this block
const generateBlock = (level: number, column: number, before: Block, above: Block): Block => {
const generateBlock = (level: number, column: number): Block => {
// no randomness needed, there is always air above the trees
if (level < L.treeTop) return T.air
@ -15,7 +13,7 @@ export default function createBlockGenerator(rand: NoiseFunction2D) {
// Air layer: mostly air, sometimes trees
if (level < L.ground) {
if (level === L.treeTop && r < P.tree) return T.treeTopMiddle
if (level === L.treeTop && r < P.tree) return T.treeCrown
return T.air
}
@ -40,11 +38,11 @@ export default function createBlockGenerator(rand: NoiseFunction2D) {
return T.bedrock
}
const fillRow = (level: number, column: number, row: Block[], previousRow: Block[]) => {
const fillRow = (level: number, column: number, row: Block[]) => {
for (let i = 0; i < row.length; i++) {
row[i] = generateBlock(level, column + i, row[i - 1], previousRow[i])
row[i] = generateBlock(level, column + i)
}
}
return fillRow
return { fillRow, generateBlock }
}

@ -12,48 +12,28 @@ export type Block = {
hp: number,
walkable: boolean,
climbable?: boolean,
transparent?: boolean,
}
export const blockTypes: Record<string, Block> = {
air: { type: 'air', hp: Infinity, walkable: true },
air: { type: 'air', hp: Infinity, walkable: true, transparent: true },
grass: { type: 'grass', hp: 1, walkable: false },
treeTopLeft: { type: 'treeTopLeft', hp: 5, walkable: true },
treeTopMiddle: { type: 'treeTopMiddle', hp: 5, walkable: true },
treeTopRight: { type: 'treeTopRight', hp: 5, walkable: true },
treeCrownLeft: { type: 'treeCrownLeft', hp: 5, walkable: true },
treeCrownMiddle: { type: 'treeCrownMiddle', hp: 5, walkable: true, climbable: true },
treeCrownRight: { type: 'treeCrownRight', hp: 5, walkable: true },
treeTrunkLeft: { type: 'treeTrunkLeft', hp: 5, walkable: true },
treeTrunkMiddle: { type: 'treeTrunkMiddle', hp: 5, walkable: true, climbable: true },
treeTrunkRight: { type: 'treeTrunkRight', hp: 5, walkable: true },
treeRootLeft: { type: 'treeRootLeft', hp: 5, walkable: true },
treeRootMiddle: { type: 'treeRootMiddle', hp: 5, walkable: true, climbable: true },
treeRootRight: { type: 'treeRootRight', hp: 5, walkable: true },
treeTopLeftMixed: { type: 'treeTopLeftMixed', hp: 5, walkable: true },
treeCrownLeftMixed: { type: 'treeCrownLeftMixed', hp: 5, walkable: true },
treeTrunkLeftMixed: { type: 'treeTrunkLeftMixed', hp: 5, walkable: true },
treeRootLeftMixed: { type: 'treeRootLeftMixed', hp: 5, walkable: true },
treeTopRightMixed: { type: 'treeTopRightMixed', hp: 5, walkable: true },
treeCrownRightMixed: { type: 'treeCrownRightMixed', hp: 5, walkable: true },
treeTrunkRightMixed: { type: 'treeTrunkRightMixed', hp: 5, walkable: true },
treeRootRightMixed: { type: 'treeRootRightMixed', hp: 5, walkable: true },
treeCrown: { type: 'treeCrown', hp: 5, walkable: true, transparent: true },
treeLeaves: { type: 'treeLeaves', hp: 5, walkable: true, transparent: true },
treeTrunk: { type: 'treeTrunk', hp: 15, walkable: true, climbable: true, transparent: true },
treeRoot: { type: 'treeRoot', hp: 15, walkable: true, climbable: true },
soil: { type: 'soil', hp: 2, walkable: false },
soilGravel: { type: 'soilGravel', hp: 5, walkable: false },
stoneGravel: { type: 'stoneGravel', hp: 5, walkable: false },
stone: { type: 'stone', hp: 10, walkable: false },
bedrock: { type: 'bedrock', hp: 25, walkable: false },
cave: { type: 'cave', hp: Infinity, walkable: true },
cave: { type: 'cave', hp: Infinity, walkable: true, transparent: true },
}
export const level = {
treeTop: 10,
treeTop: 9,
ground: 14,
rock: 16,
underground: 24,
@ -61,7 +41,7 @@ export const level = {
}
export const probability = {
tree: 0.2,
tree: 0.3,
soilHole: 0.3,
soilGravel: 0.2,
stoneGravel: 0.1,

@ -5,12 +5,19 @@ import createBlockExtender from './blockExt'
import {blockTypes as T, level as L, type Block} from './def'
export default function createLevel(width: number, height: number, seed = 'very random seed') {
const MAX_LIGHT = 100 // maximum level where light shines
export default function createLevel(width: number, height: number, seed = 'extremely random seed') {
const prng = alea(seed)
const noise2D = createNoise2D(prng)
const rand: NoiseFunction2D = (x, y) => 0.5 + 0.5 * noise2D(x, y)
// stores the current grid of blocks, visible on the screen
const _grid: Block[][] = new Array(height)
// stores the limit to where light still shines,
// for each column currently visible on the screen
const _lightBarrier: number[] = [...new Array(width)].map(() => MAX_LIGHT)
const blockGen = createBlockGenerator(rand)
const blockExt = createBlockExtender(rand)
@ -19,23 +26,45 @@ export default function createLevel(width: number, height: number, seed = 'very
// TODO
}
function calcLightBarrier(columnOffset: number) {
let previousBlock: Block = T.air
for (let col = 0; col < width; col++) {
for (let level = 0; level < MAX_LIGHT; level++) {
let block = blockGen.generateBlock(level, col + columnOffset)
block = blockExt.extendBlock(level, col, columnOffset, block, previousBlock)
previousBlock = block
if (!block.transparent) {
_lightBarrier[col] = level
break
}
}
}
}
function generate(column: number, y: number) {
for (let i = 0; i < height; i++) {
const level = y+i
const row: Block[] = Array(width)
const previousRow = i ? _grid[i-1] : [] as Block[]
blockGen(level, column, row, previousRow)
blockExt(level, column, row, previousRow)
blockGen.fillRow(level, column, row)
blockExt.extendRow(level, column, row, previousRow)
_grid[i] = row
}
}
function sunLight(x: number, y: number) {
calcLightBarrier(x)
return _lightBarrier
}
function grid(x: number, y: number) {
generate(x, y)
return _grid
}
return { grid, change }
return { grid, sunLight, change }
}

1
src/vite-env.d.ts vendored

@ -13,6 +13,7 @@ declare global {
name: string
type: string
icon: string
amount: number
quality?: 'bronze' | 'iron' | 'silver' | 'gold' | 'diamond'
}

Loading…
Cancel
Save