mirror of
https://github.com/tiennm99/tiennm99bot.git
synced 2026-10-11 03:13:46 +00:00
feat(gacha): draw the polychrome on the card engravings only
The sliding rainbow sheen over the whole face and the spectrum foil are gone. 4★ cards are now engraved with pack-cards' epic contour and 5★ cards with the legendary rings or facets, and those engraved lines carry a still rainbow; 3★ cards stay plain. The warm-up also renders a 4★ wish, since the first card with the contour engraving otherwise rendered about seven seconds slower.
This commit is contained in:
1 parent
9665a3b47b
commit
6a4d0a1abb
4 files changed
+37
-69
No files matched your search
+8
-5
@@ -53,9 +53,11 @@ Authorization: Bearer change-me
|
||||
Renders a 6-second portrait wish: a collectible card pack from
|
||||
[pack-cards](https://github.com/paubineau/pack-cards) is torn open, its card
|
||||
spins out with a burst of sparkles, and lands showing the request's `label`,
|
||||
its rank, and its stars under a polychrome rainbow foil. `rarity` (required)
|
||||
picks the rank (`B` for 3★, `A` for 4★, `S` for 5★), the star count, the
|
||||
card's material (rare, epic, legendary), and the colour (blue, purple, gold).
|
||||
its rank, and its stars. `rarity` (required) picks the rank (`B` for 3★, `A`
|
||||
for 4★, `S` for 5★), the star count, the card's material (rare, epic,
|
||||
legendary), and the colour (blue, purple, gold). 4★ and 5★ cards are engraved
|
||||
with pack-cards' rarity textures (contour on 4★; rings or facets on 5★, chosen
|
||||
by the label) drawn in a still polychrome rainbow; 3★ cards are plain.
|
||||
`fps` is `24` or `30`. `width` is the long edge of the portrait frame:
|
||||
`640` renders 360×640 and `854` renders 480×854. Optional `seed` (integer,
|
||||
`0` to `2147483647`) seeds the page's randomness; when omitted the service
|
||||
@@ -72,8 +74,9 @@ server process in `--deterministic-mode`, steps virtual time one frame at a
|
||||
time, tears the pack with a scripted drag, captures each frame, and encodes
|
||||
them with Remotion's bundled ffmpeg. The page (`src/gacha/page/`) and the
|
||||
package are served from disk; the page has no network access. The first render
|
||||
compiles the pack's WebGL shaders in software, which takes several seconds, so
|
||||
server start-up runs one throwaway wish first.
|
||||
compiles the pack's WebGL shaders in software and the first card of each
|
||||
engraving rasterises its texture, which takes several seconds, so server
|
||||
start-up renders a throwaway 5★ and 4★ wish first.
|
||||
|
||||
pack-cards has no npm release, so it is installed from a GitHub tarball pinned
|
||||
to a commit. A moving branch URL would change the tarball's checksum and break
|
||||
|
||||
@@ -49,57 +49,24 @@ body {
|
||||
}
|
||||
|
||||
/*
|
||||
* Polychrome: a rainbow band pattern glazed over the card under the print,
|
||||
* sliding diagonally so the colours shift. Only a transform animates, which
|
||||
* the compositor moves without repainting the foil each frame.
|
||||
* Polychrome engraving: the tooled lines (pack-cards' rarity-epic-contour,
|
||||
* rarity-legendary, and rarity-legendary-facets textures) are filled with a
|
||||
* fixed rainbow instead of the metallic glint, so the colours hold still.
|
||||
*/
|
||||
.wish-polychrome {
|
||||
border-radius: inherit;
|
||||
inset: 0;
|
||||
mix-blend-mode: screen;
|
||||
opacity: var(--wish-polychrome);
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.wish-polychrome::before {
|
||||
animation: wish-polychrome 2.4s ease-in-out infinite alternate;
|
||||
background: repeating-linear-gradient(
|
||||
#stage
|
||||
.recap-card.recap-collectible:is([data-effect='engraved'], [data-effect='engraved-lettering'])
|
||||
.recap-effect-texture::before {
|
||||
background: linear-gradient(
|
||||
125deg,
|
||||
#ff5f9e 0%,
|
||||
#ffb347 6%,
|
||||
#fff275 12%,
|
||||
#6dffb0 18%,
|
||||
#5fd4ff 24%,
|
||||
#9a7bff 30%,
|
||||
#ff5f9e 36%
|
||||
#ffb347 18%,
|
||||
#fff275 34%,
|
||||
#6dffb0 50%,
|
||||
#5fd4ff 66%,
|
||||
#9a7bff 82%,
|
||||
#ff5f9e 100%
|
||||
);
|
||||
content: '';
|
||||
height: 300%;
|
||||
left: -100%;
|
||||
position: absolute;
|
||||
top: -100%;
|
||||
width: 300%;
|
||||
}
|
||||
|
||||
/* The band overhangs the card by a third of its size on each side, so it may slide at most that far. */
|
||||
@keyframes wish-polychrome {
|
||||
to {
|
||||
transform: translate(30%, 30%);
|
||||
}
|
||||
}
|
||||
|
||||
.wish-card > :not(.wish-polychrome) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/*
|
||||
* The spectrum foil sets --accent inline on the card to its own colour; the
|
||||
* print inside keeps the rarity colour.
|
||||
*/
|
||||
.wish-card > * {
|
||||
--accent: var(--wish-accent);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.wish-rank {
|
||||
|
||||
@@ -33,9 +33,6 @@ const el = (tag, className, text) => {
|
||||
return node;
|
||||
};
|
||||
|
||||
/** @type {Record<number, number>} */
|
||||
const polychromeStrength = {3: 0.3, 4: 0.42, 5: 0.55};
|
||||
|
||||
const createFace = () => {
|
||||
const face = el('article', 'wish-card');
|
||||
const header = el('header', 'recap-card-header');
|
||||
@@ -46,10 +43,7 @@ const createFace = () => {
|
||||
content.append(el('span', 'wish-rank', wish.rank), title, el('p', 'wish-stars', '★'.repeat(wish.stars)));
|
||||
const footer = el('footer', 'recap-card-footer');
|
||||
footer.append(el('span', '', `${wish.stars}★`), el('span', '', '01 / 01'));
|
||||
// A rainbow sheen drifting across the whole face, stronger on rarer cards.
|
||||
const sheen = el('span', 'wish-polychrome');
|
||||
sheen.style.setProperty('--wish-polychrome', String(polychromeStrength[wish.stars] ?? 0.3));
|
||||
face.append(sheen, header, content, footer);
|
||||
face.append(header, content, footer);
|
||||
return face;
|
||||
};
|
||||
|
||||
@@ -121,15 +115,15 @@ const burstSparkles = (deck, delay, duration) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Polychrome foil: every rarity gets pack-cards' rainbow holographic print,
|
||||
* from a border on 3★ to the whole card on 4★ and 5★.
|
||||
* Engravings carry the polychrome (page.css): 4★ cards are tooled with the
|
||||
* epic contour, 5★ cards with the legendary rings or facets, picked by
|
||||
* pack-cards from the card's label. 3★ cards stay plain.
|
||||
*
|
||||
* @type {import('pack-cards').AppearanceSettingsOptions['rarities']}
|
||||
*/
|
||||
const polychrome = Object.freeze({
|
||||
rare: {foil: 'holographic', coverage: 'border', palette: 'spectrum', pattern: 'stardust'},
|
||||
epic: {foil: 'holographic', coverage: 'full', palette: 'spectrum', pattern: 'stardust'},
|
||||
legendary: {foil: 'holographic', coverage: 'full', palette: 'spectrum', pattern: 'facets'},
|
||||
const engravings = Object.freeze({
|
||||
epic: {engraving: 'contour'},
|
||||
legendary: {engraving: ['radial', 'facets']},
|
||||
});
|
||||
|
||||
const animate = Element.prototype.animate;
|
||||
@@ -177,7 +171,7 @@ const view = createPackView(stage, {
|
||||
label: 'Gacha',
|
||||
artwork: wish.artwork,
|
||||
labels: {title: 'Gacha', swipe: '', tap: ''},
|
||||
appearance: {opening: 'animated', motion: 'interactive', glow: wish.glow, pack_zoom: true, rarities: polychrome},
|
||||
appearance: {opening: 'animated', motion: 'interactive', glow: wish.glow, pack_zoom: true, rarities: engravings},
|
||||
});
|
||||
|
||||
view.showPack({
|
||||
|
||||
@@ -152,13 +152,17 @@ export const closeGachaBrowser = async () => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Pays the shared browser's one-time shader compilation with a throwaway
|
||||
* wish, so the first real request renders as fast as later ones.
|
||||
* Pays the shared browser's one-time costs with throwaway wishes, so the first
|
||||
* real request renders as fast as later ones: the WebGL shader compilation,
|
||||
* and the first raster of each card's engraving texture. 4★ and 5★ cards use
|
||||
* different engravings, so both are warmed.
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export const warmGachaBrowser = async () => {
|
||||
await renderGachaVideo({label: 'Warm-up', rarity: 5, fps: 24, width: 640, seed: 1}, {timeoutInMilliseconds: 120000});
|
||||
for (const rarity of /** @type {const} */ ([5, 4])) {
|
||||
await renderGachaVideo({label: 'Warm-up', rarity, fps: 24, width: 640, seed: 1}, {timeoutInMilliseconds: 120000});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user