fix types
This commit is contained in:
parent
b8335d9392
commit
be68f73721
13 changed files with 108 additions and 130 deletions
28
src/App.vue
28
src/App.vue
|
@ -1,15 +1,16 @@
|
|||
<script setup lang="ts">
|
||||
import type { Block, Direction, Item, InventoryItem } from './types.d'
|
||||
import { ref, computed, watch, onMounted } from 'vue'
|
||||
import Help from './screens/help.vue'
|
||||
import Inventory from './screens/inventory.vue'
|
||||
|
||||
import { BLOCK_SIZE, STAGE_WIDTH, STAGE_HEIGHT, type Block } from './level/def'
|
||||
import { BLOCK_SIZE, STAGE_WIDTH, STAGE_HEIGHT } from './level/def'
|
||||
import { getItem, getItemClass } from './level/items'
|
||||
import createLevel from './level'
|
||||
|
||||
import usePlayer from './util/usePlayer'
|
||||
import useTime from './util/useTime'
|
||||
import useInput from './util/useInput'
|
||||
import usePlayer, { type InventoryItem } from './util/usePlayer'
|
||||
import useLightMap from './util/useLightMap'
|
||||
|
||||
const { updateTime, time, timeOfDay, clock } = useTime()
|
||||
|
@ -20,9 +21,9 @@ const level = createLevel(STAGE_WIDTH + 2, STAGE_HEIGHT + 2)
|
|||
const lightMapEl = ref<HTMLCanvasElement | undefined>(undefined)
|
||||
let updateLightMap: ReturnType<typeof useLightMap>
|
||||
|
||||
pocket({ name: 'Shovel', type: 'tool', icon: 'shovel', quality: 'wood' })
|
||||
pocket({ name: 'Sword', type: 'weapon', icon: 'sword', quality: 'wood' })
|
||||
pocket({ name: 'Pick Axe', type: 'tool', icon: 'pick', quality: 'wood' })
|
||||
pocket({ name: 'Wooden Shovel', type: 'tool', icon: 'shovel', quality: 'wood' })
|
||||
pocket({ name: 'Wooden Sword', type: 'tool', icon: 'sword', quality: 'wood' })
|
||||
pocket({ name: 'Wooden Pick Axe', type: 'tool', icon: 'pick', quality: 'wood' })
|
||||
|
||||
let animationFrame = 0
|
||||
let lastTick = 0
|
||||
|
@ -54,14 +55,7 @@ const arriving = ref(true)
|
|||
const walking = ref(false)
|
||||
const inventorySelection = ref<InventoryItem>(player.inventory[0])
|
||||
|
||||
type Surroundings = {
|
||||
at: Block,
|
||||
left: Block,
|
||||
right: Block,
|
||||
up: Block,
|
||||
down: Block,
|
||||
}
|
||||
const surroundings = computed<Surroundings>(() => {
|
||||
const surroundings = computed<Record<Direction, Block>>(() => {
|
||||
const _update = mapUpdateCount.value // reactivity trigger
|
||||
const x = px.value
|
||||
const y = py.value
|
||||
|
@ -100,7 +94,7 @@ function dig(blockX: number, blockY: number, block: Block) {
|
|||
// finally dig that block
|
||||
// TODO: damage blocks first
|
||||
level.change({
|
||||
type: 'exchange',
|
||||
change: 'exchange',
|
||||
x: floorX.value + blockX,
|
||||
y: floorY.value + blockY,
|
||||
newType: 'air'
|
||||
|
@ -120,14 +114,14 @@ function build(blockX: number, blockY: number, block: InventoryItem) {
|
|||
if (!blockToBuild) return
|
||||
|
||||
level.change({
|
||||
type: 'exchange',
|
||||
change: 'exchange',
|
||||
x: floorX.value + blockX,
|
||||
y: floorY.value + blockY,
|
||||
newType: blockToBuild
|
||||
})
|
||||
mapUpdateCount.value = mapUpdateCount.value + 1
|
||||
|
||||
const newAmount = unpocket(block)
|
||||
const newAmount = unpocket(block as Item)
|
||||
if (newAmount < 1) inventorySelection.value = player.inventory[0]
|
||||
}
|
||||
|
||||
|
@ -268,8 +262,6 @@ onMounted(() => {
|
|||
x:{{ floorX }}, y:{{ floorY }}
|
||||
<template v-if="paused">(PAUSED)</template>
|
||||
<template v-else>({{ clock }})</template>
|
||||
<br/>
|
||||
Map Changes: {{ mapUpdateCount }}
|
||||
</div>
|
||||
|
||||
<Inventory :shown="inventory"
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
.item.tool-shovel-wood { background-image: url("/Items/shovel_bronze.png"); }
|
||||
.item.weapon-sword-wood { background-image: url("/Items/sword_bronze.png"); }
|
||||
.item.tool-sword-wood { background-image: url("/Items/sword_bronze.png"); }
|
||||
.item.tool-pick-wood { background-image: url("/Items/pick_bronze.png"); }
|
||||
|
||||
.item.tool-shovel-iron { background-image: url("/Items/shovel_iron.png"); }
|
||||
.item.tool-sword-iron { background-image: url("/Items/sword_iron.png"); }
|
||||
.item.tool-pick-iron { background-image: url("/Items/pick_iron.png"); }
|
||||
|
||||
.item.tool-shovel-diamond { background-image: url("/Items/shovel_diamond.png"); }
|
||||
.item.tool-sword-diamond { background-image: url("/Items/sword_diamond.png"); }
|
||||
.item.tool-pick-diamond { background-image: url("/Items/pick_diamond.png"); }
|
||||
|
||||
.item.block-wood { background-image: url("/Tiles/wood.png"); }
|
||||
.item.block-dirt { background-image: url("/Tiles/dirt.png"); }
|
||||
.item.block-stone { background-image: url("/Tiles/stone.png"); }
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import type { NoiseFunction2D } from 'simplex-noise'
|
||||
import {blockTypes as T, level as L, probability as P, type Block} from './def'
|
||||
import { blockTypes as T, level as L, probability as P } from './def'
|
||||
import type { Block } from '../types.d'
|
||||
|
||||
const TREE_ROOT = [T.treeRootLeft, T.treeRootMiddle, T.treeRootRight]
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import type { NoiseFunction2D } from 'simplex-noise'
|
||||
import {blockTypes as T, level as L, probability as P, type Block} from './def'
|
||||
import { blockTypes as T, level as L, probability as P } from './def'
|
||||
import type { Block } from '../types.d'
|
||||
|
||||
export default function createBlockGenerator(rand: NoiseFunction2D) {
|
||||
// randomly generate a block
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { DropItem } from './items'
|
||||
import type { Block, BlockType } from '../types.d'
|
||||
|
||||
export const BLOCK_SIZE = 64 // each block is 64̨̣̌̇x64 pixel in size and equals 1m
|
||||
export const BLOCK_SIZE = 64 // each block is 64x64 px in size and equals 1m
|
||||
export const RECIPROCAL = 1 / BLOCK_SIZE
|
||||
|
||||
export const STAGE_WIDTH = 20 // 20*64 = 1280 pixel wide stage
|
||||
|
@ -9,23 +9,6 @@ export const STAGE_HEIGHT = 12 // 12*64 = 768 pixel high stage
|
|||
|
||||
export const GRAVITY = 10 // blocks per second
|
||||
|
||||
export type Block = {
|
||||
type: string, // 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?: DropItem, // what do I get, when loot it?
|
||||
}
|
||||
|
||||
export type BlockType =
|
||||
| 'air' | 'grass'
|
||||
| 'treeCrown' | 'treeLeaves' | 'treeTrunk' | 'treeRoot'
|
||||
| 'soil' | 'soilGravel' | 'stone' | 'stoneGravel'
|
||||
| 'bedrock' | 'cave'
|
||||
| 'brickWall'
|
||||
|
||||
export const blockTypes: Record<BlockType, Block> = {
|
||||
// Transparent Blocks
|
||||
air: { type: 'air', hp: Infinity, walkable: true, transparent: true },
|
||||
|
@ -35,6 +18,9 @@ export const blockTypes: Record<BlockType, Block> = {
|
|||
treeLeaves: { type: 'treeLeaves', hp: 1, walkable: true, transparent: true, drops: 'leaves' },
|
||||
treeTrunk: { type: 'treeTrunk', hp: 10, walkable: true, climbable: true, transparent: true, drops: 'wood' },
|
||||
treeRoot: { type: 'treeRoot', hp: 10, walkable: true, climbable: true, drops: 'wood' },
|
||||
treeRootLeft: { type: 'treeRootLeft', hp: 10, walkable: true, climbable: true, drops: 'wood' },
|
||||
treeRootMiddle: { type: 'treeRootMiddle', hp: 10, walkable: true, climbable: true, drops: 'wood' },
|
||||
treeRootRight: { type: 'treeRootRight', hp: 10, walkable: true, climbable: true, drops: 'wood' },
|
||||
// Opaque Natural Blocks
|
||||
grass: { type: 'grass', hp: 5, walkable: false, drops: 'dirt' },
|
||||
soil: { type: 'soil', hp: 5, walkable: false, drops: 'dirt' },
|
||||
|
|
|
@ -3,22 +3,8 @@ import { createNoise2D, type NoiseFunction2D } from 'simplex-noise'
|
|||
import createBlockGenerator from './blockGen'
|
||||
import createBlockExtender from './blockExt'
|
||||
|
||||
import {blockTypes, blockTypes as T, level as L, type Block, type BlockType} from './def'
|
||||
|
||||
// describes a changed block, eg digged or placed by the player
|
||||
type DamagedBlock = {
|
||||
type: 'damage'
|
||||
x: number
|
||||
y: number
|
||||
damage: number
|
||||
}
|
||||
type ChangedBlock = {
|
||||
type: 'exchange'
|
||||
x: number
|
||||
y: number
|
||||
newType: BlockType
|
||||
}
|
||||
type Change = DamagedBlock | ChangedBlock
|
||||
import { blockTypes, blockTypes as T } from './def'
|
||||
import type { Block, Change } from '../types.d'
|
||||
|
||||
const MAX_LIGHT = 100 // maximum level where light shines
|
||||
|
||||
|
@ -50,7 +36,7 @@ export default function createLevel(width: number, height: number, seed = 'extre
|
|||
if (changes) {
|
||||
const maxLevel = levelOffset + height
|
||||
changes.forEach(c => {
|
||||
if (c.type !== 'exchange' || c.y < levelOffset || c.y >= maxLevel) return
|
||||
if (c.change !== 'exchange' || c.y < levelOffset || c.y >= maxLevel) return
|
||||
_grid[c.y - levelOffset][c.x - columnOffset] = blockTypes[c.newType]
|
||||
})
|
||||
}
|
||||
|
@ -71,7 +57,7 @@ export default function createLevel(width: number, height: number, seed = 'extre
|
|||
const changes = _changes[columnOffset + col]
|
||||
if (changes) {
|
||||
const change = changes.find(c => c.y === level)
|
||||
if (change && change.type === 'exchange') block = blockTypes[change.newType]
|
||||
if (change && change.change === 'exchange') block = blockTypes[change.newType]
|
||||
}
|
||||
|
||||
previousBlock = block
|
||||
|
@ -107,7 +93,7 @@ export default function createLevel(width: number, height: number, seed = 'extre
|
|||
let lastGenY = 0
|
||||
generate(0, 0)
|
||||
|
||||
function grid(x: number, y: number, force: false): Block[][] {
|
||||
function grid(x: number, y: number, force = false): Block[][] {
|
||||
if (force || lastGenX !== x || lastGenY !== y) {
|
||||
generate(x, y)
|
||||
lastGenX = x
|
||||
|
|
|
@ -1,26 +1,21 @@
|
|||
import type { BlockType } from './def'
|
||||
import type { InventoryItem } from '../util/usePlayer'
|
||||
|
||||
export type ItemQuality = 'wood' | 'iron' | 'silver' | 'gold' | 'diamond'
|
||||
export type ItemType = 'tool' | 'weapon' | 'block' | 'ore'
|
||||
|
||||
export type DropItem =
|
||||
| 'Shovel' | 'Pick Axe' | 'Sword'
|
||||
| 'leaves' | 'dirt' | 'wood' | 'stone' | 'gravel'
|
||||
| 'coal' | 'iron' | 'silver' | 'gold' | 'ruby' | 'diamond' | 'emerald'
|
||||
|
||||
export interface Item {
|
||||
name: DropItem
|
||||
type: ItemType
|
||||
icon: string
|
||||
hasQuality?: boolean
|
||||
builds?: BlockType
|
||||
}
|
||||
import type { ItemQuality, Item, InventoryItem } from '../types.d'
|
||||
|
||||
export const items: Item[] = [
|
||||
{ name: 'Shovel', type: 'tool', icon: 'shovel', hasQuality: true },
|
||||
{ name: 'Pick Axe', type: 'tool', icon: 'pick', hasQuality: true },
|
||||
{ name: 'Sword', type: 'weapon', icon: 'sword', hasQuality: true },
|
||||
{ name: 'Wooden Shovel', type: 'tool', icon: 'shovel', quality: 'wood' },
|
||||
{ name: 'Wooden Pick Axe', type: 'tool', icon: 'pick', quality: 'wood' },
|
||||
{ name: 'Wooden Sword', type: 'tool', icon: 'sword', quality: 'wood' },
|
||||
|
||||
{ name: 'Iron Shovel', type: 'tool', icon: 'shovel', quality: 'iron' },
|
||||
{ name: 'Iron Pick Axe', type: 'tool', icon: 'pick', quality: 'iron' },
|
||||
{ name: 'Iron Sword', type: 'tool', icon: 'sword', quality: 'iron' },
|
||||
|
||||
{ name: 'Diamond Shovel', type: 'tool', icon: 'shovel', quality: 'diamond' },
|
||||
{ name: 'Diamond Pick Axe', type: 'tool', icon: 'pick', quality: 'diamond' },
|
||||
{ name: 'Diamond Sword', type: 'tool', icon: 'sword', quality: 'diamond' },
|
||||
|
||||
{ name: 'Wooden Shovel', type: 'tool', icon: 'shovel', quality: 'wood' },
|
||||
{ name: 'Wooden Pick Axe', type: 'tool', icon: 'pick', quality: 'wood' },
|
||||
{ name: 'Wooden Sword', type: 'tool', icon: 'sword', quality: 'wood' },
|
||||
|
||||
{ name: 'leaves', type: 'block', icon: 'leaves', builds: 'treeLeaves' },
|
||||
{ name: 'dirt', type: 'block', icon: 'dirt', builds: 'soil' },
|
||||
|
@ -39,13 +34,11 @@ export const items: Item[] = [
|
|||
|
||||
export const damage: Record<ItemQuality, number> = {
|
||||
wood: 1,
|
||||
iron: 2,
|
||||
silver: 3,
|
||||
gold: 5,
|
||||
diamond: 8,
|
||||
iron: 3,
|
||||
diamond: 5,
|
||||
}
|
||||
|
||||
export function getItem(name: string, quality = null) {
|
||||
export function getItem(name: string, quality?: ItemQuality) {
|
||||
const item = items.find(i => i.name === name)
|
||||
if (item) {
|
||||
return {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, computed, onUnmounted } from 'vue'
|
||||
import { getItemClass } from '../level/items'
|
||||
import type { InventoryItem } from '../util/usePlayer'
|
||||
import type { InventoryItem } from '../types.d'
|
||||
|
||||
export interface Props {
|
||||
items: InventoryItem[]
|
||||
|
@ -10,7 +10,7 @@ export interface Props {
|
|||
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<{
|
||||
(event: 'selection', value: InventoryItem | null): void
|
||||
(event: 'selection', value: InventoryItem): void
|
||||
}>()
|
||||
|
||||
// inventory size is 15
|
||||
|
|
52
src/types.d.ts
vendored
52
src/types.d.ts
vendored
|
@ -1,8 +1,10 @@
|
|||
export type ItemQuality = 'wood' | 'iron' | 'silver' | 'gold' | 'diamond'
|
||||
export type ItemType = 'tool' | 'weapon' | 'block' | 'ore'
|
||||
export type ItemQuality = 'wood' | 'iron' | 'diamond'
|
||||
export type ItemType = 'tool' | 'block' | 'ore'
|
||||
|
||||
export type DropItem =
|
||||
| 'Shovel' | 'Pick Axe' | 'Sword'
|
||||
| 'Wooden Shovel' | 'Iron Shovel' | 'Diamond Shovel'
|
||||
| 'Wooden Pick Axe' | 'Iron Pick Axe' | 'Diamond Pick Axe'
|
||||
| 'Wooden Sword' | 'Iron Sword' | 'Diamond Sword'
|
||||
| 'leaves' | 'dirt' | 'wood' | 'stone' | 'gravel'
|
||||
| 'coal' | 'iron' | 'silver' | 'gold' | 'ruby' | 'diamond' | 'emerald'
|
||||
|
||||
|
@ -10,12 +12,29 @@ export interface Item {
|
|||
name: DropItem
|
||||
type: ItemType
|
||||
icon: string
|
||||
hasQuality?: boolean
|
||||
quality?: ItemQuality
|
||||
builds?: BlockType
|
||||
}
|
||||
|
||||
export interface ToolItem extends Item {
|
||||
type: 'tool'
|
||||
quality: ItemQuality
|
||||
}
|
||||
|
||||
export interface BlockItem extends Item {
|
||||
type: 'block'
|
||||
builds: BlockType
|
||||
}
|
||||
|
||||
export type BlockType =
|
||||
| 'air' | 'grass'
|
||||
| 'treeCrown' | 'treeLeaves' | 'treeTrunk' | 'treeRoot' | 'treeRootRight' | 'treeRootMiddle' | 'treeRootLeft'
|
||||
| 'soil' | 'soilGravel' | 'stone' | 'stoneGravel'
|
||||
| 'bedrock' | 'cave'
|
||||
| 'brickWall'
|
||||
|
||||
export type Block = {
|
||||
type: string, // what is 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?
|
||||
|
@ -24,12 +43,20 @@ export type Block = {
|
|||
drops?: DropItem, // what do I get, when loot it?
|
||||
}
|
||||
|
||||
export type BlockType =
|
||||
| 'air' | 'grass'
|
||||
| 'treeCrown' | 'treeLeaves' | 'treeTrunk' | 'treeRoot'
|
||||
| 'soil' | 'soilGravel' | 'stone' | 'stoneGravel'
|
||||
| 'bedrock' | 'cave'
|
||||
| 'brickWall'
|
||||
// describes a changed block, eg digged or placed by the player
|
||||
type DamagedBlock = {
|
||||
change: 'damage'
|
||||
x: number
|
||||
y: number
|
||||
damage: number
|
||||
}
|
||||
type ChangedBlock = {
|
||||
change: 'exchange'
|
||||
x: number
|
||||
y: number
|
||||
newType: BlockType
|
||||
}
|
||||
type Change = DamagedBlock | ChangedBlock
|
||||
|
||||
export interface InventoryItem extends Item {
|
||||
amount: number
|
||||
|
@ -52,3 +79,6 @@ export interface Npc extends Moveable {
|
|||
export interface Player extends Moveable {
|
||||
inventory: InventoryItem[]
|
||||
}
|
||||
|
||||
export type Direction = 'at' | 'left' | 'right' | 'up' | 'down'
|
||||
|
||||
|
|
|
@ -135,11 +135,11 @@ export default function useBackground (canvasEl: HTMLCanvasElement, w: number, h
|
|||
const grH = h / rayQuality
|
||||
|
||||
const ctx = canvasEl.getContext('2d')
|
||||
if (ctx === null) return // like, how old is your browser?
|
||||
if (ctx === null) return () => {} // like, how old is your browser?
|
||||
|
||||
const grCanvasEl = document.createElement('canvas')
|
||||
const grCtx = grCanvasEl.getContext('2d')
|
||||
if (grCtx === null) return // like, how old is your browser?
|
||||
if (grCtx === null) return () => {} // for real, how old is it?
|
||||
|
||||
grCanvasEl.width = grW
|
||||
grCanvasEl.height = grH
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import type { ComputedRef } from 'vue'
|
||||
import type { Ref, ComputedRef } from 'vue'
|
||||
import { BLOCK_SIZE, STAGE_WIDTH, STAGE_HEIGHT } from '../level/def'
|
||||
|
||||
type RefOrComputed<T> = Ref<T> | ComputedRef<T>
|
||||
|
||||
export default function useLightMap(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
x: ComputedRef<number>,
|
||||
y: ComputedRef<number>,
|
||||
tx: ComputedRef<number>,
|
||||
ty: ComputedRef<number>,
|
||||
time: ComputedRef<number>,
|
||||
lightBarrier: ComputedRef<number[]>,
|
||||
x: RefOrComputed<number>,
|
||||
y: RefOrComputed<number>,
|
||||
tx: RefOrComputed<number>,
|
||||
ty: RefOrComputed<number>,
|
||||
time: RefOrComputed<number>,
|
||||
lightBarrier: RefOrComputed<number[]>,
|
||||
) {
|
||||
const W = ((STAGE_WIDTH + 2) * BLOCK_SIZE)
|
||||
const H = ((STAGE_HEIGHT + 2) * BLOCK_SIZE)
|
||||
|
|
|
@ -1,15 +1,6 @@
|
|||
import { computed, reactive } from 'vue'
|
||||
import { RECIPROCAL, STAGE_WIDTH, STAGE_HEIGHT } from '../level/def'
|
||||
import type { Item, ItemQuality } from '../level/items'
|
||||
|
||||
export interface InventoryItem extends Item {
|
||||
amount: number
|
||||
quality: ItemQuality | null
|
||||
}
|
||||
|
||||
export interface Player extends Moveable {
|
||||
inventory: InventoryItem[]
|
||||
}
|
||||
import type { Item, Player } from '../types.d'
|
||||
|
||||
const player = reactive<Player>({
|
||||
x: Math.round((STAGE_WIDTH + 2) / 2),
|
||||
|
@ -17,7 +8,7 @@ const player = reactive<Player>({
|
|||
lastDir: 0,
|
||||
vx: 0,
|
||||
vy: 1, // always falling, because of gravity
|
||||
inventory: [], // not yet in use
|
||||
inventory: [],
|
||||
})
|
||||
|
||||
const pocket = (newItem: Item) => {
|
||||
|
|
12
src/vite-env.d.ts
vendored
12
src/vite-env.d.ts
vendored
|
@ -1,18 +1,6 @@
|
|||
/// <reference types="vite/client" />
|
||||
|
||||
declare global {
|
||||
interface Moveable {
|
||||
x: number // position on x-axis (fixed for the player)
|
||||
y: number // position on y-axis (fixed for the player)
|
||||
lastDir: number // store last face direction
|
||||
vx: number // velocity on the x-axis
|
||||
vy: number // velocity on the y-axis
|
||||
}
|
||||
|
||||
interface Npc extends Moveable {
|
||||
hostile: boolean
|
||||
inventory: InventoryItem[]
|
||||
}
|
||||
}
|
||||
|
||||
export {}
|
||||
|
|
Loading…
Add table
Reference in a new issue