arkaos 5.4.0 → 5.5.0
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/README.md +2 -2
- package/THE-ARKAOS-GUIDE.md +1 -1
- package/VERSION +1 -1
- package/arka/SKILL.md +1 -1
- package/config/skills-provenance.yaml +18 -0
- package/departments/dev/skills/canvas-generative/SKILL.md +362 -0
- package/departments/dev/skills/canvas-generative/references/algorithms.md +934 -0
- package/departments/dev/skills/canvas-generative/references/genjutsu.LICENSE +21 -0
- package/departments/dev/skills/css-native/SKILL.md +353 -0
- package/departments/dev/skills/css-native/references/genjutsu.LICENSE +21 -0
- package/departments/dev/skills/css-native/references/modern-css.md +465 -0
- package/departments/dev/skills/framer-motion/SKILL.md +223 -0
- package/departments/dev/skills/framer-motion/references/api.md +312 -0
- package/departments/dev/skills/framer-motion/references/genjutsu.LICENSE +21 -0
- package/harness/codex/AGENTS.md +1 -1
- package/harness/copilot/copilot-instructions.md +1 -1
- package/harness/cursor/rules/arkaos.mdc +2 -2
- package/harness/gemini/GEMINI.md +1 -1
- package/harness/opencode/AGENTS.md +1 -1
- package/harness/opencode/agents/arka-architect-gabriel.md +1 -1
- package/harness/opencode/agents/arka-brand-director-valentina.md +1 -1
- package/harness/opencode/agents/arka-cfo-helena.md +1 -1
- package/harness/opencode/agents/arka-chief-of-staff-afonso.md +1 -1
- package/harness/opencode/agents/arka-community-strategist-beatriz.md +1 -1
- package/harness/opencode/agents/arka-content-strategist-rafael.md +1 -1
- package/harness/opencode/agents/arka-conversion-strategist-ines.md +1 -1
- package/harness/opencode/agents/arka-coo-sofia.md +1 -1
- package/harness/opencode/agents/arka-copy-director-eduardo.md +1 -1
- package/harness/opencode/agents/arka-cqo-marta.md +1 -1
- package/harness/opencode/agents/arka-cto-marco.md +1 -1
- package/harness/opencode/agents/arka-design-ops-lead-iris.md +1 -1
- package/harness/opencode/agents/arka-ecom-director-ricardo.md +1 -1
- package/harness/opencode/agents/arka-knowledge-director-clara.md +1 -1
- package/harness/opencode/agents/arka-leadership-director-rodrigo.md +1 -1
- package/harness/opencode/agents/arka-marketing-director-luna.md +1 -1
- package/harness/opencode/agents/arka-ops-lead-daniel.md +1 -1
- package/harness/opencode/agents/arka-pm-director-carolina.md +1 -1
- package/harness/opencode/agents/arka-revops-lead-vicente.md +1 -1
- package/harness/opencode/agents/arka-saas-strategist-tiago.md +1 -1
- package/harness/opencode/agents/arka-sales-director-miguel.md +1 -1
- package/harness/opencode/agents/arka-strategy-director-tomas.md +1 -1
- package/harness/opencode/agents/arka-tech-director-francisca.md +1 -1
- package/harness/opencode/agents/arka-tech-lead-paulo.md +1 -1
- package/harness/opencode/agents/arka-video-producer-simao.md +1 -1
- package/harness/zed/.rules +1 -1
- package/knowledge/commands-registry.json +1 -1
- package/knowledge/skills-manifest.json +46 -1
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/scripts/marketplace_gen.py +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
**The Operating System for AI Agent Teams.**
|
|
6
6
|
|
|
7
|
-
89 agents. 17 departments.
|
|
7
|
+
89 agents. 17 departments. 337 skills. Enterprise frameworks. Multi-runtime. One install.
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
npx arkaos install
|
|
@@ -97,7 +97,7 @@ npx arkaos doctor # Health check
|
|
|
97
97
|
|
|
98
98
|
### Skill packs, à la carte
|
|
99
99
|
|
|
100
|
-
The default install ships a curated core so your context window stays lean. Everything else lives in the ArkaOS plugin marketplace: 16 department packs with
|
|
100
|
+
The default install ships a curated core so your context window stays lean. Everything else lives in the ArkaOS plugin marketplace: 16 department packs with 263 skills, generated straight from the same sources the core uses. Inside Claude Code:
|
|
101
101
|
|
|
102
102
|
```
|
|
103
103
|
/plugin marketplace add andreagroferreira/arka-os
|
package/THE-ARKAOS-GUIDE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# The ArkaOS Guide
|
|
2
2
|
|
|
3
|
-
> v5.
|
|
3
|
+
> v5.5.0 — 89 agents, 17 departments, 337 skills, 299 commands, 20 ADRs.
|
|
4
4
|
> One file, everything you need to start. Generated by `scripts/guide_gen.py` — never hand-edited.
|
|
5
5
|
|
|
6
6
|
## What it is
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
5.
|
|
1
|
+
5.5.0
|
package/arka/SKILL.md
CHANGED
|
@@ -63,7 +63,7 @@ complementary, not alternatives.
|
|
|
63
63
|
# ArkaOS — Main Orchestrator
|
|
64
64
|
|
|
65
65
|
> **The Operating System for AI Agent Teams**
|
|
66
|
-
> 89 agents. 17 departments.
|
|
66
|
+
> 89 agents. 17 departments. 337 skills. Multi-runtime. Dashboard. Knowledge RAG.
|
|
67
67
|
|
|
68
68
|
## ⛔ Evidence flow — 4 gates (NON-NEGOTIABLE)
|
|
69
69
|
|
|
@@ -121,6 +121,24 @@ derived:
|
|
|
121
121
|
origin: community
|
|
122
122
|
source: https://github.com/zanwei/design-dna
|
|
123
123
|
license: MIT
|
|
124
|
+
# Animation/design absorption campaign PR-3 — three skills cherry-picked
|
|
125
|
+
# from AThevon/genjutsu (MIT, 15 skills upstream). Bodies are upstream
|
|
126
|
+
# near-verbatim with ArkaOS frontmatter, agent attribution and Output;
|
|
127
|
+
# canvas-generative's handoff table rewritten to in-repo destinations.
|
|
128
|
+
# The 12 skills NOT taken are recorded with reasons in
|
|
129
|
+
# docs/THIRD-PARTY-NOTICES.md.
|
|
130
|
+
departments/dev/skills/canvas-generative:
|
|
131
|
+
origin: community
|
|
132
|
+
source: https://github.com/AThevon/genjutsu
|
|
133
|
+
license: MIT
|
|
134
|
+
departments/dev/skills/framer-motion:
|
|
135
|
+
origin: community
|
|
136
|
+
source: https://github.com/AThevon/genjutsu
|
|
137
|
+
license: MIT
|
|
138
|
+
departments/dev/skills/css-native:
|
|
139
|
+
origin: community
|
|
140
|
+
source: https://github.com/AThevon/genjutsu
|
|
141
|
+
license: MIT
|
|
124
142
|
# Marketing skills integration campaign — derived from
|
|
125
143
|
# coreyhaines31/marketingskills (MIT). Frontmatter metadata must match
|
|
126
144
|
# each entry field-for-field (test_registry_matches_frontmatter_field_for_field).
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dev/canvas-generative
|
|
3
|
+
description: >
|
|
4
|
+
Algorithmic and generative art with Canvas 2D: DPR-aware setup, particle
|
|
5
|
+
systems with pooled allocation, noise fields, flow fields, fractals and
|
|
6
|
+
L-systems, double buffering — with reference implementations for the
|
|
7
|
+
core algorithms.
|
|
8
|
+
TRIGGER: "generative art", "arte generativa", "particles background",
|
|
9
|
+
"fundo de partículas", "noise field", "flow field", "canvas animation",
|
|
10
|
+
"fundo processual", "creative coding em canvas", "/dev canvas-generative".
|
|
11
|
+
SKIP: real-time 3D or shader work -> no dedicated skill yet, use the
|
|
12
|
+
frontend workflows; a pre-rendered 3D world scrubbed by scroll ->
|
|
13
|
+
dev/scroll-world; turning an existing video into a scroll site ->
|
|
14
|
+
dev/animated-website; charts and data graphics -> the dataviz skill.
|
|
15
|
+
allowed-tools: [Read, Write, Edit, Bash, Grep, Glob]
|
|
16
|
+
metadata:
|
|
17
|
+
origin: community
|
|
18
|
+
source: https://github.com/AThevon/genjutsu
|
|
19
|
+
license: MIT
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
<!-- arka:kb-first-prefix begin -->
|
|
23
|
+
> **KB-first:** query `mcp__obsidian__search_notes` (and
|
|
24
|
+
> `mcp__graphify__query_graph` when configured) and cite `[[wikilinks]]`
|
|
25
|
+
> or graph nodes — or declare the gap — BEFORE any external research.
|
|
26
|
+
> Full doctrine: `arka/SKILL.md` (KB-First Research).
|
|
27
|
+
<!-- arka:kb-first-prefix end -->
|
|
28
|
+
|
|
29
|
+
# Canvas Generative — `/dev canvas-generative`
|
|
30
|
+
|
|
31
|
+
> **Agent:** Diana (Frontend Dev) | **Framework:** Canvas 2D generative patterns (genjutsu)
|
|
32
|
+
|
|
33
|
+
> Algorithmic and generative art with Canvas 2D.
|
|
34
|
+
> Concise rules here. Deep-dive and reference implementations in `references/`.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Canvas 2D Setup
|
|
39
|
+
|
|
40
|
+
### DPR-Aware Sizing
|
|
41
|
+
|
|
42
|
+
Every canvas must be sharp on Retina/HiDPI displays. Set the buffer size to the physical pixel size, scale down with CSS.
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
function setupCanvas(canvas, width, height) {
|
|
46
|
+
const dpr = window.devicePixelRatio || 1;
|
|
47
|
+
canvas.width = width * dpr;
|
|
48
|
+
canvas.height = height * dpr;
|
|
49
|
+
canvas.style.width = `${width}px`;
|
|
50
|
+
canvas.style.height = `${height}px`;
|
|
51
|
+
const ctx = canvas.getContext('2d');
|
|
52
|
+
ctx.scale(dpr, dpr);
|
|
53
|
+
return ctx;
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Resize Handler
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
function handleResize(canvas, ctx, draw) {
|
|
61
|
+
const ro = new ResizeObserver(([entry]) => {
|
|
62
|
+
const { width, height } = entry.contentRect;
|
|
63
|
+
const dpr = window.devicePixelRatio || 1;
|
|
64
|
+
canvas.width = width * dpr;
|
|
65
|
+
canvas.height = height * dpr;
|
|
66
|
+
// setupCanvas pinned the CSS box inline; inline styles beat
|
|
67
|
+
// stylesheet rules, so skip this pair and the canvas stretches
|
|
68
|
+
// and blurs after any viewport change.
|
|
69
|
+
canvas.style.width = `${width}px`;
|
|
70
|
+
canvas.style.height = `${height}px`;
|
|
71
|
+
ctx.scale(dpr, dpr); // setting width reset the transform; rescale
|
|
72
|
+
draw(); // re-render after resize
|
|
73
|
+
});
|
|
74
|
+
ro.observe(canvas.parentElement);
|
|
75
|
+
return () => ro.disconnect();
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Animation Loop (RAF)
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
let animId;
|
|
83
|
+
let prevTime = 0;
|
|
84
|
+
|
|
85
|
+
function loop(time) {
|
|
86
|
+
const dt = Math.min((time - prevTime) / 1000, 0.1); // cap delta to avoid spiral of death
|
|
87
|
+
prevTime = time;
|
|
88
|
+
|
|
89
|
+
update(dt);
|
|
90
|
+
render(ctx);
|
|
91
|
+
|
|
92
|
+
animId = requestAnimationFrame(loop);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Start
|
|
96
|
+
animId = requestAnimationFrame(loop);
|
|
97
|
+
// Stop
|
|
98
|
+
cancelAnimationFrame(animId);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Noise
|
|
104
|
+
|
|
105
|
+
| Type | Characteristics | Best For |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| Perlin | Smooth, grid-aligned bias, cheaper | Terrain, clouds, gentle organic textures |
|
|
108
|
+
| Simplex | No grid artifacts, better gradients, slightly costlier | Flow fields, organic motion, seamless tiling |
|
|
109
|
+
| Worley (Cellular) | Distance-to-nearest-point, cell-like | Voronoi patterns, caustics, cracks, cell textures |
|
|
110
|
+
|
|
111
|
+
**Usage rules:**
|
|
112
|
+
- Always scale input coordinates (divide by a `noiseScale` factor) -- raw pixel coords produce visual noise
|
|
113
|
+
- Use octaves (fractal Brownian motion) for detail: sum multiple noise calls at increasing frequency and decreasing amplitude
|
|
114
|
+
- Seed your noise for reproducibility
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
// fBm pattern
|
|
118
|
+
function fbm(x, y, octaves = 4, lacunarity = 2, gain = 0.5) {
|
|
119
|
+
let value = 0, amplitude = 1, frequency = 1, maxAmp = 0;
|
|
120
|
+
for (let i = 0; i < octaves; i++) {
|
|
121
|
+
value += amplitude * noise2D(x * frequency, y * frequency);
|
|
122
|
+
maxAmp += amplitude;
|
|
123
|
+
amplitude *= gain;
|
|
124
|
+
frequency *= lacunarity;
|
|
125
|
+
}
|
|
126
|
+
return value / maxAmp; // normalize to [-1, 1]
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Particle Systems
|
|
133
|
+
|
|
134
|
+
### Pool Pattern (No GC Pressure)
|
|
135
|
+
|
|
136
|
+
Pre-allocate a fixed array. Never `new` or `splice` at runtime.
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
const POOL_SIZE = 10000;
|
|
140
|
+
const particles = new Array(POOL_SIZE);
|
|
141
|
+
let aliveCount = 0;
|
|
142
|
+
|
|
143
|
+
// Init pool
|
|
144
|
+
for (let i = 0; i < POOL_SIZE; i++) {
|
|
145
|
+
particles[i] = { x: 0, y: 0, vx: 0, vy: 0, life: 0, maxLife: 0, active: false };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function spawn(x, y) {
|
|
149
|
+
if (aliveCount >= POOL_SIZE) return;
|
|
150
|
+
const p = particles[aliveCount++];
|
|
151
|
+
p.x = x; p.y = y;
|
|
152
|
+
p.vx = (Math.random() - 0.5) * 2;
|
|
153
|
+
p.vy = (Math.random() - 0.5) * 2;
|
|
154
|
+
p.life = 0; p.maxLife = 60 + Math.random() * 60;
|
|
155
|
+
p.active = true;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function update() {
|
|
159
|
+
for (let i = aliveCount - 1; i >= 0; i--) {
|
|
160
|
+
const p = particles[i];
|
|
161
|
+
p.x += p.vx; p.y += p.vy;
|
|
162
|
+
p.life++;
|
|
163
|
+
if (p.life >= p.maxLife) {
|
|
164
|
+
// Swap with last alive, shrink pool
|
|
165
|
+
particles[i] = particles[--aliveCount];
|
|
166
|
+
particles[aliveCount] = p;
|
|
167
|
+
p.active = false;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Flow Fields
|
|
176
|
+
|
|
177
|
+
Grid of angle vectors that steer particles. The classic generative recipe.
|
|
178
|
+
|
|
179
|
+
1. **Build grid:** Divide canvas into cells, compute an angle per cell (from noise)
|
|
180
|
+
2. **Lookup:** Particle position maps to grid cell, retrieve angle
|
|
181
|
+
3. **Steer:** Apply angle as velocity, accumulate over frames
|
|
182
|
+
|
|
183
|
+
```js
|
|
184
|
+
const cols = Math.ceil(width / cellSize);
|
|
185
|
+
const rows = Math.ceil(height / cellSize);
|
|
186
|
+
const field = new Float32Array(cols * rows);
|
|
187
|
+
|
|
188
|
+
// Fill with noise-based angles
|
|
189
|
+
for (let y = 0; y < rows; y++) {
|
|
190
|
+
for (let x = 0; x < cols; x++) {
|
|
191
|
+
field[y * cols + x] = noise2D(x * 0.05, y * 0.05) * Math.PI * 2;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Particle follow
|
|
196
|
+
function followField(p) {
|
|
197
|
+
const col = Math.floor(p.x / cellSize);
|
|
198
|
+
const row = Math.floor(p.y / cellSize);
|
|
199
|
+
if (col >= 0 && col < cols && row >= 0 && row < rows) {
|
|
200
|
+
const angle = field[row * cols + col];
|
|
201
|
+
p.vx += Math.cos(angle) * force;
|
|
202
|
+
p.vy += Math.sin(angle) * force;
|
|
203
|
+
}
|
|
204
|
+
// Damping to prevent runaway velocity
|
|
205
|
+
p.vx *= 0.98;
|
|
206
|
+
p.vy *= 0.98;
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Fractals & L-Systems
|
|
213
|
+
|
|
214
|
+
An L-system encodes recursive structure as string rewriting + turtle graphics.
|
|
215
|
+
|
|
216
|
+
| Component | Role |
|
|
217
|
+
|---|---|
|
|
218
|
+
| Axiom | Starting string (e.g. `"F"`) |
|
|
219
|
+
| Rules | Production rules (e.g. `"F" -> "F[+F]F[-F]F"`) |
|
|
220
|
+
| Angle | Turtle turn angle per `+`/`-` |
|
|
221
|
+
| Iterations | How many times to apply rules |
|
|
222
|
+
|
|
223
|
+
```js
|
|
224
|
+
function lsystem(axiom, rules, iterations) {
|
|
225
|
+
let current = axiom;
|
|
226
|
+
for (let i = 0; i < iterations; i++) {
|
|
227
|
+
current = current.split('').map(c => rules[c] || c).join('');
|
|
228
|
+
}
|
|
229
|
+
return current;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function drawLSystem(ctx, commands, len, angle) {
|
|
233
|
+
const stack = [];
|
|
234
|
+
for (const c of commands) {
|
|
235
|
+
switch (c) {
|
|
236
|
+
case 'F': ctx.lineTo(ctx._x += Math.cos(ctx._a) * len, ctx._y += Math.sin(ctx._a) * len); break;
|
|
237
|
+
case '+': ctx._a += angle; break;
|
|
238
|
+
case '-': ctx._a -= angle; break;
|
|
239
|
+
case '[': stack.push({ x: ctx._x, y: ctx._y, a: ctx._a }); break;
|
|
240
|
+
case ']': { const s = stack.pop(); ctx._x = s.x; ctx._y = s.y; ctx._a = s.a; ctx.moveTo(s.x, s.y); } break;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Double Buffer Pattern
|
|
249
|
+
|
|
250
|
+
Render to an offscreen canvas, then blit to the visible one. Eliminates flicker and enables trail effects.
|
|
251
|
+
|
|
252
|
+
```js
|
|
253
|
+
const offscreen = document.createElement('canvas');
|
|
254
|
+
offscreen.width = canvas.width;
|
|
255
|
+
offscreen.height = canvas.height;
|
|
256
|
+
const offCtx = offscreen.getContext('2d');
|
|
257
|
+
|
|
258
|
+
function render() {
|
|
259
|
+
// Draw to offscreen
|
|
260
|
+
offCtx.fillStyle = 'rgba(0, 0, 0, 0.05)'; // trail fade
|
|
261
|
+
offCtx.fillRect(0, 0, offscreen.width, offscreen.height);
|
|
262
|
+
drawParticles(offCtx);
|
|
263
|
+
|
|
264
|
+
// Blit to screen
|
|
265
|
+
ctx.drawImage(offscreen, 0, 0);
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Do Not
|
|
272
|
+
|
|
273
|
+
### 1. Never clearRect every frame for trail effects
|
|
274
|
+
|
|
275
|
+
Clearing destroys the trail. Use a semi-transparent fill instead.
|
|
276
|
+
|
|
277
|
+
```js
|
|
278
|
+
// BAD -- kills trails
|
|
279
|
+
ctx.clearRect(0, 0, w, h);
|
|
280
|
+
|
|
281
|
+
// GOOD -- fades previous frame
|
|
282
|
+
ctx.fillStyle = 'rgba(0, 0, 0, 0.02)';
|
|
283
|
+
ctx.fillRect(0, 0, w, h);
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### 2. Never getImageData in the animation loop
|
|
287
|
+
|
|
288
|
+
`getImageData` reads back from GPU -- extremely slow. Avoid unless absolutely required (e.g. one-time color sampling).
|
|
289
|
+
|
|
290
|
+
```js
|
|
291
|
+
// BAD -- 60fps GPU readback
|
|
292
|
+
function loop() {
|
|
293
|
+
const data = ctx.getImageData(0, 0, w, h); // blocks rendering pipeline
|
|
294
|
+
processPixels(data);
|
|
295
|
+
requestAnimationFrame(loop);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// GOOD -- sample once, cache
|
|
299
|
+
const colorMap = ctx.getImageData(0, 0, w, h);
|
|
300
|
+
function getColor(x, y) {
|
|
301
|
+
const i = (y * w + x) * 4;
|
|
302
|
+
return [colorMap.data[i], colorMap.data[i+1], colorMap.data[i+2]];
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### 3. Always respect DPR for sharpness
|
|
307
|
+
|
|
308
|
+
A canvas without DPR scaling looks blurry on Retina displays. See setup section above.
|
|
309
|
+
|
|
310
|
+
```js
|
|
311
|
+
// BAD
|
|
312
|
+
canvas.width = 800;
|
|
313
|
+
canvas.height = 600;
|
|
314
|
+
|
|
315
|
+
// GOOD
|
|
316
|
+
const dpr = window.devicePixelRatio || 1;
|
|
317
|
+
canvas.width = 800 * dpr;
|
|
318
|
+
canvas.height = 600 * dpr;
|
|
319
|
+
canvas.style.width = '800px';
|
|
320
|
+
canvas.style.height = '600px';
|
|
321
|
+
ctx.scale(dpr, dpr);
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### 4. Never allocate in the hot loop
|
|
325
|
+
|
|
326
|
+
No `new`, no object spread, no array creation inside `update()` or `render()`. Pre-allocate everything.
|
|
327
|
+
|
|
328
|
+
```js
|
|
329
|
+
// BAD
|
|
330
|
+
function update() {
|
|
331
|
+
particles.forEach(p => {
|
|
332
|
+
const force = { x: Math.cos(a), y: Math.sin(a) }; // new object every frame per particle
|
|
333
|
+
p.vx += force.x;
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// GOOD
|
|
338
|
+
let fx = 0, fy = 0; // reuse
|
|
339
|
+
function update() {
|
|
340
|
+
for (let i = 0; i < aliveCount; i++) {
|
|
341
|
+
fx = Math.cos(a); fy = Math.sin(a);
|
|
342
|
+
particles[i].vx += fx;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## Quick Reference: Loading Sub-skills
|
|
350
|
+
|
|
351
|
+
| Need | Load |
|
|
352
|
+
|---|---|
|
|
353
|
+
| Noise implementations, particle pool, flow field, L-system, attractors | `references/algorithms.md` |
|
|
354
|
+
| Timing and easing for animated transitions | the brand guidelines' Motion System (§06), reached via the source-of-truth table in `departments/brand/references/uiux-knowledge-and-tools.md` |
|
|
355
|
+
| 3D generative (shaders, GPU particles) | out of this skill's scope — Canvas 2D only; scope a WebGL approach with the frontend squad |
|
|
356
|
+
|
|
357
|
+
## Output
|
|
358
|
+
|
|
359
|
+
A self-contained canvas module — DPR-aware setup, pooled particles or the
|
|
360
|
+
chosen algorithm, RAF loop with cleanup — dropped into the project's
|
|
361
|
+
component conventions, plus a one-line note of the algorithm and budget
|
|
362
|
+
chosen. Deep implementations stay in `references/algorithms.md`.
|