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,33 +1,69 @@
|
||||
<script lang="ts">
|
||||
import type { FxOf } from "../fx";
|
||||
import { center } from "./geom";
|
||||
|
||||
let { fx }: { fx: FxOf<"bolt"> } = $props();
|
||||
/** A fresh jagged path every strike. */
|
||||
const points = $derived.by(() => {
|
||||
const uid = $props.id();
|
||||
|
||||
/** A fresh jagged path every strike, plus two forks off mid-joints. */
|
||||
const geom = $derived.by(() => {
|
||||
const a = center(fx.from), b = center(fx.to);
|
||||
const segs = 6;
|
||||
const pts: string[] = [`${a.x},${a.y}`];
|
||||
const joints: { x: number; y: number }[] = [a];
|
||||
for (let i = 1; i < segs; i++) {
|
||||
const t = i / segs;
|
||||
pts.push(`${(a.x + (b.x - a.x) * t + (Math.random() - 0.5) * 16).toFixed(1)},${(a.y + (b.y - a.y) * t + (Math.random() - 0.5) * 16).toFixed(1)}`);
|
||||
joints.push({
|
||||
x: a.x + (b.x - a.x) * t + (Math.random() - 0.5) * 16,
|
||||
y: a.y + (b.y - a.y) * t + (Math.random() - 0.5) * 16,
|
||||
});
|
||||
}
|
||||
pts.push(`${b.x},${b.y}`);
|
||||
return pts.join(" ");
|
||||
joints.push(b);
|
||||
const points = joints.map((p) => `${p.x.toFixed(1)},${p.y.toFixed(1)}`).join(" ");
|
||||
const fork = (j: { x: number; y: number }) => {
|
||||
const dx = (Math.random() - 0.5) * 26, dy = (Math.random() - 0.5) * 26;
|
||||
return `M ${j.x} ${j.y} l ${dx / 2} ${dy / 2} l ${dx / 2 + (Math.random() - 0.5) * 8} ${dy / 2}`;
|
||||
};
|
||||
return { points, forks: [fork(joints[2]!), fork(joints[4]!)] };
|
||||
});
|
||||
</script>
|
||||
|
||||
<polyline {points} class="bolt" />
|
||||
<defs>
|
||||
<filter id={`bolt-glow-${uid}`} x="-60%" y="-60%" width="220%" height="220%">
|
||||
<feGaussianBlur stdDeviation="4" result="blur" />
|
||||
<feMerge><feMergeNode in="blur" /><feMergeNode in="SourceGraphic" /></feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
|
||||
<g class="bolt" filter={`url(#bolt-glow-${uid})`}>
|
||||
<polyline points={geom.points} class="wide" />
|
||||
{#each geom.forks as d, i (i)}
|
||||
<path {d} class="fork" />
|
||||
{/each}
|
||||
<polyline points={geom.points} class="core" />
|
||||
</g>
|
||||
|
||||
<style>
|
||||
.bolt {
|
||||
.bolt .wide {
|
||||
fill: none;
|
||||
stroke: #ffe94d;
|
||||
stroke-width: 3;
|
||||
stroke-width: 5;
|
||||
stroke-linejoin: round;
|
||||
filter: drop-shadow(0 0 7px rgba(255, 233, 77, 0.95));
|
||||
animation: flicker 0.5s steps(2, jump-none) forwards;
|
||||
opacity: 0.55;
|
||||
}
|
||||
@keyframes flicker {
|
||||
.bolt .fork {
|
||||
fill: none;
|
||||
stroke: #fff6b0;
|
||||
stroke-width: 1.6;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
.bolt .core {
|
||||
fill: none;
|
||||
stroke: #fffdf0;
|
||||
stroke-width: 1.8;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
.bolt { animation: bolt-flicker 0.5s steps(2, jump-none) forwards; }
|
||||
@keyframes bolt-flicker {
|
||||
0% { opacity: 0; } 15% { opacity: 1; } 40% { opacity: 0.3; }
|
||||
60% { opacity: 1; } 100% { opacity: 0; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user