wobnimo 0.1.4 → 0.2.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/AGENTS.md +18 -4
- package/README.md +38 -7
- package/dist/characters/bao.d.ts +6 -0
- package/dist/characters/bao.js +1 -0
- package/dist/characters/berry.d.ts +6 -0
- package/dist/characters/berry.js +1 -0
- package/dist/characters/boo.js +1 -1
- package/dist/characters/bumble.d.ts +6 -0
- package/dist/characters/bumble.js +1 -0
- package/dist/characters/cacti.d.ts +6 -0
- package/dist/characters/cacti.js +1 -0
- package/dist/characters/cap.d.ts +6 -0
- package/dist/characters/cap.js +1 -0
- package/dist/characters/drift.d.ts +6 -0
- package/dist/characters/drift.js +1 -0
- package/dist/characters/ember.d.ts +6 -0
- package/dist/characters/ember.js +1 -0
- package/dist/characters/hop.d.ts +6 -0
- package/dist/characters/hop.js +1 -0
- package/dist/characters/index.d.ts +11 -1
- package/dist/characters/index.js +11 -11
- package/dist/characters/inky.js +1 -1
- package/dist/characters/latte.d.ts +6 -0
- package/dist/characters/latte.js +1 -0
- package/dist/characters/microduck.js +1 -1
- package/dist/characters/miso.js +1 -1
- package/dist/characters/mochi.js +1 -1
- package/dist/characters/pebble.js +1 -1
- package/dist/characters/pip.js +1 -1
- package/dist/characters/rex.js +1 -1
- package/dist/characters/swirl.d.ts +6 -0
- package/dist/characters/swirl.js +1 -0
- package/dist/characters/tad.js +1 -1
- package/dist/characters/volt.js +1 -1
- package/dist/cli.js +1888 -0
- package/dist/element.d.ts +1 -1
- package/dist/element.js +9 -9
- package/dist/index-Cm5wWKoT.d.ts +12 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +6 -6
- package/dist/react.js +16 -16
- package/dist/wobnimo.js +12 -12
- package/package.json +14 -4
- package/skill/SKILL.md +719 -0
- package/skill/examples/bao.ts +73 -0
- package/skill/examples/berry.ts +97 -0
- package/skill/examples/boo.ts +87 -0
- package/skill/examples/bumble.ts +70 -0
- package/skill/examples/cacti.ts +79 -0
- package/skill/examples/cap.ts +59 -0
- package/skill/examples/drift.ts +74 -0
- package/skill/examples/ember.ts +78 -0
- package/skill/examples/hop.ts +66 -0
- package/skill/examples/inky.ts +168 -0
- package/skill/examples/latte.ts +73 -0
- package/skill/examples/microduck.ts +222 -0
- package/skill/examples/miso.ts +182 -0
- package/skill/examples/mochi.ts +78 -0
- package/skill/examples/pebble.ts +174 -0
- package/skill/examples/pip.ts +170 -0
- package/skill/examples/rex.ts +193 -0
- package/skill/examples/swirl.ts +69 -0
- package/skill/examples/tad.ts +117 -0
- package/skill/examples/volt.ts +214 -0
- package/skill/reference/recipes.md +551 -0
- package/skill/reference/spec.md +258 -0
- package/skill/templates/starter.ts +73 -0
- package/dist/index-DRDEWSGV.d.ts +0 -8
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { CharacterSpec } from 'wobnimo';
|
|
2
|
+
|
|
3
|
+
/** A white bunny with long floppy ears. */
|
|
4
|
+
export const hop: CharacterSpec = {
|
|
5
|
+
id: 'hop',
|
|
6
|
+
name: 'Hop',
|
|
7
|
+
tagline: 'A soft white bunny whose long floppy ears swing with every hop',
|
|
8
|
+
accent: '#ff8fb1',
|
|
9
|
+
frame: { target: 0.57, radius: 0.76 },
|
|
10
|
+
bound: { y: 0.56, radius: 0.66 },
|
|
11
|
+
motion: { hop: 0.22, squash: 1.3, snap: 1.15, talkSquash: 0.4 },
|
|
12
|
+
materials: {
|
|
13
|
+
fur: { color: '#fbf8f4', f0: 0.03, spec: 0.4, shininess: 20, rim: 1, sheen: 0.7, surface: { kind: 'fur', scale: 110, strength: 0.3, bone: 'head' } },
|
|
14
|
+
bodyFur: { color: '#fbf8f4', shadeOf: 'fur', f0: 0.03, spec: 0.4, shininess: 20, rim: 1, sheen: 0.7, surface: { kind: 'fur', scale: 110, strength: 0.3 } },
|
|
15
|
+
earFur: { color: '#fbf8f4', shadeOf: 'fur', f0: 0.03, spec: 0.4, shininess: 20, rim: 1.2, sheen: 0.7, sss: 0.35, sssColor: '#ffc4d4' },
|
|
16
|
+
nose: { color: '#ff7fa5', f0: 0.06, spec: 1.6, shininess: 160, rim: 0.3, gloss: 0.8 },
|
|
17
|
+
},
|
|
18
|
+
bones: [
|
|
19
|
+
{ name: 'body', pivot: [0, 0, 0], drive: { ry: [['yaw', 0.2]], rz: [['roll', 0.35]] } },
|
|
20
|
+
{ name: 'head', parent: 'body', pivot: [0, 0.42, 0.02], drive: { rx: [['pitch', -1]], ry: [['yaw', 0.8]], rz: [['roll', 0.7]] } },
|
|
21
|
+
/* long ears that flop down and swing */
|
|
22
|
+
{ name: 'earL', parent: 'head', pivot: [-0.1, 0.3, -0.02], rest: { rz: 0.35, rx: 0.2 }, jiggle: { axis: [0, 1, 0], length: 0.32, freq: 2, damping: 0.14, maxAngle: 0.8 } },
|
|
23
|
+
{ name: 'earR', parent: 'head', pivot: [0.1, 0.3, -0.02], rest: { rz: -1.2, rx: 0.2 }, jiggle: { axis: [0, 1, 0], length: 0.32, freq: 2, damping: 0.14, maxAngle: 0.8 } },
|
|
24
|
+
{ name: 'tail', parent: 'body', pivot: [0, 0.14, -0.2], jiggle: { axis: [0, 0, -1], length: 0.06, freq: 4, damping: 0.2 } },
|
|
25
|
+
],
|
|
26
|
+
parts: [
|
|
27
|
+
{ bone: 'body', shape: 'ellipsoid', at: [0, 0.22, 0], radii: [0.22, 0.22, 0.21], material: 'bodyFur' },
|
|
28
|
+
{ bone: 'body', shape: 'ellipsoid', at: [-0.12, 0.05, 0.1], radii: [0.08, 0.05, 0.13], blend: 0.04, material: 'bodyFur' },
|
|
29
|
+
{ bone: 'body', shape: 'ellipsoid', at: [0.12, 0.05, 0.1], radii: [0.08, 0.05, 0.13], blend: 0.04, material: 'bodyFur' },
|
|
30
|
+
{ bone: 'tail', shape: 'sphere', at: [0, 0, -0.03], radius: 0.07, blend: 0.03, material: 'bodyFur' },
|
|
31
|
+
{ bone: 'head', shape: 'ellipsoid', at: [0, 0.14, 0], radii: [0.25, 0.22, 0.22], blend: 0.1, material: 'fur' },
|
|
32
|
+
{ bone: 'head', shape: 'ellipsoid', at: [-0.06, 0.06, 0.17], radii: [0.07, 0.055, 0.06], blend: 0.04, material: 'fur' },
|
|
33
|
+
{ bone: 'head', shape: 'ellipsoid', at: [0.06, 0.06, 0.17], radii: [0.07, 0.055, 0.06], blend: 0.04, material: 'fur' },
|
|
34
|
+
{ bone: 'head', shape: 'ellipsoid', at: [0, 0.1, 0.22], radii: [0.028, 0.02, 0.018], material: 'nose' },
|
|
35
|
+
{ bone: 'earL', shape: 'ellipsoid', at: [0, 0.2, 0], radii: [0.065, 0.22, 0.03], material: 'earFur' },
|
|
36
|
+
{ bone: 'earR', shape: 'ellipsoid', at: [0, 0.2, 0], radii: [0.065, 0.22, 0.03], material: 'earFur' },
|
|
37
|
+
],
|
|
38
|
+
paints: [
|
|
39
|
+
{ bone: 'earL', on: ['earFur'], kind: 'ellipse', at: [0, 0.2, 0.03], radii: [0.035, 0.16], color: '#ffc2d3', soft: 0.4 },
|
|
40
|
+
{ bone: 'earR', on: ['earFur'], kind: 'ellipse', at: [0, 0.2, 0.03], radii: [0.035, 0.16], color: '#ffc2d3', soft: 0.4 },
|
|
41
|
+
{ bone: 'head', on: ['fur'], kind: 'sphere', at: [-0.16, 0.07, 0.16], radius: 0.045, color: '#ffb3c8', soft: 0.6, opacity: 0.8 },
|
|
42
|
+
{ bone: 'head', on: ['fur'], kind: 'sphere', at: [0.16, 0.07, 0.16], radius: 0.045, color: '#ffb3c8', soft: 0.6, opacity: 0.8 },
|
|
43
|
+
],
|
|
44
|
+
eyes: { kind: 'ball', bone: 'head', at: [[-0.1, 0.17, 0.17], [0.1, 0.17, 0.17]], radius: 0.05, iris: '#3b1f2b', irisSize: 0.85, pupilSize: 0.55, lid: 'fur' },
|
|
45
|
+
face: { kind: 'mouth', bone: 'head', on: ['fur'], at: [0, 0.035, 0.21], width: 0.035, color: '#5a2a3a', tongue: '#ff8fa3' },
|
|
46
|
+
anchors: {
|
|
47
|
+
top: { bone: 'head', at: [0.15, 0.5, 0.05] },
|
|
48
|
+
mouth: { bone: 'head', at: [0, 0.035, 0.24] },
|
|
49
|
+
ear: { bone: 'earL', at: [0, 0.2, 0] },
|
|
50
|
+
feet: { bone: 'root', at: [0, 0.02, 0.15] },
|
|
51
|
+
},
|
|
52
|
+
acting: {
|
|
53
|
+
thinking: { earR: { rz: -0.4 }, head: { rz: 0.1 } },
|
|
54
|
+
listening: { earL: { rz: 0, rx: -0.2 }, earR: { rz: 0, rx: -0.2 } },
|
|
55
|
+
sleeping: { earL: { rz: 1.2, rx: 0.5 }, earR: { rz: -1.4, rx: 0.5 } },
|
|
56
|
+
error: { earL: { rz: [0.6, 0.2, 9, 0] }, earR: { rz: [-0.6, 0.2, 9, 1] } },
|
|
57
|
+
surprised: { earL: { rz: 0.05, rx: -0.1 }, earR: { rz: -0.05, rx: -0.1 } },
|
|
58
|
+
celebrating: { earL: { rz: [0.2, 0.3, 4, 0] }, earR: { rz: [-0.2, 0.3, 4, Math.PI] } },
|
|
59
|
+
sad: { earL: { rz: 1.4, rx: 0.6 }, earR: { rz: -1.4, rx: 0.6 } },
|
|
60
|
+
},
|
|
61
|
+
fx: {
|
|
62
|
+
happy: [{ glyph: 'heart', anchor: 'top', rate: 1.2, velocity: [0, 0.22, 0.04], jitter: 0.1, life: [1, 1.3], size: [0.04, 0.06], color: '#ff8fb1' }],
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export default hop;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import type { BoneSpec, CharacterSpec, Expression, Motion, PartSpec } from 'wobnimo';
|
|
2
|
+
|
|
3
|
+
/* Six tentacles, each a chain of three jiggle bones: every segment lags
|
|
4
|
+
behind the one before it, so they trail and curl with no animation of
|
|
5
|
+
their own beyond a slow wave. Generated here, but the result is plain
|
|
6
|
+
data like any other spec. */
|
|
7
|
+
const TENTACLES = 6;
|
|
8
|
+
const SEGMENT = 0.17;
|
|
9
|
+
const RADII = [0.085, 0.064, 0.044, 0.016];
|
|
10
|
+
const CURL = [-0.6, -0.42, -0.62];
|
|
11
|
+
|
|
12
|
+
type Acting = Partial<Record<Expression, Record<string, { rx?: Motion; rz?: Motion }>>>;
|
|
13
|
+
|
|
14
|
+
/* How the tentacles act. Each state sets every segment's curl; a couple of
|
|
15
|
+
tentacles get their own business (one to the chin, one to the ear). */
|
|
16
|
+
function tentacleActing(): Acting {
|
|
17
|
+
const acting: Required<Acting> = {
|
|
18
|
+
idle: {}, thinking: {}, listening: {}, speaking: {}, sleeping: {}, working: {}, error: {}, surprised: {}, celebrating: {}, sad: {}, happy: {},
|
|
19
|
+
};
|
|
20
|
+
for (let i = 0; i < TENTACLES; i++) {
|
|
21
|
+
const phase = i * 1.05;
|
|
22
|
+
acting.speaking[`t${i}s0`] = { rx: [0, 0.2, 1.1, phase] };
|
|
23
|
+
acting.speaking[`t${i}s2`] = { rx: [0, 0.35, 1.6, phase + 1] };
|
|
24
|
+
acting.sleeping[`t${i}s0`] = { rx: 0.3 };
|
|
25
|
+
acting.sleeping[`t${i}s1`] = { rx: 0.35 };
|
|
26
|
+
acting.sleeping[`t${i}s2`] = { rx: 0.55 };
|
|
27
|
+
acting.happy[`t${i}s0`] = { rx: [-0.45, 0.35, 2.4, phase] };
|
|
28
|
+
acting.happy[`t${i}s1`] = { rx: [0, 0.3, 2.4, phase + 1] };
|
|
29
|
+
/* a jolt: every tentacle splays and trembles */
|
|
30
|
+
acting.error[`t${i}s0`] = { rx: -0.35 };
|
|
31
|
+
acting.error[`t${i}s1`] = { rx: [0.35, 0.18, 9, phase] };
|
|
32
|
+
acting.error[`t${i}s2`] = { rx: [0.2, 0.22, 11, phase + 2] };
|
|
33
|
+
/* a fright flings them all up and out */
|
|
34
|
+
acting.surprised[`t${i}s0`] = { rx: -0.85 };
|
|
35
|
+
acting.surprised[`t${i}s1`] = { rx: -0.25 };
|
|
36
|
+
acting.surprised[`t${i}s2`] = { rx: -0.3 };
|
|
37
|
+
acting.celebrating[`t${i}s0`] = { rx: [-0.5, 0.3, 3, phase] };
|
|
38
|
+
acting.celebrating[`t${i}s1`] = { rx: [0.15, 0.3, 3, phase + 1] };
|
|
39
|
+
acting.celebrating[`t${i}s2`] = { rx: [0.2, 0.3, 3, phase + 2] };
|
|
40
|
+
/* limp, hanging straight down */
|
|
41
|
+
acting.sad[`t${i}s0`] = { rx: 0.45 };
|
|
42
|
+
acting.sad[`t${i}s1`] = { rx: 0.42 };
|
|
43
|
+
acting.sad[`t${i}s2`] = { rx: [0.55, 0.06, 0.4, phase] };
|
|
44
|
+
acting.working[`t${i}s0`] = { rx: [-0.15, 0.08, 1.2, phase] };
|
|
45
|
+
}
|
|
46
|
+
/* the two front tentacles type, in turn */
|
|
47
|
+
acting.working.t0s0 = { rx: [-1.25, 0.22, 5.5, 0] };
|
|
48
|
+
acting.working.t0s1 = { rx: [0.7, 0.2, 5.5, 0.6] };
|
|
49
|
+
acting.working.t5s0 = { rx: [-1.25, 0.22, 5.5, Math.PI] };
|
|
50
|
+
acting.working.t5s1 = { rx: [0.7, 0.2, 5.5, Math.PI + 0.6] };
|
|
51
|
+
/* and cheer, the front pair flung out to the sides (a swing across the
|
|
52
|
+
tentacle, rz), never forward and up where they would cross the face */
|
|
53
|
+
acting.celebrating.t0s0 = { rx: -0.3, rz: [1.05, 0.25, 3.2, 0] };
|
|
54
|
+
acting.celebrating.t0s1 = { rx: [0.5, 0.15, 3.2, 1] };
|
|
55
|
+
acting.celebrating.t0s2 = { rx: [0.6, 0.2, 3.2, 2] };
|
|
56
|
+
acting.celebrating.t5s0 = { rx: -0.3, rz: [-1.05, 0.25, 3.2, Math.PI] };
|
|
57
|
+
acting.celebrating.t5s1 = { rx: [0.5, 0.15, 3.2, Math.PI + 1] };
|
|
58
|
+
acting.celebrating.t5s2 = { rx: [0.6, 0.2, 3.2, Math.PI + 2] };
|
|
59
|
+
/* tentacle 0 sits front-right: it curls up to the chin */
|
|
60
|
+
acting.thinking.t0s0 = { rx: -1.75 };
|
|
61
|
+
acting.thinking.t0s1 = { rx: 0.95 };
|
|
62
|
+
acting.thinking.t0s2 = { rx: [1.0, 0.12, 1.6, 0] };
|
|
63
|
+
/* tentacle 5 sits front-left: it cups by the side of the head */
|
|
64
|
+
acting.listening.t5s0 = { rx: -1.6 };
|
|
65
|
+
acting.listening.t5s1 = { rx: -0.2 };
|
|
66
|
+
acting.listening.t5s2 = { rx: 0.7 };
|
|
67
|
+
return acting;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const bones: BoneSpec[] = [
|
|
71
|
+
{ name: 'mantle', pivot: [0, 0.42, 0], drive: { rx: [['pitch', -0.6]], ry: [['yaw', 0.6]], rz: [['roll', 0.6]] } },
|
|
72
|
+
];
|
|
73
|
+
const parts: PartSpec[] = [];
|
|
74
|
+
|
|
75
|
+
for (let i = 0; i < TENTACLES; i++) {
|
|
76
|
+
const a = ((i + 0.5) / TENTACLES) * Math.PI * 2;
|
|
77
|
+
for (let s = 0; s < 3; s++) {
|
|
78
|
+
const name = `t${i}s${s}`;
|
|
79
|
+
bones.push({
|
|
80
|
+
name,
|
|
81
|
+
parent: s === 0 ? 'mantle' : `t${i}s${s - 1}`,
|
|
82
|
+
pivot: s === 0 ? [0.26 * Math.sin(a), 0.02, 0.26 * Math.cos(a)] : [0, -SEGMENT, 0],
|
|
83
|
+
rest: s === 0 ? { rx: CURL[0], ry: a } : { rx: CURL[s] },
|
|
84
|
+
wave: { rx: [0.12 + s * 0.1, 0.32, i * 1.3 + s * 0.8], rz: [0.06 + s * 0.05, 0.21, i * 2.1 + s] },
|
|
85
|
+
jiggle: { axis: [0, -1, 0], length: SEGMENT, freq: 2.4 - s * 0.4, damping: 0.25, maxAngle: 0.8 },
|
|
86
|
+
});
|
|
87
|
+
parts.push({
|
|
88
|
+
bone: name,
|
|
89
|
+
shape: 'roundCone',
|
|
90
|
+
from: [0, 0, 0],
|
|
91
|
+
to: [0, -SEGMENT, 0],
|
|
92
|
+
r1: RADII[s],
|
|
93
|
+
r2: RADII[s + 1],
|
|
94
|
+
blend: s === 0 ? 0.1 : 0.04,
|
|
95
|
+
material: 'skin',
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** A floating octopus: a glossy mantle and six trailing tentacles. */
|
|
101
|
+
export const inky: CharacterSpec = {
|
|
102
|
+
id: 'inky',
|
|
103
|
+
name: 'Inky',
|
|
104
|
+
tagline: 'Floats, with six tentacles that trail on spring chains',
|
|
105
|
+
accent: '#e04f7d',
|
|
106
|
+
frame: { target: 0.86, radius: 0.98 },
|
|
107
|
+
bound: { y: 0.64, radius: 1.0 },
|
|
108
|
+
motion: { float: 0.32, hop: 0.12, squash: 1.1, snap: 0.85, look: 0.8, talkSquash: 0.5 },
|
|
109
|
+
materials: {
|
|
110
|
+
skin: { color: '#f2647f', f0: 0.05, spec: 1.1, shininess: 90, rim: 0.8, sss: 0.35, sssColor: '#ffb0c4', gloss: 0.7 },
|
|
111
|
+
},
|
|
112
|
+
bones,
|
|
113
|
+
parts: [
|
|
114
|
+
{ bone: 'mantle', shape: 'ellipsoid', at: [0, 0.38, -0.04], radii: [0.43, 0.45, 0.41], material: 'skin' },
|
|
115
|
+
{ bone: 'mantle', shape: 'ellipsoid', at: [0, 0.04, 0], radii: [0.35, 0.15, 0.35], blend: 0.16, material: 'skin' },
|
|
116
|
+
...parts,
|
|
117
|
+
],
|
|
118
|
+
paints: [
|
|
119
|
+
...([
|
|
120
|
+
[0.14, 0.78, 0.12, 0.07],
|
|
121
|
+
[-0.2, 0.72, 0.16, 0.055],
|
|
122
|
+
[0.33, 0.6, 0.12, 0.05],
|
|
123
|
+
[-0.04, 0.83, -0.05, 0.06],
|
|
124
|
+
[-0.36, 0.52, 0.1, 0.05],
|
|
125
|
+
[0.06, 0.62, 0.33, 0.045],
|
|
126
|
+
[0.338, 0.425, -0.291, 0.045],
|
|
127
|
+
] as const).map(([x, y, z, r]) => ({
|
|
128
|
+
bone: 'mantle', on: ['skin'], kind: 'sphere' as const, at: [x, y, z] as [number, number, number], radius: r, color: '#d23f6c', soft: 0.2,
|
|
129
|
+
})),
|
|
130
|
+
{ bone: 'mantle', on: ['skin'], kind: 'sphere', at: [-0.27, 0.18, 0.31], radius: 0.065, color: '#ff9db0', soft: 0.6, opacity: 0.7 },
|
|
131
|
+
{ bone: 'mantle', on: ['skin'], kind: 'sphere', at: [0.27, 0.18, 0.31], radius: 0.065, color: '#ff9db0', soft: 0.6, opacity: 0.7 },
|
|
132
|
+
],
|
|
133
|
+
eyes: {
|
|
134
|
+
kind: 'ball',
|
|
135
|
+
bone: 'mantle',
|
|
136
|
+
at: [[-0.16, 0.27, 0.3], [0.16, 0.27, 0.3]],
|
|
137
|
+
radius: 0.098,
|
|
138
|
+
iris: '#f2b33d',
|
|
139
|
+
irisSize: 0.66,
|
|
140
|
+
pupilSize: 0.3,
|
|
141
|
+
pupilAspect: 1.9,
|
|
142
|
+
lid: 'skin',
|
|
143
|
+
},
|
|
144
|
+
face: {
|
|
145
|
+
kind: 'mouth',
|
|
146
|
+
bone: 'mantle',
|
|
147
|
+
on: ['skin'],
|
|
148
|
+
at: [0, 0.13, 0.3],
|
|
149
|
+
width: 0.062,
|
|
150
|
+
color: '#5a1430',
|
|
151
|
+
tongue: '#ff8fa8',
|
|
152
|
+
},
|
|
153
|
+
anchors: {
|
|
154
|
+
top: { bone: 'mantle', at: [0.16, 0.86, 0.1] },
|
|
155
|
+
mouth: { bone: 'mantle', at: [0, 0.13, 0.33] },
|
|
156
|
+
ear: { bone: 'mantle', at: [-0.46, 0.4, 0] },
|
|
157
|
+
skirt: { bone: 'mantle', at: [0, 0.0, 0] },
|
|
158
|
+
},
|
|
159
|
+
acting: tentacleActing(),
|
|
160
|
+
fx: {
|
|
161
|
+
replace: ['syllable'],
|
|
162
|
+
/* it lives underwater: bubbles rise all the time, and it talks in bubbles */
|
|
163
|
+
ambient: [{ glyph: 'bubble', anchor: 'skirt', rate: 0.7, spread: 0.35, velocity: [0, 0.18, 0], jitter: 0.05, wobble: 0.06, life: [2.4, 3.2], size: [0.02, 0.045], color: '#8fcfff' }],
|
|
164
|
+
syllable: [{ glyph: 'bubble', anchor: 'mouth', rate: 2, offset: [0, 0, 0.04], velocity: [0.05, 0.2, 0.1], jitter: 0.1, wobble: 0.05, life: [1, 1.4], size: [0.014, 0.034], color: '#9ad7ff' }],
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
export default inky;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { CharacterSpec } from 'wobnimo';
|
|
2
|
+
|
|
3
|
+
/** A coffee cup with a foam-art heart and a curl of steam for hair. */
|
|
4
|
+
export const latte: CharacterSpec = {
|
|
5
|
+
id: 'latte',
|
|
6
|
+
name: 'Latte',
|
|
7
|
+
tagline: 'A cheerful coffee cup with latte-art foam and a curl of steam for hair',
|
|
8
|
+
accent: '#b7794b',
|
|
9
|
+
frame: { target: 0.43, radius: 0.68 },
|
|
10
|
+
bound: { y: 0.41, radius: 0.57 },
|
|
11
|
+
motion: { hop: 0.1, squash: 0.7, snap: 1, talkSquash: 0.4 },
|
|
12
|
+
materials: {
|
|
13
|
+
cup: { color: '#f4efe6', f0: 0.06, spec: 1.6, shininess: 140, rim: 0.6, gloss: 0.85 },
|
|
14
|
+
band: { color: '#c9854f', f0: 0.05, spec: 1, shininess: 80, rim: 0.5, gloss: 0.6 },
|
|
15
|
+
coffee: { color: '#6b3f22', f0: 0.04, spec: 1.2, shininess: 90, rim: 0.3, gloss: 0.7 },
|
|
16
|
+
foam: { color: '#f2dcc0', f0: 0.03, spec: 0.4, shininess: 20, rim: 0.4, sss: 0.3, sssColor: '#fff3e2' },
|
|
17
|
+
steam: { color: '#ffffff', f0: 0.02, spec: 0.2, shininess: 10, rim: 1.4, sss: 0.7, sssColor: '#ffffff', emit: '#ffffff', emitStrength: 0.08 },
|
|
18
|
+
bead: { color: '#2a1a10', f0: 0.06, spec: 2.2, shininess: 400, rim: 0.2, gloss: 1 },
|
|
19
|
+
},
|
|
20
|
+
bones: [
|
|
21
|
+
{ name: 'body', pivot: [0, -0.08, 0], drive: { rx: [['pitch', -0.3]], ry: [['yaw', 0.6]], rz: [['roll', 0.5]] }, wave: { rz: [0.02, 0.5, 0] } },
|
|
22
|
+
{ name: 'handle', parent: 'body', pivot: [0.31, 0.36, 0], drive: { rz: [['flap', 0.4]] } },
|
|
23
|
+
/* the steam curls and sways like a tuft of hair */
|
|
24
|
+
{ name: 'steam', parent: 'body', pivot: [0, 0.58, 0], wave: { rz: [0.12, 0.6, 0] }, jiggle: { axis: [0, 1, 0], length: 0.2, freq: 1.6, damping: 0.12, maxAngle: 0.6 } },
|
|
25
|
+
],
|
|
26
|
+
parts: [
|
|
27
|
+
/* a straight-sided mug with a flat rim, hollowed at the top and filled with coffee and foam */
|
|
28
|
+
{ bone: 'body', shape: 'cylinder', at: [0, 0.33, 0], radius: 0.3, half: 0.25, round: 0.05, material: 'cup' },
|
|
29
|
+
{ bone: 'body', shape: 'cylinder', at: [0, 0.64, 0], radius: 0.25, half: 0.1, round: 0.02, op: 'sub', blend: 0.015, material: 'cup' },
|
|
30
|
+
{ bone: 'body', shape: 'cylinder', at: [0, 0.55, 0], radius: 0.255, half: 0.012, round: 0.008, material: 'coffee' },
|
|
31
|
+
{ bone: 'body', shape: 'ellipsoid', at: [0, 0.562, 0], radii: [0.2, 0.022, 0.2], material: 'foam' },
|
|
32
|
+
/* a cardboard sleeve low on the cup, leaving room for the face */
|
|
33
|
+
{ bone: 'body', shape: 'cylinder', at: [0, 0.2, 0], radius: 0.305, half: 0.05, round: 0.012, material: 'band' },
|
|
34
|
+
/* a ring handle on the right */
|
|
35
|
+
{ bone: 'handle', shape: 'frame', at: [0.07, -0.02, 0], half: [0.08, 0.1], corner: 0.08, width: 0.025, depth: 0.03, rot: [Math.PI / 2, 0, 0], material: 'cup' },
|
|
36
|
+
/* a curl of steam */
|
|
37
|
+
{ bone: 'steam', shape: 'capsule', from: [0, 0, 0], to: [-0.05, 0.12, 0], radius: 0.045, material: 'steam' },
|
|
38
|
+
{ bone: 'steam', shape: 'capsule', from: [-0.05, 0.12, 0], to: [0.03, 0.22, 0], radius: 0.035, blend: 0.04, material: 'steam' },
|
|
39
|
+
{ bone: 'steam', shape: 'capsule', from: [0.03, 0.22, 0], to: [-0.01, 0.3, 0], radius: 0.022, blend: 0.03, material: 'steam' },
|
|
40
|
+
],
|
|
41
|
+
paints: [
|
|
42
|
+
/* a latte-art heart in the foam */
|
|
43
|
+
{ bone: 'body', on: ['foam'], kind: 'sphere', at: [-0.035, 0.584, 0.02], radius: 0.05, color: '#b98257', soft: 0.25 },
|
|
44
|
+
{ bone: 'body', on: ['foam'], kind: 'sphere', at: [0.035, 0.584, 0.02], radius: 0.05, color: '#b98257', soft: 0.25 },
|
|
45
|
+
{ bone: 'body', on: ['foam'], kind: 'sphere', at: [0, 0.584, 0.08], radius: 0.035, color: '#b98257', soft: 0.3 },
|
|
46
|
+
{ bone: 'body', on: ['cup'], kind: 'sphere', at: [-0.19, 0.34, 0.24], radius: 0.05, color: '#ffa4a4', soft: 0.6, opacity: 0.7 },
|
|
47
|
+
{ bone: 'body', on: ['cup'], kind: 'sphere', at: [0.19, 0.34, 0.24], radius: 0.05, color: '#ffa4a4', soft: 0.6, opacity: 0.7 },
|
|
48
|
+
],
|
|
49
|
+
eyes: { kind: 'bead', bone: 'body', at: [[-0.1, 0.42, 0.3], [0.1, 0.42, 0.3]], radii: [0.032, 0.048, 0.02], material: 'bead' },
|
|
50
|
+
face: { kind: 'mouth', bone: 'body', on: ['cup'], at: [0, 0.33, 0.305], width: 0.05, color: '#4a2a18', tongue: '#ff8a8a' },
|
|
51
|
+
anchors: {
|
|
52
|
+
top: { bone: 'steam', at: [0, 0.34, 0] },
|
|
53
|
+
mouth: { bone: 'body', at: [0, 0.33, 0.32] },
|
|
54
|
+
ear: { bone: 'body', at: [-0.32, 0.45, 0] },
|
|
55
|
+
feet: { bone: 'root', at: [0, 0.02, 0.2] },
|
|
56
|
+
},
|
|
57
|
+
acting: {
|
|
58
|
+
thinking: { steam: { rz: 0.4 } },
|
|
59
|
+
listening: { steam: { rz: -0.3 } },
|
|
60
|
+
speaking: { handle: { rz: [0.1, 0.15, 1.4, 0] } },
|
|
61
|
+
sleeping: { steam: { rz: 0.9, rx: 0.3 } },
|
|
62
|
+
working: { steam: { ry: [0, 0, 0, 0, 6] } },
|
|
63
|
+
error: { steam: { rz: [0, 0.4, 9, 0] } },
|
|
64
|
+
surprised: { steam: { rx: -0.3 } },
|
|
65
|
+
celebrating: { steam: { ry: [0, 0, 0, 0, 12] } },
|
|
66
|
+
sad: { steam: { rz: 1.1, rx: 0.5 } },
|
|
67
|
+
},
|
|
68
|
+
fx: {
|
|
69
|
+
ambient: [{ glyph: 'puff', anchor: 'top', rate: 0.8, velocity: [0, 0.15, 0], jitter: 0.04, wobble: 0.06, life: [1.2, 1.6], size: [0.03, 0.07], color: '#ffffff' }],
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default latte;
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import type { CharacterSpec, PaintSpec, PartSpec } from 'wobnimo';
|
|
2
|
+
|
|
3
|
+
/* a quarter turn: servo axles and side plates are mostly turned by one */
|
|
4
|
+
const R = Math.PI / 2;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A little bipedal robot duck: a white helmet head with an orange bill and
|
|
8
|
+
* camera-lens eyes, a stack of servos for a neck, bracket legs and chunky
|
|
9
|
+
* orange boots. Everything moves on servos, so it snaps and holds.
|
|
10
|
+
*/
|
|
11
|
+
export const microduck: CharacterSpec = {
|
|
12
|
+
id: 'microduck',
|
|
13
|
+
name: 'Microduck',
|
|
14
|
+
tagline: 'A bipedal robot duck: servo neck, lens eyes, a bill that clacks when it talks, and boots it marches in',
|
|
15
|
+
accent: '#ff6a1f',
|
|
16
|
+
frame: { target: 0.57, radius: 0.8 },
|
|
17
|
+
bound: { y: 0.58, radius: 0.88 },
|
|
18
|
+
motion: { hop: 0.12, squash: 0.45, snap: 1.4, look: 0.9, snapLook: 1, talkSquash: 0.12 },
|
|
19
|
+
materials: {
|
|
20
|
+
/* injection-moulded plastic: satin, with a faint printed grain */
|
|
21
|
+
shell: {
|
|
22
|
+
color: '#f3f1ec', f0: 0.04, spec: 1.1, shininess: 70, rim: 0.55, gloss: 0.5, sss: 0.12, sssColor: '#ffffff',
|
|
23
|
+
surface: { kind: 'ripple', scale: 70, strength: 0.12, bone: 'head' },
|
|
24
|
+
},
|
|
25
|
+
bodyShell: {
|
|
26
|
+
color: '#f3f1ec', shadeOf: 'shell', f0: 0.04, spec: 1.1, shininess: 70, rim: 0.55, gloss: 0.5, sss: 0.12, sssColor: '#ffffff',
|
|
27
|
+
surface: { kind: 'ripple', scale: 70, strength: 0.12, bone: 'body' },
|
|
28
|
+
},
|
|
29
|
+
bill: { color: '#ff5f1f', f0: 0.05, spec: 1.3, shininess: 90, rim: 0.45, gloss: 0.65, sss: 0.2, sssColor: '#ffb27a' },
|
|
30
|
+
ring: { color: '#ff8410', f0: 0.05, spec: 1.3, shininess: 90, rim: 0.4, gloss: 0.65, sss: 0.15, sssColor: '#ffd08a' },
|
|
31
|
+
boot: { color: '#ff5a24', f0: 0.04, spec: 0.9, shininess: 50, rim: 0.4, gloss: 0.4, sss: 0.15, sssColor: '#ffb08a' },
|
|
32
|
+
sole: { color: '#ffb12e', f0: 0.04, spec: 0.7, shininess: 40, rim: 0.3, gloss: 0.3 },
|
|
33
|
+
/* anodised servo housings and brackets */
|
|
34
|
+
servo: { color: '#2a2d33', f0: 0.06, spec: 1.2, shininess: 80, rim: 0.5, gloss: 0.55, metal: 0.25 },
|
|
35
|
+
horn: { color: '#a3a9b1', f0: 0.3, spec: 1.6, shininess: 120, rim: 0.4, gloss: 0.7, metal: 0.8 },
|
|
36
|
+
/* glass camera lenses */
|
|
37
|
+
lens: { color: '#101318', f0: 0.12, spec: 2.6, shininess: 420, rim: 0.3, gloss: 1 },
|
|
38
|
+
mouth: { color: '#3b1510', f0: 0.04, spec: 0.5, shininess: 30, rim: 0 },
|
|
39
|
+
/* a status light on the chest that takes the state's colour */
|
|
40
|
+
led: { color: '#ffffff', f0: 0.05, spec: 1, shininess: 120, rim: 0, glows: true },
|
|
41
|
+
},
|
|
42
|
+
bones: [
|
|
43
|
+
/* it stands three-quarters on, like the photos of the real thing, so
|
|
44
|
+
one lens looks straight out and the long head reads in profile */
|
|
45
|
+
{ name: 'hips', pivot: [0, 0, 0], rest: { ry: 0.55 } },
|
|
46
|
+
/* the legs hang from the hips, not the body, so the boots stay planted
|
|
47
|
+
when the body turns and rolls */
|
|
48
|
+
{ name: 'legL', parent: 'hips', pivot: [-0.12, 0.36, 0] },
|
|
49
|
+
{ name: 'shinL', parent: 'legL', pivot: [0, -0.15, 0] },
|
|
50
|
+
{ name: 'legR', parent: 'hips', pivot: [0.12, 0.36, 0] },
|
|
51
|
+
{ name: 'shinR', parent: 'legR', pivot: [0, -0.15, 0] },
|
|
52
|
+
{ name: 'body', parent: 'hips', pivot: [0, 0.39, 0], drive: { ry: [['yaw', 0.2]], rz: [['roll', 0.4]] } },
|
|
53
|
+
/* a two-servo neck shares the nod and the turn with the head */
|
|
54
|
+
{ name: 'neck0', parent: 'body', pivot: [0, 0.19, 0.04], drive: { rx: [['pitch', -0.15]], ry: [['yaw', 0.25]] } },
|
|
55
|
+
{
|
|
56
|
+
name: 'neck1', parent: 'neck0', pivot: [0, 0.09, 0], drive: { rx: [['pitch', -0.1]], ry: [['yaw', 0.2]] },
|
|
57
|
+
jiggle: { axis: [0, 1, 0], length: 0.2, freq: 3.4, damping: 0.35, maxAngle: 0.16 },
|
|
58
|
+
},
|
|
59
|
+
{ name: 'head', parent: 'neck1', pivot: [0, 0.09, 0], drive: { rx: [['pitch', -0.35]], ry: [['yaw', 0.55]], rz: [['roll', 0.6]] } },
|
|
60
|
+
/* the lower bill hinges at the back and drops to talk */
|
|
61
|
+
{ name: 'jaw', parent: 'head', pivot: [0, 0.063, -0.18], drive: { rx: [['talk', 0.24]] } },
|
|
62
|
+
],
|
|
63
|
+
parts: [
|
|
64
|
+
/* ── head: a rounded hood over a bill of two flat plates ── */
|
|
65
|
+
{ bone: 'head', shape: 'roundBox', at: [0, 0.245, 0.05], half: [0.2, 0.17, 0.3], round: 0.16, clip: { normal: [0, -1, 0], offset: 0.145 }, material: 'shell' },
|
|
66
|
+
/* the bill is two flat orange plates, like the real one: the top plate
|
|
67
|
+
is fixed under the hood and runs out past it, the lower one hinges
|
|
68
|
+
at the back and drops to talk. Behind them, a dark throat */
|
|
69
|
+
{ bone: 'head', shape: 'roundBox', at: [0, 0.085, 0.1], half: [0.208, 0.022, 0.32], round: 0.016, material: 'bill' },
|
|
70
|
+
{ bone: 'head', shape: 'roundBox', at: [0, 0.045, -0.06], half: [0.17, 0.035, 0.12], round: 0.02, material: 'mouth' },
|
|
71
|
+
{ bone: 'jaw', shape: 'roundBox', at: [0, -0.017, 0.27], half: [0.192, 0.018, 0.285], round: 0.014, material: 'bill' },
|
|
72
|
+
/* lens eyes in orange rings on the flat sides of the hood, turned a little to the front */
|
|
73
|
+
{ bone: 'head', shape: 'cylinder', at: [-0.205, 0.225, 0.15], rot: [R, -1.05, 0], radius: 0.08, half: 0.026, round: 0.016, material: 'ring' },
|
|
74
|
+
{ bone: 'head', shape: 'cylinder', at: [0.205, 0.225, 0.15], rot: [R, 1.05, 0], radius: 0.08, half: 0.026, round: 0.016, material: 'ring' },
|
|
75
|
+
/* a dark sensor hole above and ahead of each eye */
|
|
76
|
+
{ bone: 'head', shape: 'sphere', at: [-0.2, 0.31, 0.25], radius: 0.016, material: 'servo' },
|
|
77
|
+
{ bone: 'head', shape: 'sphere', at: [0.2, 0.31, 0.25], radius: 0.016, material: 'servo' },
|
|
78
|
+
/* the bracket the neck bolts into */
|
|
79
|
+
{ bone: 'head', shape: 'roundBox', at: [0, 0.01, 0], half: [0.07, 0.035, 0.07], round: 0.016, material: 'servo' },
|
|
80
|
+
|
|
81
|
+
/* ── neck: two stacked servos with silver horns ── */
|
|
82
|
+
{ bone: 'neck0', shape: 'roundBox', at: [0, 0.045, 0], half: [0.048, 0.047, 0.042], round: 0.016, material: 'servo' },
|
|
83
|
+
{ bone: 'neck0', shape: 'cylinder', at: [0, 0.02, 0], rot: [0, 0, R], radius: 0.026, half: 0.057, round: 0.01, material: 'horn' },
|
|
84
|
+
{ bone: 'neck1', shape: 'roundBox', at: [0, 0.045, 0], half: [0.045, 0.047, 0.04], round: 0.016, material: 'servo' },
|
|
85
|
+
{ bone: 'neck1', shape: 'cylinder', at: [0, 0.02, 0], rot: [0, 0, R], radius: 0.024, half: 0.053, round: 0.01, material: 'horn' },
|
|
86
|
+
|
|
87
|
+
/* ── body: a rounded box on a servo hip block ── */
|
|
88
|
+
{ bone: 'body', shape: 'roundBox', at: [0, 0.1, -0.01], half: [0.19, 0.1, 0.15], round: 0.085, material: 'bodyShell' },
|
|
89
|
+
{ bone: 'body', shape: 'capsule', from: [-0.03, 0.12, 0.14], to: [0.03, 0.12, 0.14], radius: 0.014, material: 'led' },
|
|
90
|
+
{ bone: 'hips', shape: 'roundBox', at: [0, 0.37, 0], half: [0.15, 0.04, 0.09], round: 0.02, material: 'servo' },
|
|
91
|
+
{ bone: 'hips', shape: 'cylinder', at: [-0.16, 0.36, 0], rot: [0, 0, R], radius: 0.045, half: 0.026, round: 0.012, material: 'horn' },
|
|
92
|
+
{ bone: 'hips', shape: 'cylinder', at: [0.16, 0.36, 0], rot: [0, 0, R], radius: 0.045, half: 0.026, round: 0.012, material: 'horn' },
|
|
93
|
+
|
|
94
|
+
/* ── legs: brackets, knee servos with white guards, chunky boots ── */
|
|
95
|
+
...([['legL', 'shinL', -1], ['legR', 'shinR', 1]] as const).flatMap(([leg, shin, s]): PartSpec[] => [
|
|
96
|
+
{ bone: leg, shape: 'roundBox', at: [0, -0.075, 0], half: [0.038, 0.07, 0.042], round: 0.015, material: 'servo' },
|
|
97
|
+
{ bone: leg, shape: 'cylinder', at: [0, -0.15, 0], rot: [0, 0, R], radius: 0.036, half: 0.05, round: 0.012, material: 'horn' },
|
|
98
|
+
{ bone: leg, shape: 'plate', at: [s * 0.056, -0.1, -0.005], rot: [s * R, s * Math.PI / 4, R], half: [0.058, 0.058], corner: 0.034, depth: 0.012, material: 'bodyShell' },
|
|
99
|
+
{ bone: shin, shape: 'roundBox', at: [0, -0.06, 0], half: [0.034, 0.055, 0.038], round: 0.014, material: 'servo' },
|
|
100
|
+
{ bone: shin, shape: 'roundBox', at: [0, -0.135, 0.005], half: [0.048, 0.036, 0.052], round: 0.016, material: 'servo' },
|
|
101
|
+
{ bone: shin, shape: 'roundBox', at: [0, -0.17, 0.045], half: [0.074, 0.04, 0.108], round: 0.038, material: 'boot' },
|
|
102
|
+
{ bone: shin, shape: 'roundBox', at: [0, -0.196, 0.045], half: [0.079, 0.014, 0.113], round: 0.012, material: 'sole' },
|
|
103
|
+
]),
|
|
104
|
+
],
|
|
105
|
+
paints: [
|
|
106
|
+
/* little red rivets on the bill and vent dots on the boots */
|
|
107
|
+
...[-1, 1].flatMap((s): PaintSpec[] => [
|
|
108
|
+
{ bone: 'head', on: ['bill'], kind: 'sphere', at: [s * 0.208, 0.085, -0.13], radius: 0.013, color: '#c8261a', soft: 0.2 },
|
|
109
|
+
{ bone: 'head', on: ['bill'], kind: 'sphere', at: [s * 0.208, 0.085, -0.18], radius: 0.013, color: '#c8261a', soft: 0.2 },
|
|
110
|
+
]),
|
|
111
|
+
...['shinL', 'shinR'].flatMap((bone) =>
|
|
112
|
+
[[-0.03, 0.1], [0.03, 0.1], [0, 0.13], [-0.03, 0.06], [0.03, 0.06]].map(([x, z]): PaintSpec => ({
|
|
113
|
+
bone, on: ['boot'], kind: 'sphere', at: [x, -0.13, z], radius: 0.011, color: '#c23a14', soft: 0.25,
|
|
114
|
+
})),
|
|
115
|
+
),
|
|
116
|
+
/* screw heads at the corners of the body */
|
|
117
|
+
...[-1, 1].map((s): PaintSpec => ({ bone: 'body', on: ['bodyShell'], kind: 'sphere', at: [s * 0.142, 0.04, 0.117], radius: 0.009, color: '#8d9198', soft: 0.2 })),
|
|
118
|
+
],
|
|
119
|
+
/* the dark lens behind each ring: it narrows to blink */
|
|
120
|
+
eyes: {
|
|
121
|
+
kind: 'bead',
|
|
122
|
+
bone: 'head',
|
|
123
|
+
at: [[-0.228, 0.225, 0.165], [0.228, 0.225, 0.165]],
|
|
124
|
+
radii: [0.048, 0.048, 0.048],
|
|
125
|
+
material: 'lens',
|
|
126
|
+
},
|
|
127
|
+
anchors: {
|
|
128
|
+
top: { bone: 'head', at: [0.1, 0.42, 0.08] },
|
|
129
|
+
mouth: { bone: 'head', at: [0, 0.06, 0.45] },
|
|
130
|
+
ear: { bone: 'head', at: [-0.24, 0.2, 0.05] },
|
|
131
|
+
feet: { bone: 'root', at: [0, 0.02, 0.08] },
|
|
132
|
+
chest: { bone: 'body', at: [0, 0.12, 0.16] },
|
|
133
|
+
neck: { bone: 'neck0', at: [0.05, 0.08, 0.05] },
|
|
134
|
+
},
|
|
135
|
+
acting: {
|
|
136
|
+
/* weight shifting from boot to boot, the head bobbing on its servos */
|
|
137
|
+
idle: {
|
|
138
|
+
body: { rz: [0, 0.03, 0.45, 0] },
|
|
139
|
+
neck0: { rx: [0, 0.04, 0.9, 0] },
|
|
140
|
+
},
|
|
141
|
+
/* head cocked, bill ajar, one boot tapping */
|
|
142
|
+
thinking: {
|
|
143
|
+
head: { rz: 0.22, rx: -0.1 },
|
|
144
|
+
jaw: { rx: 0.06 },
|
|
145
|
+
legR: { rx: [-0.05, 0.05, 2.4, 0] },
|
|
146
|
+
shinR: { rx: [0.05, 0.05, 2.4, Math.PI] },
|
|
147
|
+
},
|
|
148
|
+
/* one lens turned to the sound */
|
|
149
|
+
listening: {
|
|
150
|
+
head: { rz: -0.24, ry: 0.2 },
|
|
151
|
+
neck0: { rx: 0.1 },
|
|
152
|
+
},
|
|
153
|
+
speaking: {
|
|
154
|
+
neck0: { rx: [0, 0.05, 1.6, 0] },
|
|
155
|
+
body: { rz: [0, 0.03, 0.8, 0] },
|
|
156
|
+
},
|
|
157
|
+
/* powered down: the neck folds and the head rests on its chest */
|
|
158
|
+
sleeping: {
|
|
159
|
+
neck0: { rx: 0.08 },
|
|
160
|
+
neck1: { rx: 0.05 },
|
|
161
|
+
head: { rz: 0.12 },
|
|
162
|
+
legL: { rx: -0.12 },
|
|
163
|
+
shinL: { rx: 0.24 },
|
|
164
|
+
legR: { rx: -0.12 },
|
|
165
|
+
shinR: { rx: 0.24 },
|
|
166
|
+
},
|
|
167
|
+
/* pecking at a keyboard */
|
|
168
|
+
working: {
|
|
169
|
+
neck0: { rx: [0.1, 0.06, 4.2, 0] },
|
|
170
|
+
neck1: { rx: [0.04, 0.04, 4.2, 0.6] },
|
|
171
|
+
jaw: { rx: [0.03, 0.03, 8.4, 0] },
|
|
172
|
+
},
|
|
173
|
+
/* a fault: knock-kneed, bill hanging, head twitching on a stuck servo */
|
|
174
|
+
error: {
|
|
175
|
+
head: { rz: [0.2, 0.06, 9, 0] },
|
|
176
|
+
jaw: { rx: 0.06 },
|
|
177
|
+
legL: { rz: 0.1 },
|
|
178
|
+
legR: { rz: -0.1 },
|
|
179
|
+
neck0: { rx: 0.12 },
|
|
180
|
+
},
|
|
181
|
+
/* the neck shoots up and the bill drops open */
|
|
182
|
+
surprised: {
|
|
183
|
+
neck0: { rx: -0.15 },
|
|
184
|
+
head: { rx: 0.05 },
|
|
185
|
+
},
|
|
186
|
+
/* marching in place, head bopping side to side */
|
|
187
|
+
celebrating: {
|
|
188
|
+
legL: { rx: [-0.25, 0.25, 2.4, 0] },
|
|
189
|
+
shinL: { rx: [0.25, 0.25, 2.4, Math.PI] },
|
|
190
|
+
legR: { rx: [-0.25, 0.25, 2.4, Math.PI] },
|
|
191
|
+
shinR: { rx: [0.25, 0.25, 2.4, 0] },
|
|
192
|
+
head: { rz: [0, 0.2, 1.2, 0] },
|
|
193
|
+
},
|
|
194
|
+
/* the neck sinks and the knees give a little */
|
|
195
|
+
sad: {
|
|
196
|
+
head: { rz: -0.1 },
|
|
197
|
+
legL: { rx: -0.08 },
|
|
198
|
+
shinL: { rx: 0.16 },
|
|
199
|
+
legR: { rx: -0.08 },
|
|
200
|
+
shinR: { rx: 0.16 },
|
|
201
|
+
},
|
|
202
|
+
/* a happy stomp and a clack of the bill */
|
|
203
|
+
happy: {
|
|
204
|
+
legL: { rx: [-0.2, 0.2, 4, 0] },
|
|
205
|
+
shinL: { rx: [0.2, 0.2, 4, Math.PI] },
|
|
206
|
+
legR: { rx: [-0.2, 0.2, 4, Math.PI] },
|
|
207
|
+
shinR: { rx: [0.2, 0.2, 4, 0] },
|
|
208
|
+
jaw: { rx: [0.08, 0.08, 8, 0] },
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
fx: {
|
|
212
|
+
/* a robot shorts out with sparks from its neck */
|
|
213
|
+
error: [
|
|
214
|
+
{ glyph: 'spark', anchor: 'neck', rate: 5, spread: 0.03, velocity: [0.25, 0.3, 0.1], jitter: 0.8, gravity: 2, life: [0.2, 0.35], size: [0.03, 0.012], color: '#ffd166', glow: true, align: true },
|
|
215
|
+
],
|
|
216
|
+
working: [
|
|
217
|
+
{ glyph: 'dot', anchor: 'chest', rate: 1.6, offset: [0, 0.02, 0.02], spread: 0.03, velocity: [0, 0.1, 0.06], jitter: 0.02, life: [0.7, 0.9], size: [0.012, 0.004], color: '#ffb27a', glow: true },
|
|
218
|
+
],
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
export default microduck;
|