The fireball sets the bar, and the rest of the catalog rises to it
Eric's fireball lands as the house style — layered construction, gradient core, glow halo, a directional tail riding rotate="auto" — with its defs scoped per instance via $props.id(), so simultaneous fireballs cannot steal each other's gradients. The rest of the catalog is rebuilt in its image: the waterbolt becomes its cold sibling (spray tail, no turbulence — one heavy filter stack is enough); lightning grows a glowing core and branching forks; the burst blooms through a fire gradient with a shockwave and flying embers; the splash throws a crown of droplets; the shield raises a gradient dome with a rim strike; the pow star flashes white and radiates speed dashes; claws leave tapered gashes; the absorbed card spirals in along a pull ring; the soul is a proper little ghost with eyes, swaying as it rises; fireworks ride colored trails; Chaos catches card slips in its vortex; the pit opens a gradient hole that swallows a faller; ooze splats and flings blobs; the thornbush sheds leaves; slime closes over and pops bubbles; masonry dust goes soft with falling grit. Whiff, tacks, portal, and the sector ghosts keep their simpler forms on purpose — restraint is part of the style. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
fe0318b99b
commit
308f1b6ff9
@@ -1,26 +1,64 @@
|
||||
<script lang="ts">
|
||||
import type { FxOf } from "../fx";
|
||||
import { center } from "./geom";
|
||||
|
||||
let { fx }: { fx: FxOf<"burst"> } = $props();
|
||||
const uid = $props.id();
|
||||
const c = $derived(center(fx.at));
|
||||
const EMBERS = [15, 80, 145, 210, 275, 340];
|
||||
</script>
|
||||
|
||||
<circle cx={c.x} cy={c.y} r="4" class="burst" />
|
||||
<circle cx={c.x} cy={c.y} r="4" class="burst late" />
|
||||
<defs>
|
||||
<radialGradient id={`burst-fire-${uid}`}>
|
||||
<stop offset="0" stop-color="#fffde0" />
|
||||
<stop offset="0.3" stop-color="#ffd34e" />
|
||||
<stop offset="0.65" stop-color="#ff8c1a" stop-opacity="0.85" />
|
||||
<stop offset="1" stop-color="#ef3b08" stop-opacity="0" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
|
||||
<circle cx={c.x} cy={c.y} r="16" fill={`url(#burst-fire-${uid})`} class="bloom" />
|
||||
<circle cx={c.x} cy={c.y} r="6" class="shockwave" />
|
||||
{#each EMBERS as deg (deg)}
|
||||
<circle
|
||||
cx={c.x + 13 * Math.cos((deg * Math.PI) / 180)}
|
||||
cy={c.y + 13 * Math.sin((deg * Math.PI) / 180)}
|
||||
r={deg % 2 === 0 ? 2 : 1.5}
|
||||
class="ember"
|
||||
style={`transform-origin: ${c.x}px ${c.y}px`}
|
||||
/>
|
||||
{/each}
|
||||
|
||||
<style>
|
||||
.burst {
|
||||
.bloom {
|
||||
transform-box: fill-box;
|
||||
transform-origin: center;
|
||||
animation: bloom 0.5s ease-out forwards;
|
||||
}
|
||||
.shockwave {
|
||||
transform-box: fill-box;
|
||||
transform-origin: center;
|
||||
fill: none;
|
||||
stroke: #ff8c1a;
|
||||
stroke-width: 4;
|
||||
animation: ring 0.5s ease-out 0.05s forwards;
|
||||
stroke: #ffd27a;
|
||||
stroke-width: 2.5;
|
||||
animation: shockwave 0.45s ease-out 0.08s forwards;
|
||||
opacity: 0;
|
||||
}
|
||||
.burst.late { stroke: #ffd27a; animation-delay: 0.16s; }
|
||||
@keyframes ring {
|
||||
0% { opacity: 0.95; transform: scale(1); }
|
||||
100% { opacity: 0; transform: scale(5); }
|
||||
.ember {
|
||||
fill: #ff9d19;
|
||||
animation: ember-fly 0.55s ease-out forwards;
|
||||
}
|
||||
@keyframes bloom {
|
||||
0% { opacity: 0; transform: scale(0.2); }
|
||||
25% { opacity: 1; transform: scale(1.2); }
|
||||
100% { opacity: 0; transform: scale(2.4); }
|
||||
}
|
||||
@keyframes shockwave {
|
||||
0% { opacity: 0.9; transform: scale(1); }
|
||||
100% { opacity: 0; transform: scale(6); }
|
||||
}
|
||||
@keyframes ember-fly {
|
||||
0% { opacity: 1; transform: scale(1); }
|
||||
100% { opacity: 0; transform: scale(2.1) rotate(24deg); }
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user