Compare commits
No commits in common. "3266ddb21799ed2e0da3d3c620cb44c4647db3da" and "8f281fbdf9c17af948280397e19c10e60b29d2e8" have entirely different histories.
3266ddb217
...
8f281fbdf9
15 changed files with 123 additions and 186 deletions
Binary file not shown.
Before Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB |
105
src/App.vue
105
src/App.vue
|
@ -1,11 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import type { Block, BlockType, Direction, Item, InventoryItem, LightSource } from './types.d'
|
||||
import type { Block, Direction, Item, InventoryItem } from './types.d'
|
||||
import { ref, computed, watch, onMounted, useTemplateRef } from 'vue'
|
||||
import Help from './screens/help.vue'
|
||||
import Inventory from './screens/inventory.vue'
|
||||
import Background from './Background.vue'
|
||||
|
||||
import { BLOCK_SIZE, STAGE_WIDTH, STAGE_HEIGHT, softTerrain, hardTerrain } from './level/def'
|
||||
import { BLOCK_SIZE, STAGE_WIDTH, STAGE_HEIGHT } from './level/def'
|
||||
import { getItem, getItemClass } from './level/items'
|
||||
import createLevel from './level'
|
||||
|
||||
|
@ -25,12 +25,11 @@ let updateLightMap = (() => {}) as ReturnType<typeof useLightMask>
|
|||
pocket(getItem('tool_shovel_wood'))
|
||||
pocket(getItem('tool_sword_wood'))
|
||||
pocket(getItem('tool_pickaxe_wood'))
|
||||
pocket(getItem('fixture_torch'), 5)
|
||||
|
||||
let animationFrame = 0
|
||||
let lastTick = 0
|
||||
|
||||
const debug = ref(true)
|
||||
const debug = ref(false)
|
||||
const x = ref(0)
|
||||
const y = ref(0)
|
||||
const floorX = computed(() => Math.floor(x.value))
|
||||
|
@ -52,35 +51,15 @@ const mapGrid = computed<Block[][]>(() => {
|
|||
const _update = mapUpdateCount.value // reactivity trigger
|
||||
return level.grid(floorX.value, floorY.value, true)
|
||||
})
|
||||
const lightSources = computed(() => {
|
||||
const _update = mapUpdateCount.value // reactivity trigger
|
||||
const _floorX = floorX.value // reactivity trigger
|
||||
const _floorY = floorY.value // reactivity trigger
|
||||
|
||||
const lightSources: LightSource[] = []
|
||||
const grid = mapGrid.value
|
||||
|
||||
for (let y = 0; y < grid.length; y++) {
|
||||
const row = grid[y]
|
||||
for (let x = 0; x < row.length; x++) {
|
||||
const block = row[x]
|
||||
if (block.illumination) {
|
||||
lightSources.push({
|
||||
x, y,
|
||||
strength: block.illumination,
|
||||
color: block.color ?? '#FFE'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return lightSources
|
||||
})
|
||||
|
||||
const arriving = ref(true)
|
||||
const walking = ref(false)
|
||||
const inventorySelection = ref<InventoryItem>(player.inventory[0])
|
||||
|
||||
const getSurroundings = (x: number, y: number) => {
|
||||
const surroundings = computed<Record<Direction, Block>>(() => {
|
||||
const _update = mapUpdateCount.value // reactivity trigger
|
||||
const x = px.value
|
||||
const y = py.value
|
||||
const rows = mapGrid.value
|
||||
|
||||
const rowY = rows[y]
|
||||
|
@ -94,11 +73,6 @@ const getSurroundings = (x: number, y: number) => {
|
|||
up: rowYp[x],
|
||||
down: rowYn[x],
|
||||
}
|
||||
}
|
||||
|
||||
const surroundings = computed<Record<Direction, Block>>(() => {
|
||||
const _update = mapUpdateCount.value // reactivity trigger
|
||||
return getSurroundings(px.value, py.value)
|
||||
})
|
||||
const blocked = computed(() => {
|
||||
const { left, right, up, down } = surroundings.value
|
||||
|
@ -136,26 +110,15 @@ function dig(blockX: number, blockY: number, block: Block) {
|
|||
}
|
||||
|
||||
function build(blockX: number, blockY: number, block: InventoryItem) {
|
||||
let blockToBuild = block.builds
|
||||
if (!blockToBuild) return // the block doesn't do anything?!
|
||||
|
||||
// While blocks are just filling the space completely, fixtures are attached
|
||||
// to the closest surface. We check the surroundings, starting at with left
|
||||
// and right, then bottom and top.
|
||||
if (block.type === 'fixture') {
|
||||
const { left, right, up, down } = getSurroundings(blockX, blockY)
|
||||
|
||||
if (!left.transparent) blockToBuild = `${blockToBuild}Left`
|
||||
else if (!right.transparent) blockToBuild = `${blockToBuild}Right`
|
||||
else if (!up.transparent) blockToBuild = `${blockToBuild}Ceiling`
|
||||
else if (!down.transparent) blockToBuild = `${blockToBuild}Floor`
|
||||
}
|
||||
const blockToBuild = block.builds
|
||||
// the block doesn't do anything
|
||||
if (!blockToBuild) return
|
||||
|
||||
level.change({
|
||||
change: 'exchange',
|
||||
x: floorX.value + blockX,
|
||||
y: floorY.value + blockY,
|
||||
newType: blockToBuild as BlockType
|
||||
newType: blockToBuild
|
||||
})
|
||||
mapUpdateCount.value = mapUpdateCount.value + 1
|
||||
|
||||
|
@ -164,37 +127,20 @@ function build(blockX: number, blockY: number, block: InventoryItem) {
|
|||
}
|
||||
|
||||
function interactWith(blockX: number, blockY: number, block: Block) {
|
||||
if (debug) {
|
||||
console.debug(
|
||||
`interact with ${block.type} at ${blockX},${blockY},`,
|
||||
`with a ${inventorySelection.value.id} in hand`
|
||||
)
|
||||
}
|
||||
if (debug) console.debug('interact with', blockX, blockY, block.type)
|
||||
// § 4 ArbZG
|
||||
if (paused.value) return
|
||||
|
||||
// no spooky interaction at a distance
|
||||
const distanceX = ~~(px.value - blockX)
|
||||
const distanceY = ~~(py.value - blockY)
|
||||
if (distanceX > 1 || distanceY > 1) return
|
||||
|
||||
const blockInHand = inventorySelection.value
|
||||
const shovelInHand = blockInHand.id.indexOf('shovel') >= 0
|
||||
const pickaxeInHand = blockInHand.id.indexOf('pickaxe') >= 0
|
||||
|
||||
const canBuild = !!blockInHand.builds
|
||||
const hasTool = blockInHand.type === 'tool'
|
||||
const hasSpace = block.type === 'air' || block.type === 'cave'
|
||||
const canUseShovel = softTerrain.indexOf(block.type) >= 0
|
||||
const canUsePickaxe = hardTerrain.indexOf(block.type) >= 0
|
||||
const blockInHand = inventorySelection.value.type === 'block'
|
||||
const toolInHand = inventorySelection.value.type === 'tool'
|
||||
const emptyBlock = block.type === 'air' || block.type === 'cave'
|
||||
|
||||
// put the selected block
|
||||
if (canBuild && hasSpace) {
|
||||
build(blockX, blockY, blockInHand)
|
||||
if (blockInHand && emptyBlock) {
|
||||
build(blockX, blockY, inventorySelection.value)
|
||||
// dig a block with shovel or pick axe
|
||||
} else if (hasTool && !hasSpace) {
|
||||
if (shovelInHand && canUseShovel) dig(blockX, blockY, block)
|
||||
else if (pickaxeInHand && canUsePickaxe) dig(blockX, blockY, block)
|
||||
} else if (toolInHand && !emptyBlock) {
|
||||
dig(blockX, blockY, block)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,10 +214,7 @@ onMounted(() => {
|
|||
canvas.height = (BLOCK_SIZE + 2) * STAGE_HEIGHT
|
||||
canvas.width = (BLOCK_SIZE + 2) * STAGE_WIDTH
|
||||
const ctx = canvas.getContext('2d')!
|
||||
updateLightMap = useLightMask(
|
||||
ctx, floorY, tx, ty,
|
||||
lightBarrier, lightSources,
|
||||
)
|
||||
updateLightMap = useLightMask(ctx, floorX, floorY, tx, ty, time, lightBarrier)
|
||||
} else {
|
||||
console.warn('lightmap deactivated')
|
||||
}
|
||||
|
@ -322,13 +265,7 @@ onMounted(() => {
|
|||
<div id="beam" v-if="arriving"></div>
|
||||
<div id="level-indicator">
|
||||
x:{{ floorX }}, y:{{ floorY }}
|
||||
<template v-if="paused">
|
||||
<template v-if="debug">
|
||||
({{ clock }})<br/>
|
||||
time: <input type="number" max="0" min="1000" v-model="time" />
|
||||
</template>
|
||||
<template v-else>(PAUSED)</template>
|
||||
</template>
|
||||
<template v-if="paused">(PAUSED)</template>
|
||||
<template v-else>({{ clock }})</template>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -21,15 +21,18 @@ onMounted(() => {
|
|||
|
||||
const drawBackground = useBackground(
|
||||
canvasEl,
|
||||
~~(STAGE_WIDTH * BLOCK_SIZE / 1.0),
|
||||
~~(STAGE_HEIGHT * BLOCK_SIZE / 1.0),
|
||||
~~(STAGE_WIDTH * BLOCK_SIZE / 2.0),
|
||||
~~(STAGE_HEIGHT * BLOCK_SIZE / 2.0),
|
||||
)
|
||||
|
||||
watch(props, () => drawBackground(props.x, sunY.value), { immediate: true })
|
||||
watch(props, () => {
|
||||
console.log('drawing background', sunY.value)
|
||||
drawBackground(props.x, sunY.value)
|
||||
}, { immediate: true })
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<canvas ref="canvas" id="background" />
|
||||
<canvas ref="canvas" id="background"></canvas>
|
||||
</template>
|
||||
|
|
|
@ -98,10 +98,6 @@
|
|||
.block.brickWall {
|
||||
background-image: url(/Tiles/brick_grey.png);
|
||||
}
|
||||
.block.torchLeft { background-image: url("/Items/torchLeft.png"); }
|
||||
.block.torchRight { background-image: url("/Items/torchRight.png"); }
|
||||
.block.torchFloor { background-image: url("/Items/torchFloor.png"); }
|
||||
.block.torchCeiling { background-image: url("/Items/torchCeiling.png"); }
|
||||
|
||||
#field {
|
||||
user-select: none;
|
||||
|
@ -116,17 +112,17 @@
|
|||
|
||||
.morning0 .block,
|
||||
.morning0 #player {
|
||||
filter: saturate(50%) brightness(0.6);
|
||||
filter: saturate(50%);
|
||||
}
|
||||
|
||||
.morning1 .block,
|
||||
.morning1 #player {
|
||||
filter: saturate(100%) brightness(0.8);
|
||||
filter: saturate(100%);
|
||||
}
|
||||
|
||||
.morning2 .block,
|
||||
.morning2 #player {
|
||||
filter: saturate(120%) brightness(0.9);
|
||||
filter: saturate(120%);
|
||||
}
|
||||
|
||||
.evening0 .block,
|
||||
|
@ -136,17 +132,17 @@
|
|||
|
||||
.evening1 .block,
|
||||
.evening1 #player {
|
||||
filter: saturate(70%) brightness(0.8);
|
||||
filter: saturate(70%);
|
||||
}
|
||||
|
||||
.evening2 .block,
|
||||
.evening2 #player {
|
||||
filter: saturate(50%) brightness(0.6);
|
||||
filter: saturate(50%);
|
||||
}
|
||||
|
||||
.night .block,
|
||||
.night #player {
|
||||
filter: saturate(30%) brightness(0.4);
|
||||
filter: saturate(30%);
|
||||
}
|
||||
|
||||
#blocks {
|
||||
|
|
|
@ -14,5 +14,3 @@
|
|||
.item.block-dirt { background-image: url("/Tiles/dirt.png"); }
|
||||
.item.block-stone { background-image: url("/Tiles/stone.png"); }
|
||||
.item.block-gravel { background-image: url("/Tiles/gravel_stone.png"); }
|
||||
|
||||
.item.fixture-torch { background-image: url("/Items/torchFloor.png"); }
|
||||
|
|
|
@ -27,19 +27,8 @@ export const blockTypes: Record<BlockType, Block> = {
|
|||
bedrock: { type: 'bedrock', hp: 25, walkable: false, drops: 'block_stone' },
|
||||
// Built Blocks
|
||||
brickWall: { type: 'brickWall', hp: 25, walkable: false, drops: 'block_gravel' },
|
||||
|
||||
torchLeft: { type: 'torchLeft', hp: 1, walkable: true, transparent: true, drops: 'fixture_torch', illumination: 1.0, color: '#FFE', fixture: true },
|
||||
torchRight: { type: 'torchRight', hp: 1, walkable: true, transparent: true, drops: 'fixture_torch', illumination: 1.0, color: '#FFE', fixture: true },
|
||||
torchCeiling: { type: 'torchCeiling', hp: 1, walkable: true, transparent: true, drops: 'fixture_torch', illumination: 1.0, color: '#FFE', fixture: true },
|
||||
torchFloor: { type: 'torchFloor', hp: 1, walkable: true, transparent: true, drops: 'fixture_torch', illumination: 1.0, color: '#FEB', fixture: true },
|
||||
}
|
||||
|
||||
export const softTerrain: BlockType[] = [
|
||||
'grass', 'soil', 'soilGravel',
|
||||
'torchLeft', 'torchRight', 'torchCeiling', 'torchFloor',
|
||||
]
|
||||
export const hardTerrain: BlockType[] = ['stone', 'stoneGravel', 'bedrock', 'brickWall']
|
||||
|
||||
export const level = {
|
||||
treeTop: 9,
|
||||
ground: 14,
|
||||
|
|
|
@ -3,10 +3,10 @@ import { createNoise2D, type NoiseFunction2D } from 'simplex-noise'
|
|||
import createBlockGenerator from './blockGen'
|
||||
import createBlockExtender from './blockExt'
|
||||
|
||||
import { level as L, blockTypes, blockTypes as T } from './def'
|
||||
import { blockTypes, blockTypes as T } from './def'
|
||||
import type { Block, Change } from '../types.d'
|
||||
|
||||
const MAX_LIGHT = L.underground // maximum level where light shines
|
||||
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)
|
||||
|
|
|
@ -26,8 +26,6 @@ export const items = {
|
|||
ore_ruby: { id: 'ore_ruby', name: 'ruby', type: 'ore', icon: 'ore_ruby' } as Item,
|
||||
ore_diamond: { id: 'ore_diamond', name: 'diamond', type: 'ore', icon: 'ore_diamond' } as Item,
|
||||
ore_emerald: { id: 'ore_emerald', name: 'emerald', type: 'ore', icon: 'ore_emerald' } as Item,
|
||||
|
||||
fixture_torch: { id: 'fixture_torch', name: 'Torch', type: 'fixture', icon: 'torch', builds: 'torch' } as Item,
|
||||
} as const
|
||||
|
||||
export type ItemId = keyof typeof items
|
||||
|
|
36
src/types.d.ts
vendored
36
src/types.d.ts
vendored
|
@ -1,7 +1,6 @@
|
|||
import type { ItemId } from './level/items'
|
||||
export type { ItemId } from './level/items'
|
||||
export type ItemQuality = 'wood' | 'iron' | 'diamond'
|
||||
export type ItemType = 'tool' | 'block' | 'ore' | 'fixture'
|
||||
export type ItemType = 'tool' | 'block' | 'ore'
|
||||
|
||||
export interface Item {
|
||||
id: string
|
||||
|
@ -9,9 +8,7 @@ export interface Item {
|
|||
type: ItemType
|
||||
icon: string
|
||||
quality?: ItemQuality
|
||||
// this should be ItemId | BlockType, but has to be string to avoid
|
||||
// a circular type reference
|
||||
builds?: string
|
||||
builds?: BlockType
|
||||
}
|
||||
|
||||
export interface ToolItem extends Item {
|
||||
|
@ -24,8 +21,6 @@ export interface BlockItem extends Item {
|
|||
builds: BlockType
|
||||
}
|
||||
|
||||
type Fixture<T extends string> = `${T}Left` | `${T}Right` | `${T}Ceiling` | `${T}Floor`;
|
||||
|
||||
export type BlockType =
|
||||
| 'air' | 'grass'
|
||||
| 'treeCrown' | 'treeLeaves' | 'treeTrunk' | 'treeRoot'
|
||||
|
@ -33,18 +28,15 @@ export type BlockType =
|
|||
| 'stone' | 'stoneGravel'
|
||||
| 'bedrock' | 'cave'
|
||||
| 'brickWall'
|
||||
| Fixture<'torch'>
|
||||
|
||||
export type Block = {
|
||||
type: BlockType // what is it?
|
||||
hp: number // how long do I need to hit it?
|
||||
walkable: boolean // can I walk through it?
|
||||
climbable?: boolean // can I climb it?
|
||||
transparent?: boolean // can I see through it?
|
||||
fixture?: boolean // is it built by the player?
|
||||
illumination?: number // How many blocks wide is it glowing?
|
||||
color?: string // How is it coloured?
|
||||
drops?: ItemId // what do I get, when loot it?
|
||||
type: BlockType, // what is it?
|
||||
hp: number, // how long do I need to hit it?
|
||||
walkable: boolean, // can I walk through it?
|
||||
climbable?: boolean, // can I climb it?
|
||||
transparent?: boolean, // can I see through it?
|
||||
illuminated?: boolean, // is it glowing?
|
||||
drops?: ItemId, // what do I get, when loot it?
|
||||
}
|
||||
|
||||
// describes a changed block, eg digged or placed by the player
|
||||
|
@ -60,10 +52,11 @@ type ChangedBlock = {
|
|||
y: number
|
||||
newType: BlockType
|
||||
}
|
||||
export type Change = DamagedBlock | ChangedBlock
|
||||
type Change = DamagedBlock | ChangedBlock
|
||||
|
||||
export interface InventoryItem extends Item {
|
||||
amount: number
|
||||
quality: ItemQuality | null
|
||||
}
|
||||
|
||||
export interface Moveable {
|
||||
|
@ -85,10 +78,3 @@ export interface Player extends Moveable {
|
|||
|
||||
export type Direction = 'at' | 'left' | 'right' | 'up' | 'down'
|
||||
|
||||
|
||||
export interface LightSource {
|
||||
x: number
|
||||
y: number
|
||||
strength: number
|
||||
color: string
|
||||
}
|
||||
|
|
|
@ -1,87 +1,116 @@
|
|||
import type { Ref, ComputedRef } from 'vue'
|
||||
import type { LightSource } from '../types.d'
|
||||
import { BLOCK_SIZE, STAGE_WIDTH, STAGE_HEIGHT } from '../level/def'
|
||||
|
||||
type RefOrComputed<T> = Ref<T> | ComputedRef<T>
|
||||
|
||||
export default function useLightMask(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
x: RefOrComputed<number>,
|
||||
y: RefOrComputed<number>,
|
||||
tx: RefOrComputed<number>,
|
||||
ty: RefOrComputed<number>,
|
||||
time: RefOrComputed<number>,
|
||||
lightBarrier: RefOrComputed<number[]>,
|
||||
lightSources: RefOrComputed<LightSource[]>,
|
||||
) {
|
||||
const W = ((STAGE_WIDTH + 2) * BLOCK_SIZE)
|
||||
const H = ((STAGE_HEIGHT + 2) * BLOCK_SIZE)
|
||||
const B = BLOCK_SIZE - 4 // no idea why there is a difference, but it is 4px
|
||||
const BHalf = B / 2
|
||||
|
||||
const playerX = (W - B) / 2 + B / 4
|
||||
const playerY = H / 2 - BHalf
|
||||
const playerY = H / 2 - B / 2
|
||||
const playerLightSize = B * 1.8
|
||||
|
||||
function getAmbientLightColor() {
|
||||
const t = time.value
|
||||
|
||||
// Night time (pale bluish dark: hslpicker.com/#2b293d )
|
||||
if (t > 900 || t < 100) {
|
||||
return `hsl(245, 20%, 20%)`
|
||||
}
|
||||
// Morning hours (gradually more reddish hue)
|
||||
if (t < 250) {
|
||||
const s = Math.round((t - 100) / 1.5) // 0-100%
|
||||
const l = Math.round((t - 100) / 1.875) + 20 // 20-100%
|
||||
return `hsl(0, ${s}%, ${l}%)`
|
||||
}
|
||||
// Evening hours (from neutral white to bluish hue with low saturation)
|
||||
if (t > 700) {
|
||||
const s = 100 - Math.round((t - 700) / 2.5) // 100-20%
|
||||
return `hsl(245, ${s}%, ${s}%)`
|
||||
}
|
||||
// day (neutral white)
|
||||
return `hsl(0, 0%, 100%)`
|
||||
}
|
||||
|
||||
function drawPlayerLight(sizeMul:number) {
|
||||
const t = time.value
|
||||
|
||||
const playerLight = ctx.createRadialGradient(
|
||||
playerX - tx.value, playerY - ty.value, 0,
|
||||
playerX - tx.value, playerY - ty.value, playerLightSize * sizeMul
|
||||
)
|
||||
|
||||
playerLight.addColorStop(0.7, "#FFFA");
|
||||
playerLight.addColorStop(1, "#FFF0");
|
||||
// Add color stops for a light around the player
|
||||
// Night time, lets tone down the light a bit
|
||||
if (t > 900 || t < 100) {
|
||||
playerLight.addColorStop(0.7, "#AA7A");
|
||||
playerLight.addColorStop(1, "#AA70");
|
||||
|
||||
// Morning
|
||||
} else if (t < 150) {
|
||||
playerLight.addColorStop(0.7, "#CCAA");
|
||||
playerLight.addColorStop(1, "#CCA0");
|
||||
|
||||
// Day (neutral white)
|
||||
} else {
|
||||
playerLight.addColorStop(0.7, "#FFFA");
|
||||
playerLight.addColorStop(1, "#FFF0");
|
||||
}
|
||||
|
||||
// Set the fill style and draw a rectangle
|
||||
ctx.fillStyle = playerLight;
|
||||
ctx.fillRect(0, 0, W, H)
|
||||
}
|
||||
|
||||
function drawLightSources() {
|
||||
for (const src of lightSources.value) {
|
||||
const x = src.x * B
|
||||
const y = src.y * B
|
||||
const strength = src.strength + (src.strength * Math.random()) / 10
|
||||
const light = ctx.createRadialGradient(
|
||||
x + BHalf, y - BHalf, 0,
|
||||
x + BHalf, y - BHalf, strength * B,
|
||||
)
|
||||
const color = src.color
|
||||
|
||||
light.addColorStop(0.0, color)
|
||||
light.addColorStop(0.4, `${color}A`)
|
||||
light.addColorStop(1, `${color}0`)
|
||||
|
||||
ctx.fillStyle = light
|
||||
ctx.fillRect(0, 0, W, H)
|
||||
}
|
||||
}
|
||||
|
||||
function drawShadows() {
|
||||
function drawLights() {
|
||||
// used for everything above ground
|
||||
const ambientLight = getAmbientLightColor()
|
||||
const barrier = lightBarrier.value
|
||||
|
||||
for (let col = 0; col < barrier.length; col++) {
|
||||
ctx.fillStyle = ambientLight
|
||||
for (let col = 0; col < W / B; col++) {
|
||||
const level = (barrier[col] - y.value) * B
|
||||
const x = B*col
|
||||
const sw = B
|
||||
const sh = level
|
||||
const sx = col * sw
|
||||
const sy = 0
|
||||
|
||||
// gradient for the shadow that is cast down from the surface
|
||||
const gradient = ctx.createLinearGradient(0, 0, 0, H)
|
||||
gradient.addColorStop(0, '#FFF')
|
||||
gradient.addColorStop(Math.min(level / H, 1), '#FFF')
|
||||
gradient.addColorStop(Math.min((level + B) / H, 1), '#000')
|
||||
ctx.fillStyle = gradient
|
||||
ctx.fillRect(x, 0, B, H)
|
||||
ctx.fillRect(sx, sy, sw, sh)
|
||||
}
|
||||
|
||||
// make light columns wider to illuminate surrounding blocks
|
||||
const extra = Math.floor(B / 2)
|
||||
ctx.fillStyle = ambientLight.slice(0, -1) + ', 40%)'
|
||||
for (let col = 0; col < W / B; col++) {
|
||||
const level = (barrier[col] - y.value) * B
|
||||
const sw = B
|
||||
const sh = level
|
||||
const sx = col * sw
|
||||
const sy = 0
|
||||
|
||||
ctx.fillRect(sx - extra, sy - extra, sw + extra * 2, sh + extra * 2)
|
||||
}
|
||||
|
||||
// TODO: draw light for candles and torches
|
||||
}
|
||||
|
||||
return function update() {
|
||||
// first, throw the world in complete darkness
|
||||
ctx.fillStyle = '#FFFFFF'
|
||||
ctx.fillStyle = '#000000'
|
||||
ctx.fillRect(0, 0, W, H)
|
||||
|
||||
// second, hide what is beneath
|
||||
drawShadows()
|
||||
|
||||
// third, fight the darkness
|
||||
drawLightSources()
|
||||
// second, find and bring light into the world
|
||||
drawLights()
|
||||
|
||||
// finally, draw the players light
|
||||
// with a size multiplicator which might be later used to
|
||||
|
|
|
@ -11,7 +11,7 @@ const player = reactive<Player>({
|
|||
inventory: [],
|
||||
})
|
||||
|
||||
const pocket = (newItem: Item, amount = 1) => {
|
||||
const pocket = (newItem: Item) => {
|
||||
const existing = player.inventory.find(item => item.name === newItem.name)
|
||||
|
||||
if (existing) {
|
||||
|
@ -19,8 +19,9 @@ const pocket = (newItem: Item, amount = 1) => {
|
|||
return existing.amount
|
||||
}
|
||||
player.inventory.push({
|
||||
...newItem,
|
||||
amount,
|
||||
quality: null,
|
||||
amount: 1,
|
||||
...newItem
|
||||
})
|
||||
return 1
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ export function calcSunAngle(tick: number): number {
|
|||
|
||||
export default function useTime() {
|
||||
// the day is split in 1000 parts, so we start in the morning
|
||||
const time = ref(240)
|
||||
const time = ref(250)
|
||||
|
||||
function updateTime() {
|
||||
time.value = (time.value + 0.1) % 1000
|
||||
|
|
Loading…
Add table
Reference in a new issue