@audiofool/moondog 0.2.0-beta.3 → 0.2.0-beta.4
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 +1 -1
- package/package.json +1 -1
- package/src/surfaces/cli/terminal-art.mjs +38 -16
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -198,8 +198,26 @@ export function lunarRecordShapes() {
|
|
|
198
198
|
return structuredClone({ dog, eye, ...shapes, earRadius: 0.17, grooves: [1, 0.91, 0.8, 0.66] });
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
+
// The tonearm swings about its pivot, the arm's first point; a negative swing turns it off the record.
|
|
202
|
+
// Only an arm at rest on the record touches a groove, where its contact pulses as the record turns.
|
|
203
|
+
function paintTonearm({ pixel, disc, line, polygon }, rotation, swing = 0) {
|
|
204
|
+
const [pivotX, pivotY] = shapes.arm[0];
|
|
205
|
+
const [cosine, sine] = [Math.cos(swing), Math.sin(swing)];
|
|
206
|
+
const swung = ([x, y]) => [pivotX + (x - pivotX) * cosine - (y - pivotY) * sine, pivotY + (x - pivotX) * sine + (y - pivotY) * cosine];
|
|
207
|
+
const cartridge = shapes.cartridge.map(swung);
|
|
208
|
+
line(shapes.arm.map(swung), Math.max(pixel * 1.8, 0.03));
|
|
209
|
+
polygon(cartridge, true);
|
|
210
|
+
line([...cartridge, cartridge[0]], pixel);
|
|
211
|
+
disc(...swung([0.914, -0.764]), Math.max(pixel * 0.7, 0.021), false);
|
|
212
|
+
line([[0.775, -0.615], [0.735, -0.559]].map(swung), pixel * 1.3);
|
|
213
|
+
if (swing) return;
|
|
214
|
+
const pulse = Math.sin(rotation * 4);
|
|
215
|
+
const angle = -0.612 + pulse * pixel * 0.85;
|
|
216
|
+
disc(Math.cos(angle) * 0.928, Math.sin(angle) * 0.928, pixel * (0.95 + pulse * 0.15));
|
|
217
|
+
}
|
|
218
|
+
|
|
201
219
|
// The record as a field of dots, two across and four down per terminal cell, each marked with its layer.
|
|
202
|
-
function paint(columns, rows, phase, cellAspect) {
|
|
220
|
+
function paint(columns, rows, phase, cellAspect, tonearm = true) {
|
|
203
221
|
const art = drawing(columns, rows, cellAspect);
|
|
204
222
|
const { radius, pixel, circle, disc, line, polygon, paintLayer } = art;
|
|
205
223
|
const detail = radius >= 39 ? 2 : radius >= 27 ? 1 : 0;
|
|
@@ -243,7 +261,7 @@ function paint(columns, rows, phase, cellAspect) {
|
|
|
243
261
|
|
|
244
262
|
paintLayer(RECORD_LAYERS.figure);
|
|
245
263
|
// Like the logo, a clear halo separates the dog from the grooves around it.
|
|
246
|
-
const { headband, ear, nose
|
|
264
|
+
const { headband, ear, nose } = shapes;
|
|
247
265
|
line([...dog, dog[0]], pixel * 4.5, false);
|
|
248
266
|
line(headband, Math.max(pixel * 7, 0.11), false);
|
|
249
267
|
polygon(dog, false);
|
|
@@ -263,16 +281,7 @@ function paint(columns, rows, phase, cellAspect) {
|
|
|
263
281
|
disc(eye[0], eye[1], pixel * 1.05, false);
|
|
264
282
|
disc(nose[0], nose[1], pixel * 0.85);
|
|
265
283
|
|
|
266
|
-
|
|
267
|
-
polygon(cartridge, true);
|
|
268
|
-
line([...cartridge, cartridge[0]], pixel);
|
|
269
|
-
disc(0.914, -0.764, Math.max(pixel * 0.7, 0.021), false);
|
|
270
|
-
line([[0.775, -0.615], [0.735, -0.559]], pixel * 1.3);
|
|
271
|
-
const pulse = Math.sin(rotation * 4);
|
|
272
|
-
const angle = -0.612 + pulse * pixel * 0.85;
|
|
273
|
-
const contact = [Math.cos(angle) * 0.928, Math.sin(angle) * 0.928];
|
|
274
|
-
disc(contact[0], contact[1], pixel * (0.95 + pulse * 0.15));
|
|
275
|
-
|
|
284
|
+
if (tonearm) paintTonearm(art, rotation);
|
|
276
285
|
return art;
|
|
277
286
|
}
|
|
278
287
|
|
|
@@ -372,12 +381,25 @@ export function renderLunarRecordLayers({ columns = 56, rows = 24, style = "brai
|
|
|
372
381
|
/**
|
|
373
382
|
* The same record as dots rather than Braille characters, for surfaces that draw their own dots,
|
|
374
383
|
* such as the desktop window's canvas. Dots sit on a square grid of width x height, row by row;
|
|
375
|
-
* each holds 0 or the RECORD_LAYERS value that inked it.
|
|
384
|
+
* each holds 0 or the RECORD_LAYERS value that inked it. With tonearm: false the arm is left out, for
|
|
385
|
+
* a surface that draws it apart with renderTonearmDots so it can lift. centerX, centerY and radius
|
|
386
|
+
* place the record's unit coordinates on the grid, in dots.
|
|
376
387
|
*/
|
|
377
|
-
export function renderLunarRecordDots({ columns = 56, rows = 28, phase = 0 } = {}) {
|
|
388
|
+
export function renderLunarRecordDots({ columns = 56, rows = 28, phase = 0, tonearm = true } = {}) {
|
|
378
389
|
const frame = Number.isFinite(phase) ? ((Math.floor(phase) % LOGO_MOTION_FRAMES) + LOGO_MOTION_FRAMES) % LOGO_MOTION_FRAMES : 0;
|
|
379
|
-
const { dots, width, height } = paint(Math.max(10, Math.floor(columns)), Math.max(5, Math.floor(rows)), frame, 2);
|
|
380
|
-
return { dots, width, height };
|
|
390
|
+
const { dots, width, height, centerX, centerY, radius } = paint(Math.max(10, Math.floor(columns)), Math.max(5, Math.floor(rows)), frame, 2, tonearm);
|
|
391
|
+
return { dots, width, height, centerX, centerY, radius };
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* The tonearm alone, on the same grid as renderLunarRecordDots, swung `swing` radians about its pivot
|
|
396
|
+
* (negative lifts it off the record). At rest on the record its contact follows the record's phase.
|
|
397
|
+
*/
|
|
398
|
+
export function renderTonearmDots({ columns = 56, rows = 28, phase = 0, swing = 0 } = {}) {
|
|
399
|
+
const art = drawing(Math.max(10, Math.floor(columns)), Math.max(5, Math.floor(rows)), 2);
|
|
400
|
+
art.paintLayer(RECORD_LAYERS.figure);
|
|
401
|
+
paintTonearm(art, (Number.isFinite(phase) ? phase : 0) / LOGO_MOTION_FRAMES * turn, Number.isFinite(swing) ? swing : 0);
|
|
402
|
+
return { dots: art.dots, width: art.width, height: art.height };
|
|
381
403
|
}
|
|
382
404
|
|
|
383
405
|
/** Five-pixel letterforms, packed into three terminal rows without color or escapes. */
|