piclets / src /lib /components /Battle /BattleEffects.svelte
Fraser's picture
anim
81b3c3b
raw
history blame
4.45 kB
<script lang="ts">
import { fade } from 'svelte/transition';
export let effects: Array<{type: string, emoji: string, duration: number}> = [];
export let flash: boolean = false;
</script>
<!-- Flash overlay -->
{#if flash}
<div class="flash-overlay" transition:fade={{ duration: 200 }}></div>
{/if}
<!-- Particle effects -->
{#each effects as effect (effect)}
<div class="effect-particle {effect.type}" style="animation-duration: {effect.duration}ms">
<span class="effect-emoji">{effect.emoji}</span>
</div>
{/each}
<style>
.flash-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(255, 255, 255, 0.8);
z-index: 10;
pointer-events: none;
}
.effect-particle {
position: absolute;
pointer-events: none;
z-index: 5;
animation-fill-mode: forwards;
}
.effect-emoji {
font-size: 24px;
display: block;
filter: drop-shadow(0 0 4px rgba(0, 0, 0, 0.3));
}
/* Damage and status effects */
.effect-particle.burn,
.effect-particle.poison,
.effect-particle.paralyze,
.effect-particle.sleep,
.effect-particle.freeze {
top: 20%;
left: 50%;
animation: statusEffect linear;
}
/* Stat changes */
.effect-particle.attackUp,
.effect-particle.defenseUp,
.effect-particle.speedUp,
.effect-particle.accuracyUp {
bottom: 30%;
left: 50%;
animation: statIncrease ease-out;
}
.effect-particle.attackDown,
.effect-particle.defenseDown,
.effect-particle.speedDown,
.effect-particle.accuracyDown {
top: 30%;
left: 50%;
animation: statDecrease ease-out;
}
/* Special effects */
.effect-particle.critical,
.effect-particle.superEffective {
top: 10%;
left: 50%;
animation: criticalEffect ease-out;
}
.effect-particle.notVeryEffective,
.effect-particle.miss {
top: 40%;
left: 50%;
animation: missEffect ease-out;
}
.effect-particle.heal {
bottom: 20%;
left: 50%;
animation: healEffect ease-out;
}
/* Animations */
@keyframes statusEffect {
0% {
transform: translate(-50%, 0) scale(0.5);
opacity: 0;
}
20% {
transform: translate(-50%, -10px) scale(1.2);
opacity: 1;
}
40% {
transform: translate(-50%, -5px) scale(1);
opacity: 1;
}
100% {
transform: translate(-50%, -20px) scale(0.8);
opacity: 0;
}
}
@keyframes statIncrease {
0% {
transform: translate(-50%, 0) scale(0.5);
opacity: 0;
}
30% {
transform: translate(-50%, -30px) scale(1.3);
opacity: 1;
}
70% {
transform: translate(-50%, -40px) scale(1.1);
opacity: 1;
}
100% {
transform: translate(-50%, -60px) scale(0.7);
opacity: 0;
}
}
@keyframes statDecrease {
0% {
transform: translate(-50%, 0) scale(0.5);
opacity: 0;
}
30% {
transform: translate(-50%, 20px) scale(1.3);
opacity: 1;
}
70% {
transform: translate(-50%, 30px) scale(1.1);
opacity: 1;
}
100% {
transform: translate(-50%, 50px) scale(0.7);
opacity: 0;
}
}
@keyframes criticalEffect {
0% {
transform: translate(-50%, 0) scale(0.3) rotate(-10deg);
opacity: 0;
}
20% {
transform: translate(-50%, -20px) scale(1.5) rotate(5deg);
opacity: 1;
}
40% {
transform: translate(-50%, -15px) scale(1.3) rotate(-2deg);
opacity: 1;
}
60% {
transform: translate(-50%, -25px) scale(1.4) rotate(1deg);
opacity: 1;
}
100% {
transform: translate(-50%, -40px) scale(0.8) rotate(0deg);
opacity: 0;
}
}
@keyframes missEffect {
0% {
transform: translate(-50%, 0) scale(1);
opacity: 0;
}
20% {
transform: translate(-50%, 0) scale(1.2);
opacity: 0.7;
}
80% {
transform: translate(-50%, 0) scale(1.1);
opacity: 0.3;
}
100% {
transform: translate(-50%, 0) scale(1);
opacity: 0;
}
}
@keyframes healEffect {
0% {
transform: translate(-50%, 20px) scale(0.5);
opacity: 0;
}
30% {
transform: translate(-50%, -10px) scale(1.2);
opacity: 1;
}
70% {
transform: translate(-50%, -30px) scale(1);
opacity: 1;
}
100% {
transform: translate(-50%, -50px) scale(0.6);
opacity: 0;
}
}
</style>