@wallarm-org/design-system 0.55.0 → 0.55.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/AnimatedBackground/AnimatedBackground.d.ts +2 -31
- package/dist/components/AnimatedBackground/AnimatedBackground.js +102 -25
- package/dist/components/AnimatedBackground/GameHud.d.ts +15 -0
- package/dist/components/AnimatedBackground/GameHud.js +141 -0
- package/dist/components/AnimatedBackground/index.d.ts +2 -3
- package/dist/components/AnimatedBackground/index.js +1 -2
- package/dist/components/AnimatedBackground/module/constants.d.ts +28 -0
- package/dist/components/AnimatedBackground/module/constants.js +29 -0
- package/dist/components/AnimatedBackground/module/engine-colors.d.ts +16 -0
- package/dist/components/AnimatedBackground/module/engine-colors.js +49 -0
- package/dist/components/AnimatedBackground/module/engine-grid.d.ts +6 -0
- package/dist/components/AnimatedBackground/module/engine-grid.js +14 -0
- package/dist/components/AnimatedBackground/module/engine.d.ts +33 -0
- package/dist/components/AnimatedBackground/module/engine.js +206 -0
- package/dist/components/AnimatedBackground/module/game-logic.d.ts +87 -0
- package/dist/components/AnimatedBackground/module/game-logic.js +472 -0
- package/dist/components/AnimatedBackground/module/game-renderer.d.ts +16 -0
- package/dist/components/AnimatedBackground/module/game-renderer.js +121 -0
- package/dist/components/AnimatedBackground/module/index.d.ts +4 -0
- package/dist/components/AnimatedBackground/module/index.js +4 -0
- package/dist/components/AnimatedBackground/module/lib.d.ts +2 -0
- package/dist/components/AnimatedBackground/{lib.js → module/lib.js} +2 -1
- package/dist/components/AnimatedBackground/module/types.d.ts +77 -0
- package/dist/components/AnimatedBackground/module/useGameKeyboard.d.ts +3 -0
- package/dist/components/AnimatedBackground/module/useGameKeyboard.js +73 -0
- package/dist/components/Flex/Flex.d.ts +1 -1
- package/dist/components/SegmentedControl/SegmentedControlSeparator.d.ts +1 -1
- package/dist/components/Separator/Separator.d.ts +1 -1
- package/dist/components/Skeleton/Skeleton.d.ts +1 -1
- package/dist/components/Stack/Stack.d.ts +1 -1
- package/dist/metadata/components.json +23 -13
- package/dist/theme/components/login-background.css +36 -0
- package/package.json +1 -1
- package/dist/components/AnimatedBackground/classes.d.ts +0 -3
- package/dist/components/AnimatedBackground/classes.js +0 -13
- package/dist/components/AnimatedBackground/engine.d.ts +0 -9
- package/dist/components/AnimatedBackground/engine.js +0 -217
- package/dist/components/AnimatedBackground/lib.d.ts +0 -3
- package/dist/components/AnimatedBackground/types.d.ts +0 -24
- /package/dist/components/AnimatedBackground/{types.js → module/types.js} +0 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { CLEAN_BASE_ALPHA, CLEAN_DOT_HALF_BASE, CLEAN_DOT_HALF_BLOOM, GLOW_INNER_ALPHA, GLOW_INNER_HALF, GLOW_LIFETIME, GLOW_OUTER_ALPHA, GLOW_OUTER_HALF, SPAWN_PROBABILITY, SWEEP_OFFSET_GUARD } from "./constants.js";
|
|
2
|
+
import { FALLBACK_ACCENT, FALLBACK_BASE, FALLBACK_CAUGHT, FALLBACK_DOT, alphaIdx, buildPalette, parseColor } from "./engine-colors.js";
|
|
3
|
+
import { buildGrid, sweepX } from "./engine-grid.js";
|
|
4
|
+
import { CANNON_HALF_W, createGameLogic } from "./game-logic.js";
|
|
5
|
+
import { createGameRenderer } from "./game-renderer.js";
|
|
6
|
+
function createSweepEngine(canvas, options) {
|
|
7
|
+
const maybeCtx = canvas.getContext('2d');
|
|
8
|
+
if (!maybeCtx) throw new Error('2D canvas context unavailable');
|
|
9
|
+
const ctx = maybeCtx;
|
|
10
|
+
let opts = {
|
|
11
|
+
...options
|
|
12
|
+
};
|
|
13
|
+
const host = {
|
|
14
|
+
w: 0,
|
|
15
|
+
h: 0,
|
|
16
|
+
dots: [],
|
|
17
|
+
opts,
|
|
18
|
+
tanTilt: Math.tan(options.tilt * Math.PI / 180)
|
|
19
|
+
};
|
|
20
|
+
const game = createGameLogic(host);
|
|
21
|
+
const rc = {
|
|
22
|
+
ctx,
|
|
23
|
+
dotPalette: buildPalette(FALLBACK_DOT),
|
|
24
|
+
accentPalette: buildPalette(FALLBACK_ACCENT),
|
|
25
|
+
caughtPalette: buildPalette(FALLBACK_CAUGHT),
|
|
26
|
+
caughtRgb: FALLBACK_CAUGHT,
|
|
27
|
+
shadowPalette: buildPalette({
|
|
28
|
+
r: 0,
|
|
29
|
+
g: 0,
|
|
30
|
+
b: 0
|
|
31
|
+
})
|
|
32
|
+
};
|
|
33
|
+
const gr = createGameRenderer(rc, game, host);
|
|
34
|
+
let baseColor = FALLBACK_BASE;
|
|
35
|
+
const latched = [];
|
|
36
|
+
let lastLatch = -1 / 0;
|
|
37
|
+
let rafId = null;
|
|
38
|
+
let running = false;
|
|
39
|
+
let lastFrameT = 0;
|
|
40
|
+
function resolveColors() {
|
|
41
|
+
const cs = getComputedStyle(canvas);
|
|
42
|
+
const dot = parseColor(cs.getPropertyValue(opts.dotColorVar)) ?? FALLBACK_DOT;
|
|
43
|
+
const accent = parseColor(cs.getPropertyValue(opts.accentColorVar)) ?? FALLBACK_ACCENT;
|
|
44
|
+
const caught = parseColor(cs.getPropertyValue(opts.caughtColorVar)) ?? FALLBACK_CAUGHT;
|
|
45
|
+
baseColor = cs.getPropertyValue(opts.baseColorVar).trim() || FALLBACK_BASE;
|
|
46
|
+
rc.dotPalette = buildPalette(dot);
|
|
47
|
+
rc.accentPalette = buildPalette(accent);
|
|
48
|
+
rc.caughtPalette = buildPalette(caught);
|
|
49
|
+
rc.caughtRgb = caught;
|
|
50
|
+
}
|
|
51
|
+
function resize() {
|
|
52
|
+
const rect = canvas.getBoundingClientRect();
|
|
53
|
+
host.w = Math.max(1, Math.round(rect.width));
|
|
54
|
+
host.h = Math.max(1, Math.round(rect.height));
|
|
55
|
+
const dpr = Math.min(window.devicePixelRatio || 1, 2);
|
|
56
|
+
canvas.width = Math.round(host.w * dpr);
|
|
57
|
+
canvas.height = Math.round(host.h * dpr);
|
|
58
|
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
59
|
+
host.dots = buildGrid(host.w, host.h, opts.spacing);
|
|
60
|
+
host.tanTilt = Math.tan(opts.tilt * Math.PI / 180);
|
|
61
|
+
resolveColors();
|
|
62
|
+
game.cannonX = Math.max(CANNON_HALF_W, Math.min(host.w - CANNON_HALF_W, game.cannonX));
|
|
63
|
+
if (!running) renderStatic();
|
|
64
|
+
}
|
|
65
|
+
function drawClean(t) {
|
|
66
|
+
const { w, h, dots, tanTilt } = host;
|
|
67
|
+
const sx = sweepX(t, w, opts.sweepPeriod);
|
|
68
|
+
const intensity = opts.intensity;
|
|
69
|
+
for (const dot of dots){
|
|
70
|
+
const dist = Math.abs(dot.x - (sx + (h / 2 - dot.y) * tanTilt));
|
|
71
|
+
const inBloom = dist < opts.bloomRadius;
|
|
72
|
+
const alpha = inBloom ? (CLEAN_BASE_ALPHA + (opts.bloomAlpha - CLEAN_BASE_ALPHA) * (1 - dist / opts.bloomRadius)) * intensity : CLEAN_BASE_ALPHA * intensity;
|
|
73
|
+
const idx = alphaIdx(alpha);
|
|
74
|
+
if (0 === idx) continue;
|
|
75
|
+
ctx.fillStyle = rc.dotPalette[idx];
|
|
76
|
+
const half = inBloom ? CLEAN_DOT_HALF_BLOOM : CLEAN_DOT_HALF_BASE;
|
|
77
|
+
ctx.fillRect(dot.x - half, dot.y - half, 2 * half, 2 * half);
|
|
78
|
+
}
|
|
79
|
+
const sweepAt = (y)=>sx + (h / 2 - y) * tanTilt;
|
|
80
|
+
if (t - lastLatch > opts.anomalyInterval && Math.random() < SPAWN_PROBABILITY && dots.length) {
|
|
81
|
+
const cand = dots[Math.random() * dots.length | 0];
|
|
82
|
+
if (cand.x < sweepAt(cand.y) - SWEEP_OFFSET_GUARD) {
|
|
83
|
+
lastLatch = t;
|
|
84
|
+
latched.push({
|
|
85
|
+
x: cand.x,
|
|
86
|
+
y: cand.y,
|
|
87
|
+
t0: t
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
let kept = 0;
|
|
92
|
+
for (const glow of latched){
|
|
93
|
+
const age = t - glow.t0;
|
|
94
|
+
if (age >= GLOW_LIFETIME) continue;
|
|
95
|
+
latched[kept++] = glow;
|
|
96
|
+
const fade = 1 - age / GLOW_LIFETIME;
|
|
97
|
+
const glowIdx = alphaIdx(GLOW_OUTER_ALPHA * fade);
|
|
98
|
+
if (glowIdx > 0) {
|
|
99
|
+
ctx.fillStyle = rc.accentPalette[glowIdx];
|
|
100
|
+
ctx.fillRect(glow.x - GLOW_OUTER_HALF, glow.y - GLOW_OUTER_HALF, 2 * GLOW_OUTER_HALF, 2 * GLOW_OUTER_HALF);
|
|
101
|
+
}
|
|
102
|
+
ctx.fillStyle = rc.accentPalette[alphaIdx(GLOW_INNER_ALPHA * fade)];
|
|
103
|
+
ctx.fillRect(glow.x - GLOW_INNER_HALF, glow.y - GLOW_INNER_HALF, 2 * GLOW_INNER_HALF, 2 * GLOW_INNER_HALF);
|
|
104
|
+
}
|
|
105
|
+
latched.length = kept;
|
|
106
|
+
}
|
|
107
|
+
function drawHalftone(t) {
|
|
108
|
+
gr.drawGameDots(t);
|
|
109
|
+
}
|
|
110
|
+
function frame(t) {
|
|
111
|
+
ctx.fillStyle = baseColor;
|
|
112
|
+
ctx.fillRect(0, 0, host.w, host.h);
|
|
113
|
+
if ('halftone' === opts.texture) {
|
|
114
|
+
drawHalftone(t);
|
|
115
|
+
gr.drawCaughtEffects(t);
|
|
116
|
+
gr.drawCannon(t);
|
|
117
|
+
gr.drawBullets();
|
|
118
|
+
} else drawClean(t);
|
|
119
|
+
}
|
|
120
|
+
const DT_CLAMP = 0.05;
|
|
121
|
+
function tick(ts) {
|
|
122
|
+
if (!running) return;
|
|
123
|
+
const now = ts / 1000;
|
|
124
|
+
const rawDt = lastFrameT > 0 ? now - lastFrameT : 0;
|
|
125
|
+
const dt = Math.min(rawDt, DT_CLAMP);
|
|
126
|
+
if (rawDt > DT_CLAMP) {
|
|
127
|
+
const skip = rawDt - dt;
|
|
128
|
+
game.adjustTimeMarkers(skip);
|
|
129
|
+
for (const glow of latched)glow.t0 += skip;
|
|
130
|
+
if (lastLatch > -1 / 0) lastLatch += skip;
|
|
131
|
+
}
|
|
132
|
+
lastFrameT = now;
|
|
133
|
+
if ('halftone' === opts.texture) game.gameSim(now, dt);
|
|
134
|
+
game.pruneCaughtEffects(now);
|
|
135
|
+
frame(now);
|
|
136
|
+
rafId = requestAnimationFrame(tick);
|
|
137
|
+
}
|
|
138
|
+
function onVisibility() {
|
|
139
|
+
if (document.hidden) {
|
|
140
|
+
if (null !== rafId) cancelAnimationFrame(rafId);
|
|
141
|
+
rafId = null;
|
|
142
|
+
} else if (running && null === rafId) rafId = requestAnimationFrame(tick);
|
|
143
|
+
}
|
|
144
|
+
function start() {
|
|
145
|
+
if (running) return;
|
|
146
|
+
running = true;
|
|
147
|
+
lastFrameT = 0;
|
|
148
|
+
document.addEventListener('visibilitychange', onVisibility);
|
|
149
|
+
if (!document.hidden) rafId = requestAnimationFrame(tick);
|
|
150
|
+
}
|
|
151
|
+
function stop() {
|
|
152
|
+
running = false;
|
|
153
|
+
if (null !== rafId) cancelAnimationFrame(rafId);
|
|
154
|
+
rafId = null;
|
|
155
|
+
document.removeEventListener('visibilitychange', onVisibility);
|
|
156
|
+
game.setFiring(false);
|
|
157
|
+
game.setCannonDir(0);
|
|
158
|
+
}
|
|
159
|
+
function renderStatic(t = 1.4) {
|
|
160
|
+
const savedT = lastFrameT;
|
|
161
|
+
frame(t);
|
|
162
|
+
lastFrameT = savedT;
|
|
163
|
+
}
|
|
164
|
+
function setOptions(next) {
|
|
165
|
+
const keys = Object.keys(next);
|
|
166
|
+
if (0 === keys.length) {
|
|
167
|
+
resolveColors();
|
|
168
|
+
if (!running) renderStatic();
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const spacingChanged = void 0 !== next.spacing && next.spacing !== opts.spacing;
|
|
172
|
+
opts = {
|
|
173
|
+
...opts,
|
|
174
|
+
...next
|
|
175
|
+
};
|
|
176
|
+
host.opts = opts;
|
|
177
|
+
host.tanTilt = Math.tan(opts.tilt * Math.PI / 180);
|
|
178
|
+
if (spacingChanged) host.dots = buildGrid(host.w, host.h, opts.spacing);
|
|
179
|
+
resolveColors();
|
|
180
|
+
if (!running) renderStatic();
|
|
181
|
+
}
|
|
182
|
+
function exitGame() {
|
|
183
|
+
game.exitGame();
|
|
184
|
+
}
|
|
185
|
+
resize();
|
|
186
|
+
return {
|
|
187
|
+
start,
|
|
188
|
+
stop,
|
|
189
|
+
setOptions,
|
|
190
|
+
renderStatic,
|
|
191
|
+
resize,
|
|
192
|
+
setGameActive: (active)=>game.setGameActive(active),
|
|
193
|
+
catchAt: (x, y)=>game.catchAt(x, y, running),
|
|
194
|
+
setMode: (mode)=>game.setMode(mode),
|
|
195
|
+
startRound: ()=>{
|
|
196
|
+
game.startRound();
|
|
197
|
+
lastFrameT = performance.now() / 1000;
|
|
198
|
+
},
|
|
199
|
+
exitGame,
|
|
200
|
+
setCannonDir: (dir)=>game.setCannonDir(dir),
|
|
201
|
+
setFiring: (on)=>game.setFiring(on),
|
|
202
|
+
onStats: (cb)=>game.onStats(cb),
|
|
203
|
+
setExclusion: (box)=>game.setExclusion(box)
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
export { createSweepEngine };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { Dot } from './engine-grid';
|
|
2
|
+
import type { EngineOptions, GameStats } from './types';
|
|
3
|
+
export declare const ROUND_ATTACKS = 100;
|
|
4
|
+
export declare const MAX_TARGETS = 6;
|
|
5
|
+
export declare const MAX_BULLETS = 24;
|
|
6
|
+
export declare const BULLET_SPEED = 720;
|
|
7
|
+
export declare const FIRE_CADENCE = 0.18;
|
|
8
|
+
export declare const CANNON_SPEED = 420;
|
|
9
|
+
export declare const TARGET_LIFE = 4;
|
|
10
|
+
export declare const ARMED_SPAWN = 0.55;
|
|
11
|
+
export declare const HIT_R2: number;
|
|
12
|
+
export declare const CLICK_RADIUS = 52;
|
|
13
|
+
export declare const REVEAL_DELAY = 0.3;
|
|
14
|
+
export declare const ARM_RISE = 0.45;
|
|
15
|
+
export declare const FIRST_SPAWN_DELAY = 0.7;
|
|
16
|
+
export declare const ANOMALY_R = 42;
|
|
17
|
+
export declare const ANOMALY_R_SQ: number;
|
|
18
|
+
export declare const CAUGHT_DUR = 1.4;
|
|
19
|
+
export declare const CANNON_HALF_W = 16;
|
|
20
|
+
export declare const CANNON_BASE_OFFSET = 26;
|
|
21
|
+
export declare const CANNON_BARREL_Y = 40;
|
|
22
|
+
export declare const HUD_CLEAR_W = 120;
|
|
23
|
+
export declare const HUD_CLEAR_H = 140;
|
|
24
|
+
export declare const CARD_CLEAR_PAD = 48;
|
|
25
|
+
export declare const SPAWN_EDGE = 24;
|
|
26
|
+
export declare const CANNON_CLEAR = 72;
|
|
27
|
+
export declare const SPAWN_TRIES = 24;
|
|
28
|
+
export declare const IDLE_ANOMALY_LIFE = 2.4;
|
|
29
|
+
export declare const VERDICTS: readonly ["BLOCKED", "TERMINATED", "NEUTRALIZED", "QUARANTINED", "MITIGATED", "CONTAINED"];
|
|
30
|
+
export interface Anomaly {
|
|
31
|
+
x: number;
|
|
32
|
+
y: number;
|
|
33
|
+
t0: number;
|
|
34
|
+
life: number;
|
|
35
|
+
caught: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface Bullet {
|
|
38
|
+
x: number;
|
|
39
|
+
y: number;
|
|
40
|
+
}
|
|
41
|
+
export interface CaughtCell {
|
|
42
|
+
x: number;
|
|
43
|
+
y: number;
|
|
44
|
+
half: number;
|
|
45
|
+
ao: number;
|
|
46
|
+
}
|
|
47
|
+
export interface CaughtEffect {
|
|
48
|
+
x: number;
|
|
49
|
+
y: number;
|
|
50
|
+
t0: number;
|
|
51
|
+
cells: CaughtCell[];
|
|
52
|
+
label: string;
|
|
53
|
+
}
|
|
54
|
+
export type GameMode = 'idle' | 'armed' | 'over';
|
|
55
|
+
export interface GameEngineHost {
|
|
56
|
+
w: number;
|
|
57
|
+
h: number;
|
|
58
|
+
dots: Dot[];
|
|
59
|
+
opts: EngineOptions;
|
|
60
|
+
tanTilt: number;
|
|
61
|
+
}
|
|
62
|
+
export interface GameLogic {
|
|
63
|
+
readonly anomalies: Anomaly[];
|
|
64
|
+
readonly bullets: Bullet[];
|
|
65
|
+
readonly caughtEffects: CaughtEffect[];
|
|
66
|
+
gameActive: boolean;
|
|
67
|
+
gameMode: GameMode;
|
|
68
|
+
cannonX: number;
|
|
69
|
+
armT: number;
|
|
70
|
+
fontLoaded: boolean;
|
|
71
|
+
gameSim(t: number, dt: number): void;
|
|
72
|
+
pruneCaughtEffects(t: number): void;
|
|
73
|
+
adjustTimeMarkers(skip: number): void;
|
|
74
|
+
setGameActive(active: boolean): void;
|
|
75
|
+
catchAt(x: number, y: number, running: boolean): boolean;
|
|
76
|
+
setMode(mode: 'idle' | 'armed'): void;
|
|
77
|
+
startRound(): void;
|
|
78
|
+
exitGame(): void;
|
|
79
|
+
setCannonDir(dir: number): void;
|
|
80
|
+
setFiring(on: boolean): void;
|
|
81
|
+
onStats(cb: (s: GameStats) => void): void;
|
|
82
|
+
setExclusion(box: {
|
|
83
|
+
width: number;
|
|
84
|
+
height: number;
|
|
85
|
+
} | null): void;
|
|
86
|
+
}
|
|
87
|
+
export declare function createGameLogic(host: GameEngineHost): GameLogic;
|