248 lines
4.0 KiB
Vue
248 lines
4.0 KiB
Vue
|
|
<template>
|
||
|
|
<PixelCard size="large" class="pet-screen">
|
||
|
|
<div class="screen-header">
|
||
|
|
<h2 class="pet-name">{{ petName }}</h2>
|
||
|
|
</div>
|
||
|
|
<div class="pet-viewport">
|
||
|
|
<div class="background-animation">
|
||
|
|
<!-- CSS animated background -->
|
||
|
|
<div class="cloud cloud-1"></div>
|
||
|
|
<div class="cloud cloud-2"></div>
|
||
|
|
<div class="cloud cloud-3"></div>
|
||
|
|
</div>
|
||
|
|
<div class="pet-sprite" :class="petEmotion">
|
||
|
|
<!-- CSS-based pet pixel art -->
|
||
|
|
<div class="pet-body"></div>
|
||
|
|
<div class="pet-eye-left"></div>
|
||
|
|
<div class="pet-eye-right"></div>
|
||
|
|
<div class="pet-mouth"></div>
|
||
|
|
</div>
|
||
|
|
<div v-if="poopCount > 0" class="poop-container">
|
||
|
|
<div v-for="i in Math.min(poopCount, 4)" :key="i" class="poop-pile">
|
||
|
|
<div class="poop-base"></div>
|
||
|
|
<div class="poop-stink"></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</PixelCard>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script setup>
|
||
|
|
import PixelCard from './PixelCard.vue'
|
||
|
|
|
||
|
|
const props = defineProps({
|
||
|
|
petName: {
|
||
|
|
type: String,
|
||
|
|
default: 'Pet'
|
||
|
|
},
|
||
|
|
petStage: {
|
||
|
|
type: String,
|
||
|
|
default: 'egg'
|
||
|
|
},
|
||
|
|
petEmotion: {
|
||
|
|
type: String,
|
||
|
|
default: 'happy'
|
||
|
|
},
|
||
|
|
poopCount: {
|
||
|
|
type: Number,
|
||
|
|
default: 0
|
||
|
|
}
|
||
|
|
})
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.pet-screen {
|
||
|
|
width: 100%;
|
||
|
|
max-width: 600px;
|
||
|
|
margin: 0 auto;
|
||
|
|
}
|
||
|
|
|
||
|
|
.screen-header {
|
||
|
|
text-align: center;
|
||
|
|
margin-bottom: 16px;
|
||
|
|
padding-bottom: 8px;
|
||
|
|
border-bottom: 3px solid #000;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pet-name {
|
||
|
|
font-size: 16px;
|
||
|
|
text-transform: uppercase;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pet-viewport {
|
||
|
|
position: relative;
|
||
|
|
width: 100%;
|
||
|
|
height: 300px;
|
||
|
|
background: linear-gradient(180deg, #87CEEB 0%, #E0F6FF 100%);
|
||
|
|
overflow: hidden;
|
||
|
|
border: 3px solid #000;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Background clouds animation */
|
||
|
|
.background-animation {
|
||
|
|
position: absolute;
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.cloud {
|
||
|
|
position: absolute;
|
||
|
|
background: white;
|
||
|
|
border: 2px solid #ddd;
|
||
|
|
border-radius: 50%;
|
||
|
|
opacity: 0.7;
|
||
|
|
animation: float 20s infinite linear;
|
||
|
|
}
|
||
|
|
|
||
|
|
.cloud-1 {
|
||
|
|
width: 60px;
|
||
|
|
height: 30px;
|
||
|
|
top: 20%;
|
||
|
|
left: -60px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.cloud-2 {
|
||
|
|
width: 80px;
|
||
|
|
height: 40px;
|
||
|
|
top: 40%;
|
||
|
|
left: -80px;
|
||
|
|
animation-delay: -7s;
|
||
|
|
animation-duration: 25s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.cloud-3 {
|
||
|
|
width: 50px;
|
||
|
|
height: 25px;
|
||
|
|
top: 60%;
|
||
|
|
left: -50px;
|
||
|
|
animation-delay: -14s;
|
||
|
|
animation-duration: 30s;
|
||
|
|
}
|
||
|
|
|
||
|
|
@keyframes float {
|
||
|
|
from {
|
||
|
|
transform: translateX(0);
|
||
|
|
}
|
||
|
|
to {
|
||
|
|
transform: translateX(calc(600px + 100%));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Pet sprite */
|
||
|
|
.pet-sprite {
|
||
|
|
position: absolute;
|
||
|
|
bottom: 80px;
|
||
|
|
left: 50%;
|
||
|
|
transform: translateX(-50%);
|
||
|
|
width: 80px;
|
||
|
|
height: 80px;
|
||
|
|
image-rendering: pixelated;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pet-body {
|
||
|
|
width: 60px;
|
||
|
|
height: 60px;
|
||
|
|
background: #FFD700;
|
||
|
|
border: 3px solid #000;
|
||
|
|
position: absolute;
|
||
|
|
bottom: 0;
|
||
|
|
left: 10px;
|
||
|
|
border-radius: 8px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pet-eye-left,
|
||
|
|
.pet-eye-right {
|
||
|
|
width: 8px;
|
||
|
|
height: 8px;
|
||
|
|
background: #000;
|
||
|
|
border-radius: 50%;
|
||
|
|
position: absolute;
|
||
|
|
top: 20px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pet-eye-left {
|
||
|
|
left: 25px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pet-eye-right {
|
||
|
|
right: 25px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pet-mouth {
|
||
|
|
width: 20px;
|
||
|
|
height: 10px;
|
||
|
|
border: 2px solid #000;
|
||
|
|
border-top: none;
|
||
|
|
border-radius: 0 0 10px 10px;
|
||
|
|
position: absolute;
|
||
|
|
bottom: 15px;
|
||
|
|
left: 30px;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Emotions */
|
||
|
|
.pet-sprite.happy .pet-mouth {
|
||
|
|
border-radius: 0 0 20px 20px;
|
||
|
|
height: 12px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pet-sprite.sad .pet-mouth {
|
||
|
|
border-radius: 20px 20px 0 0;
|
||
|
|
border-top: 2px solid #000;
|
||
|
|
border-bottom: none;
|
||
|
|
bottom: 20px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pet-sprite.sick {
|
||
|
|
filter: hue-rotate(90deg);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Poop */
|
||
|
|
.poop-container {
|
||
|
|
position: absolute;
|
||
|
|
bottom: 60px;
|
||
|
|
left: 20px;
|
||
|
|
display: flex;
|
||
|
|
gap: 10px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.poop-pile {
|
||
|
|
position: relative;
|
||
|
|
width: 30px;
|
||
|
|
height: 30px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.poop-base {
|
||
|
|
width: 24px;
|
||
|
|
height: 24px;
|
||
|
|
background: #8B4513;
|
||
|
|
border: 2px solid #000;
|
||
|
|
border-radius: 50% 50% 40% 40%;
|
||
|
|
position: absolute;
|
||
|
|
bottom: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.poop-stink {
|
||
|
|
width: 4px;
|
||
|
|
height: 12px;
|
||
|
|
background: #888;
|
||
|
|
opacity: 0.5;
|
||
|
|
position: absolute;
|
||
|
|
top: -12px;
|
||
|
|
left: 10px;
|
||
|
|
animation: stinkWave 1.5s infinite;
|
||
|
|
}
|
||
|
|
|
||
|
|
@keyframes stinkWave {
|
||
|
|
0%, 100% {
|
||
|
|
transform: translateY(0);
|
||
|
|
opacity: 0.5;
|
||
|
|
}
|
||
|
|
50% {
|
||
|
|
transform: translateY(-8px);
|
||
|
|
opacity: 0.2;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</style>
|