formalize inventory, cute walking animation

This commit is contained in:
Norman Köhring 2023-02-13 21:57:31 +01:00
parent ecf1a9cd67
commit cd8bcbcc47
4 changed files with 53 additions and 36 deletions

View file

@ -18,14 +18,16 @@ const level = createLevel(STAGE_WIDTH + 2, STAGE_HEIGHT + 2)
let animationFrame = 0 let animationFrame = 0
let lastTick = 0 let lastTick = 0
let x = ref(0) const x = ref(0)
let y = ref(0) const y = ref(0)
const floorX = computed(() => Math.floor(x.value)) const floorX = computed(() => Math.floor(x.value))
const floorY = computed(() => Math.floor(y.value)) const floorY = computed(() => Math.floor(y.value))
const tx = computed(() => (x.value - floorX.value) * -BLOCK_SIZE) const tx = computed(() => (x.value - floorX.value) * -BLOCK_SIZE)
const ty = computed(() => (y.value - floorY.value) * -BLOCK_SIZE) const ty = computed(() => (y.value - floorY.value) * -BLOCK_SIZE)
const rows = computed(() => level.grid(floorX.value, floorY.value)) const rows = computed(() => level.grid(floorX.value, floorY.value))
const walking = ref(false)
type Surroundings = { type Surroundings = {
at: Block, at: Block,
left: Block, left: Block,
@ -101,6 +103,8 @@ const move = (thisTick: number): void => {
const optimal = 16 // 16ms per tick => 60 FPS const optimal = 16 // 16ms per tick => 60 FPS
const movementMultiplier = (tickDelta / optimal) * 2 const movementMultiplier = (tickDelta / optimal) * 2
walking.value = !!dx_
x.value += dx_ * movementMultiplier x.value += dx_ * movementMultiplier
y.value += dy_ * movementMultiplier y.value += dy_ * movementMultiplier
lastTick = thisTick lastTick = thisTick
@ -121,10 +125,10 @@ onMounted(() => {
</template> </template>
</div> </div>
<div id="player2" :class="direction"> <div id="player" :class="[direction, { walking }]">
<div class="head"></div> <div class="head"></div>
<div class="body"></div> <div class="body"></div>
<div class="feet"> <div class="legs">
<div class="left"></div> <div class="left"></div>
<div class="right"></div> <div class="right"></div>
</div> </div>

View file

@ -34,7 +34,7 @@
.night .block, .night #player { filter: brightness(0.3) saturate(30%); } .night .block, .night #player { filter: brightness(0.3) saturate(30%); }
#player2 { #player {
--player-width: 64px; --player-width: 64px;
--player-height: 76px; --player-height: 76px;
position: absolute; position: absolute;
@ -45,33 +45,45 @@
width: var(--player-width); width: var(--player-width);
height: var(--player-height); height: var(--player-height);
} }
#player2 > div { #player > div {
margin: auto; margin: auto;
background: transparent center no-repeat; background: transparent center no-repeat;
background-size: cover; background-size: cover;
} }
#player2.right > div { #player.right {
transform: scaleX(-1); transform: scaleX(-1);
} }
#player2 > .head { #player > .head {
width: 46px; width: 46px;
height: 46px; height: 46px;
background-image: url(/Characters/Alien/alien_head.png); background-image: url(/Characters/Alien/alien_head.png);
z-index: 1; z-index: 1;
} }
#player2 > .body { #player > .body {
width: 22px; width: 22px;
height: 24px; height: 24px;
margin-top: -8px; margin-top: -8px;
background-image: url(/Characters/Alien/alien_body.png); background-image: url(/Characters/Alien/alien_body.png);
} }
#player2 > .feet { #player > .legs {
position: relative;
width: 14px; width: 14px;
height: 18px; height: 18px;
margin-top: -8px;
background-image: url(/Characters/Alien/alien_leg.png);
} }
#player2 > .arms { #player > .legs > div {
position: absolute;
width: 14px;
height: 18px;
background-image: url(/Characters/Alien/alien_leg.png);
transform-origin: top center;
}
#player.walking > .legs > div.right {
animation: dangle .4s ease infinite both;
}
#player.walking > .legs > div.left {
animation: dangle .4s ease infinite reverse both;
}
#player > .arms {
position: absolute; position: absolute;
width: 8px; width: 8px;
height: 16px; height: 16px;
@ -79,17 +91,7 @@
left: 30px; left: 30px;
background-image: url(/Characters/Alien/alien_arm.png); background-image: url(/Characters/Alien/alien_arm.png);
} }
#player { .block {
position: absolute;
left: calc(var(--field-width) / 2);
top: calc(var(--field-height) / 2);
background-image: url(./dwarf_right.png);
}
#player.right { background-image: url(./dwarf_right.png); }
#player.left { background-image: url(./dwarf_left.png); }
#player.up { background-image: url(./dwarf_back.png); }
#player.down { background-image: url(./dwarf_back.png); }
#player, .block {
flex: 0 0 auto; flex: 0 0 auto;
width: var(--block-size); width: var(--block-size);
height: var(--block-size); height: var(--block-size);
@ -107,3 +109,8 @@
display: flex; display: flex;
flex-flow: row wrap; flex-flow: row wrap;
} }
@keyframes dangle {
from { transform: rotate(20deg); }
to { transform: rotate(-20deg); }
}

View file

@ -9,9 +9,9 @@ defineProps<Props>();
// inventory size is 12, and it is so empty // inventory size is 12, and it is so empty
const slots = ref([ const slots = ref([
{ name: 'Spade', type: 'tool', icon: 'spade' }, { name: 'Shovel', type: 'tool', icon: 'shovel', quality: 'bronze' },
{ name: 'Sword', type: 'weapon', icon: 'sword' }, { name: 'Sword', type: 'weapon', icon: 'sword', quality: 'bronze' },
null, { name: 'Pick Axe', type: 'tool', icon: 'pick', quality: 'bronze' },
null, null,
null, null,
null, null,
@ -22,7 +22,6 @@ const slots = ref([
null, null,
null, null,
]) ])
</script> </script>
<template> <template>
@ -33,7 +32,7 @@ const slots = ref([
<ol> <ol>
<li v-for="item in slots" <li v-for="item in slots"
:class="[item?.type, item?.icon]" :class="[item?.type, item?.icon, item?.quality]"
> >
<i v-if="item === null">(empty)</i> <i v-if="item === null">(empty)</i>
<template v-else> <template v-else>
@ -81,10 +80,13 @@ li > i, li > b {
background: black; background: black;
font-size: .8em; font-size: .8em;
} }
.tool.spade { .tool.shovel.bronze {
background-image: url("../assets/tools/spade.svg"); background-image: url("/Items/shovel_bronze.png");
} }
.weapon.sword { .weapon.sword.bronze {
background-image: url("../assets/weapons/sword.svg"); background-image: url("/Items/sword_bronze.png");
}
.tool.pick.bronze {
background-image: url("/Items/pick_bronze.png");
} }
</style> </style>

10
src/vite-env.d.ts vendored
View file

@ -9,16 +9,20 @@ declare global {
vy: number // velocity on the y-axis vy: number // velocity on the y-axis
} }
type Inventory = { type InventoryItem = {
name: string
type: string
icon: string
quality?: 'bronze' | 'iron' | 'silver' | 'gold' | 'diamond'
} }
interface Player extends Moveable { interface Player extends Moveable {
inventory: Inventory inventory: InventoryItem[]
} }
interface Npc extends Moveable { interface Npc extends Moveable {
hostile: boolean hostile: boolean
inventory: Inventory inventory: InventoryItem[]
} }
} }