Improved battle animations.

This commit is contained in:
Greyson Parrelli
2026-07-23 21:39:01 -04:00
parent ce70b1d89f
commit 9d9acc4577
3 changed files with 234 additions and 24 deletions
+111 -5
View File
@@ -1481,6 +1481,32 @@ h3 {
filter: drop-shadow(0 3px 4px rgba(0, 0, 0, 0.5));
}
/* A bought card in flight from the shop slot to its landing spot in your hand.
The element is positioned over its destination slot (fixed) and inverted back
to where it was clicked (--dx/--dy/--s), then plays that offset out — a FLIP
from shop to hand. Its deck slot stays empty (.is-arriving) until it lands. */
@keyframes buy-fly {
from {
transform: translate(var(--dx), var(--dy)) scale(var(--s));
}
to {
transform: translate(0, 0) scale(1);
}
}
.buy-flyer {
position: fixed;
z-index: 60;
transform-origin: top left;
animation: buy-fly 480ms cubic-bezier(0.5, 0.02, 0.3, 1) forwards;
pointer-events: none;
filter: drop-shadow(0 12px 18px rgba(0, 0, 0, 0.5));
}
.card-cell.is-arriving {
opacity: 0;
}
/* --- the pet in play --- */
.battle-unit-zone {
@@ -1540,6 +1566,59 @@ h3 {
pointer-events: none;
}
/* A freshly dealt food (apple) sails in from the deck — up and toward the outer
edge — and settles onto the fan, rather than blinking into place. Direction
follows the side the deck sits on (see food-in-left / food-in-right). */
@keyframes food-in-left {
from {
opacity: 0;
transform: translate(-64px, -52px) rotate(-14deg) scale(0.6);
}
to {
opacity: 1;
transform: translate(0, 0) rotate(0) scale(1);
}
}
@keyframes food-in-right {
from {
opacity: 0;
transform: translate(64px, -52px) rotate(14deg) scale(0.6);
}
to {
opacity: 1;
transform: translate(0, 0) rotate(0) scale(1);
}
}
.food-fan-card.food-in-left {
animation: food-in-left 440ms cubic-bezier(0.2, 0.8, 0.3, 1) backwards;
}
.food-fan-card.food-in-right {
animation: food-in-right 440ms cubic-bezier(0.2, 0.8, 0.3, 1) backwards;
}
/* A pet that faints with a pending effect rises up out of the arena into the
set-aside row, shrinking from its arena size to the smaller set-aside size. */
@keyframes setaside-in {
from {
opacity: 0;
transform: translateY(150px) scale(1.2);
}
55% {
opacity: 1;
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.setaside-card.setaside-in {
animation: setaside-in 600ms cubic-bezier(0.2, 0.8, 0.3, 1) backwards;
}
.battle-unit {
position: relative;
flex-shrink: 0;
@@ -1557,19 +1636,46 @@ h3 {
font-size: 1.5rem;
}
@keyframes unit-reveal {
/* A pet flips face-up off its deck: it starts over the stack (outer edge) still
turned edge-on, then slides in toward its arena slot while turning to face us.
The deck sits to the outer side of each unit, so each side pulls the reveal in
from its own edge. */
@keyframes unit-reveal-left {
from {
opacity: 0;
transform: rotateY(90deg) scale(0.8);
transform: translateX(-108px) perspective(760px) rotateY(-92deg) scale(0.92);
}
45% {
opacity: 1;
}
to {
opacity: 1;
transform: rotateY(0) scale(1);
transform: translateX(0) perspective(760px) rotateY(0deg) scale(1);
}
}
.battle-unit.unit-reveal {
animation: unit-reveal 500ms ease;
@keyframes unit-reveal-right {
from {
opacity: 0;
transform: translateX(108px) perspective(760px) rotateY(92deg) scale(0.92);
}
45% {
opacity: 1;
}
to {
opacity: 1;
transform: translateX(0) perspective(760px) rotateY(0deg) scale(1);
}
}
.battle-unit.unit-reveal-left {
transform-origin: left center;
animation: unit-reveal-left 520ms cubic-bezier(0.2, 0.8, 0.3, 1);
}
.battle-unit.unit-reveal-right {
transform-origin: right center;
animation: unit-reveal-right 520ms cubic-bezier(0.2, 0.8, 0.3, 1);
}
/* --- rock dice --- */