@adatechnology/game-animals-three 0.3.8 → 0.4.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/dist/chunk-SC4QTSML.js +1258 -0
- package/dist/chunk-SC4QTSML.js.map +1 -0
- package/dist/index.d.ts +17 -194
- package/dist/index.global.js +1039 -539
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +23 -1219
- package/dist/index.js.map +1 -1
- package/dist/testing-CjEl69y1.d.ts +184 -0
- package/dist/testing.d.ts +4 -0
- package/dist/testing.js +11 -0
- package/dist/testing.js.map +1 -0
- package/package.json +12 -7
package/dist/index.global.js
CHANGED
|
@@ -45,6 +45,618 @@ var GameAnimalsThree = (() => {
|
|
|
45
45
|
updateSplit: () => updateSplit
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
+
// ../game-contracts/dist/index.js
|
|
49
|
+
var DEFAULT_COST_ALLOCATION_BYTES = 1024 * 1024;
|
|
50
|
+
var DEFERRED_QUEUE_ID = {
|
|
51
|
+
DESTRUCTION_EVENTS: "destruction.events",
|
|
52
|
+
BREACH_PAINT: "floorplan.breach-paint",
|
|
53
|
+
AUDIO_VOICES: "audio.voices",
|
|
54
|
+
VEHICLE_CREASE: "vehicles.crease"
|
|
55
|
+
};
|
|
56
|
+
var DEFERRED_PRIORITY = {
|
|
57
|
+
[DEFERRED_QUEUE_ID.DESTRUCTION_EVENTS]: { priority: 300, phase: "present" },
|
|
58
|
+
[DEFERRED_QUEUE_ID.BREACH_PAINT]: { priority: 250, phase: "present" },
|
|
59
|
+
[DEFERRED_QUEUE_ID.AUDIO_VOICES]: { priority: 200, phase: "idle", reserveMs: 1 },
|
|
60
|
+
[DEFERRED_QUEUE_ID.VEHICLE_CREASE]: { priority: 100, phase: "idle" }
|
|
61
|
+
};
|
|
62
|
+
var KIT_ORIGIN_KEY = "kitOrigin";
|
|
63
|
+
function markKitOrigin(object2, origin) {
|
|
64
|
+
const node = object2;
|
|
65
|
+
node.userData = node.userData ?? {};
|
|
66
|
+
node.userData[KIT_ORIGIN_KEY] = { ...origin };
|
|
67
|
+
return object2;
|
|
68
|
+
}
|
|
69
|
+
var SURFACE_IDS = ["concrete", "asphalt", "wood", "tile", "dirt", "grass", "gravel", "sand", "metal", "water", "glass", "carpet"];
|
|
70
|
+
var GAIT_IDS = ["walk", "run"];
|
|
71
|
+
var LANDING_IDS = ["light", "heavy"];
|
|
72
|
+
var BODY_SOUND_IDS = [
|
|
73
|
+
"jump",
|
|
74
|
+
"cloth_rustle",
|
|
75
|
+
"body_fall",
|
|
76
|
+
"fall_damage",
|
|
77
|
+
"player_hurt",
|
|
78
|
+
"player_breath_run",
|
|
79
|
+
"player_death",
|
|
80
|
+
"bite",
|
|
81
|
+
"grab",
|
|
82
|
+
"punch_swing",
|
|
83
|
+
"punch_hit_body",
|
|
84
|
+
"punch_hit_face",
|
|
85
|
+
"punch_hit_object",
|
|
86
|
+
"kick_swing",
|
|
87
|
+
"kick_hit",
|
|
88
|
+
"kick_hit_object",
|
|
89
|
+
"shove_two_hands",
|
|
90
|
+
"knife_swing",
|
|
91
|
+
"knife_stab",
|
|
92
|
+
"knife_slash",
|
|
93
|
+
"knife_hit_object",
|
|
94
|
+
"blunt_swing",
|
|
95
|
+
"blunt_hit",
|
|
96
|
+
"blunt_hit_object",
|
|
97
|
+
"axe_swing",
|
|
98
|
+
"axe_chop",
|
|
99
|
+
"axe_hit_object"
|
|
100
|
+
];
|
|
101
|
+
var footstepSoundId = (surface, gait) => `footstep_${surface}_${gait}`;
|
|
102
|
+
var FOOTSTEP_SOUND_IDS = SURFACE_IDS.flatMap((surface) => GAIT_IDS.map((gait) => footstepSoundId(surface, gait)));
|
|
103
|
+
var LAND_SOUND_IDS = SURFACE_IDS.flatMap((surface) => LANDING_IDS.map((landing2) => `land_${surface}_${landing2}`));
|
|
104
|
+
var BODY_FOLEY_IDS = [...FOOTSTEP_SOUND_IDS, ...LAND_SOUND_IDS, ...BODY_SOUND_IDS];
|
|
105
|
+
var SWING_LEAD_SECONDS = { punch: 0.07, kick: 0.09, shove: 0, blade: 0.05, blunt: 0.1, chop: 0.11 };
|
|
106
|
+
|
|
107
|
+
// ../game-audio/dist/chunk-DZITVFMJ.js
|
|
108
|
+
var DISTANCE_CURVES = {
|
|
109
|
+
/** The game's `sfx`: `vol / (1 + d² × 0.004)`, cutoff `/ (1 + d × 0.01)`, silent below 0.01 (jogo L62091–62092, L62101). */
|
|
110
|
+
game_sfx: { model: "inverse_square", k: 4e-3, cutoffK: 0.01, minGain: 0.01 },
|
|
111
|
+
/** The game's `grito`: `1 / (1 + d² × 0.006)`, silent below 0.02 (jogo L62129–62130). */
|
|
112
|
+
game_scream: { model: "inverse_square", k: 6e-3, minGain: 0.02 },
|
|
113
|
+
/** The game's `voz`: `1 / (1 + d² × 0.01)`, silent below 0.02 (jogo L62146–62147). */
|
|
114
|
+
game_voice: { model: "inverse_square", k: 0.01, minGain: 0.02 },
|
|
115
|
+
/** The game's `boom`: `1.4 / (1 + d² × 0.002)`, never silent (jogo L68280). */
|
|
116
|
+
game_boom: { model: "inverse_square", k: 2e-3, scale: 1.4 },
|
|
117
|
+
/** The art scene's `outAt`: `vol / (1 + d² × 0.008)` (cena L1320). */
|
|
118
|
+
art_scene: { model: "inverse_square", k: 8e-3 },
|
|
119
|
+
/** The game's animal calls: `max(0, 1 − d / 70) × 0.25`, silent at or below 0.005 (jogo L66627–66628). */
|
|
120
|
+
animals: { model: "linear", range: 70, scale: 0.25, minGain: 5e-3 }
|
|
121
|
+
};
|
|
122
|
+
var game_sfx_default = {
|
|
123
|
+
sources: ["jogo:L62089-62107"],
|
|
124
|
+
note: "The game's sfx table P: [lowpass cutoff Hz, peak gain, seconds]. Played as a noise burst with the game's distance curve (falloff game_sfx) and a 0.05 s tail. Team names in `team`.",
|
|
125
|
+
classes: [
|
|
126
|
+
{ id: "pistol", team: "pistola", bus: "weapons", cutoff: 1800, gain: 0.9, seconds: 0.18 },
|
|
127
|
+
{ id: "shotgun", team: "escopeta", bus: "weapons", cutoff: 900, gain: 1.2, seconds: 0.35 },
|
|
128
|
+
{ id: "rifle", team: "fuzil", bus: "weapons", cutoff: 1400, gain: 1.1, seconds: 0.28 },
|
|
129
|
+
{ id: "long_rifle", team: "rifle", bus: "weapons", cutoff: 1100, gain: 1.3, seconds: 0.45 },
|
|
130
|
+
{ id: "impact", team: "impacto", bus: "world", cutoff: 2500, gain: 0.25, seconds: 0.05 },
|
|
131
|
+
{ id: "flesh", team: "carne", bus: "world", cutoff: 600, gain: 0.35, seconds: 0.08 },
|
|
132
|
+
{ id: "step", team: "passo", bus: "world", cutoff: 400, gain: 0.08, seconds: 0.05 },
|
|
133
|
+
{ id: "glass", team: "vidro", bus: "world", cutoff: 5e3, gain: 0.5, seconds: 0.3 },
|
|
134
|
+
{ id: "wood", team: "madeira", bus: "world", cutoff: 700, gain: 0.5, seconds: 0.2 },
|
|
135
|
+
{ id: "reload", team: "recarga", bus: "weapons", cutoff: 3e3, gain: 0.15, seconds: 0.06 },
|
|
136
|
+
{ id: "empty", team: "vazio", bus: "weapons", cutoff: 4e3, gain: 0.12, seconds: 0.03 },
|
|
137
|
+
{ id: "explosion", team: "explosao", bus: "world", cutoff: 200, gain: 1.6, seconds: 1.4 }
|
|
138
|
+
],
|
|
139
|
+
fallback: { id: "unknown", team: "(any other name)", bus: "world", cutoff: 1e3, gain: 0.5, seconds: 0.1 }
|
|
140
|
+
};
|
|
141
|
+
var GAME_SFX = game_sfx_default;
|
|
142
|
+
var GAME_SFX_CLASSES = GAME_SFX.classes;
|
|
143
|
+
var GAME_SFX_FALLBACK = GAME_SFX.fallback;
|
|
144
|
+
function noiseClassRecipe(row, id = `sfx_${row.id}`) {
|
|
145
|
+
return {
|
|
146
|
+
id,
|
|
147
|
+
bus: row.bus,
|
|
148
|
+
order: "burst",
|
|
149
|
+
duration: row.seconds,
|
|
150
|
+
tail: 0.05,
|
|
151
|
+
layers: [
|
|
152
|
+
{
|
|
153
|
+
source: { kind: "noise", offset: "random" },
|
|
154
|
+
filters: { mode: "serial", bank: [{ type: "lowpass", frequency: { set: row.cutoff } }] },
|
|
155
|
+
envelope: [
|
|
156
|
+
[0, row.gain, "set"],
|
|
157
|
+
["1d", 1e-3, "exp", "fixed"]
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
],
|
|
161
|
+
falloff: DISTANCE_CURVES.game_sfx,
|
|
162
|
+
sources: [...GAME_SFX.sources.map((source) => `${source} ${row.team}`)]
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
var GAME_SFX_BANK = { id: "game_sfx", sounds: [...GAME_SFX_CLASSES, GAME_SFX_FALLBACK].map((row) => noiseClassRecipe(row)) };
|
|
166
|
+
var mix_profiles_default = [
|
|
167
|
+
{
|
|
168
|
+
id: "game",
|
|
169
|
+
master: 0.5,
|
|
170
|
+
noise: { seconds: 1.5, create: "lazy" },
|
|
171
|
+
sources: ["jogo:L62077-62081 master 0.5 to the output", "jogo:L62082-62088 noise 1.5 s made by the first sound that needs it"]
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
id: "art_scene",
|
|
175
|
+
master: 0.85,
|
|
176
|
+
compressor: { threshold: -12, ratio: 5 },
|
|
177
|
+
reverb: { seconds: 2.2, decay: 3.4, wet: 0.4 },
|
|
178
|
+
noise: { seconds: 2, create: "eager" },
|
|
179
|
+
sources: [
|
|
180
|
+
"cena:L1308 compressor -12 dB, ratio 5",
|
|
181
|
+
"cena:L1309 master 0.85",
|
|
182
|
+
"cena:L1310 convolver, impulse 2.2 s of (1 - i/len)^3.4",
|
|
183
|
+
"cena:L1311 wet 0.4",
|
|
184
|
+
"cena:L1312 noise 2 s made with the chain"
|
|
185
|
+
]
|
|
186
|
+
}
|
|
187
|
+
];
|
|
188
|
+
var MIX_PROFILES = Object.fromEntries(
|
|
189
|
+
mix_profiles_default.map((profile) => [profile.id, profile])
|
|
190
|
+
);
|
|
191
|
+
var BENCH_BANK = {
|
|
192
|
+
id: "audio_bench",
|
|
193
|
+
sounds: [
|
|
194
|
+
{
|
|
195
|
+
id: "bench_ping",
|
|
196
|
+
bus: "ui",
|
|
197
|
+
pan: true,
|
|
198
|
+
duration: 0.25,
|
|
199
|
+
layers: [
|
|
200
|
+
{
|
|
201
|
+
gain: 0.5,
|
|
202
|
+
wet: 0.3,
|
|
203
|
+
source: { kind: "osc", wave: "sine", frequency: { from: 880 } },
|
|
204
|
+
envelope: [
|
|
205
|
+
[0, 1e-4, "set", "fixed"],
|
|
206
|
+
[2e-3, 1, "exp"],
|
|
207
|
+
["1d", 1e-4, "exp", "fixed"]
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
],
|
|
211
|
+
falloff: DISTANCE_CURVES.art_scene,
|
|
212
|
+
sources: ["sdk: bench probe, a 880 Hz ping through the art scene output stage"]
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
id: "bench_hiss",
|
|
216
|
+
bus: "ui",
|
|
217
|
+
pan: true,
|
|
218
|
+
duration: [0.3, 0.9],
|
|
219
|
+
layers: [
|
|
220
|
+
{
|
|
221
|
+
gain: 0.4,
|
|
222
|
+
source: { kind: "noise", offset: "random", offsetScale: 1.5, loop: true },
|
|
223
|
+
filters: { mode: "serial", bank: [{ type: "highpass", frequency: { set: 3e3 }, q: 0.7 }] },
|
|
224
|
+
envelope: [
|
|
225
|
+
[0, 1e-4, "set", "fixed"],
|
|
226
|
+
[2e-3, 1, "exp"],
|
|
227
|
+
["1d", 1e-4, "exp", "fixed"]
|
|
228
|
+
]
|
|
229
|
+
}
|
|
230
|
+
],
|
|
231
|
+
falloff: DISTANCE_CURVES.art_scene,
|
|
232
|
+
sources: ["sdk: bench probe, a highpass hiss of random length"]
|
|
233
|
+
}
|
|
234
|
+
]
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// ../game-audio/dist/index.js
|
|
238
|
+
var ATTACK = 2e-3;
|
|
239
|
+
function lengthOf(d, attack) {
|
|
240
|
+
if (typeof d === "number") return attack + d;
|
|
241
|
+
if (Array.isArray(d)) return [attack + d[0], attack + d[1]];
|
|
242
|
+
return { ...d, add: (d.add ?? 0) + attack };
|
|
243
|
+
}
|
|
244
|
+
var envelope = (attack) => [
|
|
245
|
+
[0, 1e-4, "set", "fixed"],
|
|
246
|
+
[attack, 1, "exp"],
|
|
247
|
+
["1d", 1e-4, "exp", "fixed"]
|
|
248
|
+
];
|
|
249
|
+
function sceneNoise(o) {
|
|
250
|
+
const a = o.a ?? ATTACK;
|
|
251
|
+
const over = typeof o.d === "number" ? o.d : 0;
|
|
252
|
+
return {
|
|
253
|
+
filters: {
|
|
254
|
+
mode: "serial",
|
|
255
|
+
bank: [{ type: o.type ?? "lowpass", frequency: o.f2 === void 0 ? { set: o.f } : { set: o.f, to: o.f2, curve: "exp", over }, q: o.q ?? 0.7 }]
|
|
256
|
+
},
|
|
257
|
+
duration: lengthOf(o.d, a),
|
|
258
|
+
gain: o.vol,
|
|
259
|
+
...o.delay === void 0 ? {} : { at: o.delay },
|
|
260
|
+
...o.wet === void 0 ? {} : { wet: o.wet },
|
|
261
|
+
source: { kind: "noise", offset: "random", offsetScale: 1.5, loop: true },
|
|
262
|
+
envelope: envelope(a)
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
function sceneTone(o) {
|
|
266
|
+
return {
|
|
267
|
+
source: { kind: "osc", wave: o.wave ?? "sine", frequency: { from: o.f, to: o.f2 ?? "from", curve: "exp", over: "duration" } },
|
|
268
|
+
duration: lengthOf(o.d, ATTACK),
|
|
269
|
+
gain: o.vol,
|
|
270
|
+
...o.delay === void 0 ? {} : { at: o.delay },
|
|
271
|
+
...o.wet === void 0 ? {} : { wet: o.wet },
|
|
272
|
+
envelope: envelope(ATTACK)
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
function sceneVoice(o) {
|
|
276
|
+
return {
|
|
277
|
+
duration: lengthOf(o.d, 0),
|
|
278
|
+
gain: o.vol,
|
|
279
|
+
wet: 0.45,
|
|
280
|
+
source: {
|
|
281
|
+
kind: "formant_voice",
|
|
282
|
+
wave: o.wave ?? "sawtooth",
|
|
283
|
+
frequency: { from: o.f0, to: o.f1, curve: "linear", over: "duration" },
|
|
284
|
+
vibrato: { rate: [4, 10], depth: 0.08 },
|
|
285
|
+
formants: [
|
|
286
|
+
{ frequency: o.fA, q: 4 },
|
|
287
|
+
{ frequency: o.fB, q: 6 }
|
|
288
|
+
],
|
|
289
|
+
breath: { frequency: o.fB, q: 1.1, gain: o.noise },
|
|
290
|
+
mix: 3.2
|
|
291
|
+
},
|
|
292
|
+
envelope: [
|
|
293
|
+
[0, 1e-4, "set", "fixed"],
|
|
294
|
+
[0.1, 1, "exp"],
|
|
295
|
+
["0.6d", 1, "set"],
|
|
296
|
+
["1d", 1e-4, "exp", "fixed"]
|
|
297
|
+
]
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
var TAKES = [
|
|
301
|
+
{ f: 1, t: 1, v: 1 },
|
|
302
|
+
{ f: 1.08, t: 0.9, v: 0.92 },
|
|
303
|
+
{ f: 0.93, t: 1.12, v: 1.05 },
|
|
304
|
+
{ f: 1.03, t: 1.05, v: 0.88 }
|
|
305
|
+
];
|
|
306
|
+
var FOOTSTEP_FALLOFF = { model: "inverse_square", k: 0.03, cutoffK: 0.03, minGain: 4e-3 };
|
|
307
|
+
var BODY_FALLOFF = { model: "inverse_square", k: 0.012, cutoffK: 0.015, minGain: 4e-3 };
|
|
308
|
+
var SURFACES = {
|
|
309
|
+
concrete: { heel: { f: 95, d: 0.05, vol: 0.55 }, roll: { type: "bandpass", f: 2300, q: 1.1, d: 0.05, vol: 0.38 }, grains: { count: 2, f: 4200, q: 2, spread: 0.04, vol: 0.08 } },
|
|
310
|
+
asphalt: { heel: { f: 90, d: 0.05, vol: 0.5 }, roll: { type: "bandpass", f: 1700, q: 0.9, d: 0.06, vol: 0.36 }, grains: { count: 4, f: 3600, q: 2.5, spread: 0.06, vol: 0.1 } },
|
|
311
|
+
wood: { heel: { f: 130, d: 0.08, vol: 0.55 }, roll: { type: "lowpass", f: 1300, q: 0.8, d: 0.06, vol: 0.3 }, ring: [{ f: 210, d: 0.1, vol: 0.18 }, { f: 470, d: 0.06, vol: 0.06 }] },
|
|
312
|
+
tile: { heel: { f: 110, d: 0.04, vol: 0.45 }, roll: { type: "bandpass", f: 3600, q: 2, d: 0.03, vol: 0.42 }, ring: [{ f: 1900, d: 0.03, vol: 0.05 }] },
|
|
313
|
+
dirt: { heel: { f: 75, d: 0.06, vol: 0.45 }, roll: { type: "lowpass", f: 750, q: 0.7, d: 0.09, vol: 0.4 }, grains: { count: 3, f: 1800, q: 1.5, spread: 0.07, vol: 0.06 } },
|
|
314
|
+
grass: { heel: { f: 70, d: 0.05, vol: 0.32 }, roll: { type: "highpass", f: 2600, q: 0.7, d: 0.13, vol: 0.28 }, grains: { count: 4, f: 5200, q: 1.2, spread: 0.1, vol: 0.07 } },
|
|
315
|
+
gravel: { heel: { f: 80, d: 0.05, vol: 0.4 }, roll: { type: "lowpass", f: 950, q: 0.8, d: 0.1, vol: 0.3 }, grains: { count: 8, f: 2600, q: 3, spread: 0.13, vol: 0.2 } },
|
|
316
|
+
sand: { heel: { f: 65, d: 0.06, vol: 0.3 }, roll: { type: "bandpass", f: 1500, q: 0.6, d: 0.16, vol: 0.3 }, grains: { count: 5, f: 4800, q: 1.5, spread: 0.12, vol: 0.05 } },
|
|
317
|
+
metal: { heel: { f: 120, d: 0.05, vol: 0.5 }, roll: { type: "bandpass", f: 2800, q: 1.5, d: 0.03, vol: 0.25 }, ring: [{ f: 420, d: 0.25, vol: 0.16 }, { f: 1130, d: 0.18, vol: 0.09 }, { f: 2470, d: 0.1, vol: 0.04 }] },
|
|
318
|
+
water: { heel: { f: 70, d: 0.04, vol: 0.25 }, roll: { type: "bandpass", f: 3e3, q: 1.2, d: 0.1, vol: 0.18 }, splash: { f: 1100, f2: 380, d: 0.22, vol: 0.55 }, grains: { count: 4, f: 2400, q: 6, spread: 0.18, vol: 0.12 } },
|
|
319
|
+
glass: { heel: { f: 90, d: 0.04, vol: 0.4 }, roll: { type: "highpass", f: 4500, q: 0.8, d: 0.06, vol: 0.2 }, grains: { count: 9, f: 6200, q: 5, spread: 0.12, vol: 0.22 }, ring: [{ f: 3900, d: 0.04, vol: 0.04 }, { f: 5300, d: 0.03, vol: 0.03 }] },
|
|
320
|
+
carpet: { heel: { f: 70, d: 0.05, vol: 0.32 }, roll: { type: "lowpass", f: 420, q: 0.7, d: 0.07, vol: 0.3 } }
|
|
321
|
+
};
|
|
322
|
+
var GAITS = {
|
|
323
|
+
walk: { vol: 1, bright: 1, toe: 0.075, short: 1 },
|
|
324
|
+
run: { vol: 1.35, bright: 1.25, toe: 0.035, short: 0.75 }
|
|
325
|
+
};
|
|
326
|
+
var grainLayers = (g, take, start, scale) => Array.from(
|
|
327
|
+
{ length: g.count },
|
|
328
|
+
(_, i) => sceneNoise({ type: "bandpass", f: [g.f * take.f * 0.85, g.f * take.f * 1.15], q: g.q, d: [8e-3, 0.02], vol: g.vol * scale * take.v, delay: start + (i + 0.5) / g.count * g.spread * take.t })
|
|
329
|
+
);
|
|
330
|
+
var ringLayers = (rings, take, scale, at = 0) => rings.map((r) => sceneTone({ f: r.f * take.f, d: r.d * take.t, vol: r.vol * scale * take.v, delay: at }));
|
|
331
|
+
function footLayers(surface, take, gait, weight = 1) {
|
|
332
|
+
const s = SURFACES[surface];
|
|
333
|
+
const toe = gait.toe * take.t;
|
|
334
|
+
return [
|
|
335
|
+
sceneTone({ f: s.heel.f * take.f * weight ** -0.3, f2: s.heel.f * take.f * 0.6, d: s.heel.d * gait.short * take.t * weight ** 0.5, vol: s.heel.vol * gait.vol * take.v * weight ** 0.5 }),
|
|
336
|
+
sceneNoise({ type: "lowpass", f: 500 * gait.bright, d: 0.02 * take.t, vol: 0.18 * gait.vol * take.v * weight ** 0.5 }),
|
|
337
|
+
sceneNoise({ type: s.roll.type, f: [s.roll.f * take.f * gait.bright * 0.92, s.roll.f * take.f * gait.bright * 1.08], q: s.roll.q, d: s.roll.d * gait.short * take.t * weight ** 0.3, vol: s.roll.vol * gait.vol * take.v, delay: toe }),
|
|
338
|
+
...s.grains ? grainLayers(s.grains, take, toe * 0.5, gait.vol * weight ** 0.5) : [],
|
|
339
|
+
...s.ring ? ringLayers(s.ring, take, gait.vol * weight ** 0.5) : [],
|
|
340
|
+
...s.splash ? [sceneNoise({ type: "bandpass", f: s.splash.f * take.f, f2: s.splash.f2 * take.f, q: 1.4, d: s.splash.d * take.t * weight ** 0.4, vol: s.splash.vol * gait.vol * take.v * weight ** 0.5 })] : []
|
|
341
|
+
];
|
|
342
|
+
}
|
|
343
|
+
var quieter = (level, layers) => layers.map((layer) => {
|
|
344
|
+
const gain = layer.gain ?? 1;
|
|
345
|
+
if (typeof gain === "number") return { ...layer, gain: gain * level };
|
|
346
|
+
if (Array.isArray(gain)) return { ...layer, gain: [gain[0] * level, gain[1] * level] };
|
|
347
|
+
return layer;
|
|
348
|
+
});
|
|
349
|
+
var recipe = (id, layers, falloff, bus = "world") => ({ id, bus, pan: true, layers, falloff, sources: ["sdk"] });
|
|
350
|
+
var takeId = (id, index) => `${id}_${String(index + 1).padStart(2, "0")}`;
|
|
351
|
+
function takes(id, layersOf, falloff, rate = [0.96, 1.04], bus) {
|
|
352
|
+
const sounds = TAKES.map((take, index) => recipe(takeId(id, index), layersOf(take, index), falloff, bus));
|
|
353
|
+
return { sounds, set: { id, variants: sounds.map((sound) => sound.id), rate } };
|
|
354
|
+
}
|
|
355
|
+
var footstep = (surface, gait) => takes(footstepSoundId(surface, gait), (take) => footLayers(surface, take, GAITS[gait]), FOOTSTEP_FALLOFF);
|
|
356
|
+
var LANDINGS = { light: { weight: 1.4, cloth: 0.12 }, heavy: { weight: 2.4, cloth: 0.22 } };
|
|
357
|
+
var LANDING_LEVEL = 0.65;
|
|
358
|
+
var landing = (surface, landing2) => takes(
|
|
359
|
+
`land_${surface}_${landing2}`,
|
|
360
|
+
(take) => quieter(LANDING_LEVEL, [
|
|
361
|
+
// both feet, a hair apart, then the knees taking the weight (a low body thump) and the clothes settling
|
|
362
|
+
...footLayers(surface, take, GAITS.run, LANDINGS[landing2].weight),
|
|
363
|
+
...footLayers(surface, { ...take, v: take.v * 0.6 }, GAITS.run, LANDINGS[landing2].weight * 0.6).map((layer) => ({ ...layer, at: (typeof layer.at === "number" ? layer.at : 0) + 0.018 * take.t })),
|
|
364
|
+
sceneTone({ f: 60 * take.f, f2: 38, d: 0.14 * LANDINGS[landing2].weight * take.t, vol: 0.22 * LANDINGS[landing2].weight ** 0.7 * take.v, delay: 0.02 }),
|
|
365
|
+
sceneNoise({ type: "bandpass", f: [1800, 2600], q: 0.8, d: 0.18, vol: LANDINGS[landing2].cloth * take.v, delay: 0.04 })
|
|
366
|
+
]),
|
|
367
|
+
FOOTSTEP_FALLOFF
|
|
368
|
+
);
|
|
369
|
+
var whoosh = (blow, from, to, d, vol, q = 1.6) => (take) => [
|
|
370
|
+
// the air: a band sweeping up as the limb speeds up; it peaks `SWING_LEAD_SECONDS` in, the moment before the contact, then dies away
|
|
371
|
+
sceneNoise({ type: "bandpass", f: from * take.f, f2: to * take.f, q, a: SWING_LEAD_SECONDS[blow], d: d * take.t, vol: vol * take.v }),
|
|
372
|
+
sceneNoise({ type: "lowpass", f: 600 * take.f, a: SWING_LEAD_SECONDS[blow], d: d * take.t * 0.8, vol: vol * 0.35 * take.v })
|
|
373
|
+
];
|
|
374
|
+
var fleshHit = (o) => (take) => [
|
|
375
|
+
sceneNoise({ type: "bandpass", f: o.slapF * take.f, q: 1.2, d: 0.03 * take.t, vol: o.slap * take.v }),
|
|
376
|
+
sceneNoise({ type: "highpass", f: 3500 * take.f, d: 0.012, vol: o.slap * 0.4 * take.v }),
|
|
377
|
+
sceneTone({ f: o.thudF * take.f, f2: o.thudF * 0.5, d: o.thudD * take.t, vol: o.thud * take.v }),
|
|
378
|
+
sceneNoise({ type: "lowpass", f: 600 * take.f, d: o.thudD * 1.2 * take.t, vol: o.thud * 0.5 * take.v }),
|
|
379
|
+
...o.crack ? [sceneNoise({ type: "highpass", f: 2500, d: 0.015, vol: o.crack * take.v, delay: 6e-3 }), sceneTone({ wave: "square", f: 900 * take.f, f2: 300, d: 0.02, vol: o.crack * 0.15 * take.v, delay: 6e-3 })] : [],
|
|
380
|
+
...o.wet ? [sceneNoise({ type: "bandpass", f: 1400 * take.f, f2: 500, q: 2.5, d: 0.12 * take.t, vol: o.wet * take.v, delay: 0.01 })] : []
|
|
381
|
+
];
|
|
382
|
+
var knock = (o) => (take) => [
|
|
383
|
+
sceneNoise({ type: "bandpass", f: o.clickF * take.f, q: 1.5, d: 0.018, vol: o.click * take.v }),
|
|
384
|
+
...o.tones.map(([f, d, vol]) => sceneTone({ f: f * take.f, d: d * take.t, vol: vol * take.v }))
|
|
385
|
+
];
|
|
386
|
+
var voice = (o) => (take) => [
|
|
387
|
+
sceneVoice({ f0: o.f0 * take.f, f1: o.f1 * take.f, d: o.d * take.t, fA: o.fA * take.f, fB: o.fB * take.f, noise: o.noise, vol: o.vol * take.v })
|
|
388
|
+
];
|
|
389
|
+
var BODY = {
|
|
390
|
+
jump: (take) => [
|
|
391
|
+
sceneNoise({ type: "bandpass", f: 900 * take.f, f2: 1700 * take.f, q: 1, a: 0.03, d: 0.12, vol: 0.18 * take.v }),
|
|
392
|
+
sceneNoise({ type: "bandpass", f: 2200 * take.f, q: 0.8, d: 0.04, vol: 0.12 * take.v }),
|
|
393
|
+
sceneTone({ f: 85 * take.f, f2: 60, d: 0.04, vol: 0.2 * take.v })
|
|
394
|
+
],
|
|
395
|
+
cloth_rustle: (take) => [
|
|
396
|
+
{ ...sceneNoise({ type: "bandpass", f: 2400 * take.f, q: 0.8, a: 0.06, d: 0.22 * take.t, vol: 0.12 * take.v }), modulators: [{ target: "gain", wave: "triangle", rate: [9, 14], depth: 0.5 }] }
|
|
397
|
+
],
|
|
398
|
+
body_fall: (take) => [
|
|
399
|
+
sceneTone({ f: 58 * take.f, f2: 35, d: 0.28 * take.t, vol: 0.9 * take.v }),
|
|
400
|
+
sceneNoise({ type: "lowpass", f: 480 * take.f, d: 0.3 * take.t, vol: 0.55 * take.v }),
|
|
401
|
+
sceneNoise({ type: "bandpass", f: 1300 * take.f, q: 1, d: 0.05, vol: 0.3 * take.v }),
|
|
402
|
+
// the limbs a moment later, and the clothes
|
|
403
|
+
sceneTone({ f: 75 * take.f, f2: 45, d: 0.12, vol: 0.4 * take.v, delay: 0.13 * take.t }),
|
|
404
|
+
sceneNoise({ type: "bandpass", f: 2200, q: 0.8, d: 0.2, vol: 0.12 * take.v, delay: 0.05 })
|
|
405
|
+
],
|
|
406
|
+
fall_damage: (take) => [
|
|
407
|
+
...BODY.body_fall(take),
|
|
408
|
+
sceneNoise({ type: "highpass", f: 2800, d: 0.02, vol: 0.35 * take.v, delay: 0.01 }),
|
|
409
|
+
...voice({ f0: 170, f1: 110, d: 0.32, fA: 650, fB: 1150, noise: 0.25, vol: 0.32 })(take).map((layer) => ({ ...layer, at: 0.08 }))
|
|
410
|
+
],
|
|
411
|
+
player_hurt: voice({ f0: 150, f1: 105, d: 0.26, fA: 620, fB: 1100, noise: 0.3, vol: 0.35 }),
|
|
412
|
+
player_breath_run: (take) => [
|
|
413
|
+
sceneNoise({ type: "bandpass", f: 1200 * take.f, q: 1, a: 0.08, d: 0.22 * take.t, vol: 0.25 * take.v }),
|
|
414
|
+
sceneNoise({ type: "bandpass", f: 900 * take.f, q: 1, a: 0.06, d: 0.26 * take.t, vol: 0.3 * take.v, delay: 0.3 * take.t })
|
|
415
|
+
],
|
|
416
|
+
player_death: voice({ f0: 135, f1: 68, d: 1, fA: 560, fB: 980, noise: 0.35, vol: 0.4 }),
|
|
417
|
+
bite: (take) => [
|
|
418
|
+
sceneNoise({ type: "highpass", f: 2600, d: 0.015, vol: 0.4 * take.v }),
|
|
419
|
+
sceneNoise({ type: "bandpass", f: 1600 * take.f, f2: 450, q: 2.2, d: 0.16 * take.t, vol: 0.55 * take.v, delay: 0.01 }),
|
|
420
|
+
sceneNoise({ type: "bandpass", f: 3200 * take.f, f2: 1800, q: 1.2, d: 0.22 * take.t, vol: 0.25 * take.v, delay: 0.09 }),
|
|
421
|
+
sceneTone({ f: 120 * take.f, f2: 70, d: 0.06, vol: 0.3 * take.v })
|
|
422
|
+
],
|
|
423
|
+
grab: (take) => [
|
|
424
|
+
sceneNoise({ type: "bandpass", f: 1900 * take.f, q: 0.9, a: 4e-3, d: 0.13 * take.t, vol: 0.32 * take.v }),
|
|
425
|
+
sceneTone({ f: 95 * take.f, f2: 60, d: 0.07, vol: 0.3 * take.v }),
|
|
426
|
+
sceneNoise({ type: "lowpass", f: 700, d: 0.08, vol: 0.2 * take.v })
|
|
427
|
+
],
|
|
428
|
+
punch_swing: whoosh("punch", 450, 1500, 0.16, 0.9),
|
|
429
|
+
punch_hit_body: fleshHit({ slap: 0.55, slapF: 1500, thud: 0.6, thudF: 115, thudD: 0.09 }),
|
|
430
|
+
punch_hit_face: fleshHit({ slap: 0.75, slapF: 2300, thud: 0.45, thudF: 150, thudD: 0.07, crack: 0.25 }),
|
|
431
|
+
punch_hit_object: knock({ clickF: 1800, click: 0.3, tones: [[210, 0.04, 0.25]] }),
|
|
432
|
+
kick_swing: whoosh("kick", 280, 950, 0.22, 1, 1.3),
|
|
433
|
+
kick_hit: fleshHit({ slap: 0.45, slapF: 1100, thud: 0.85, thudF: 82, thudD: 0.14 }),
|
|
434
|
+
kick_hit_object: knock({ clickF: 1e3, click: 0.3, tones: [[92, 0.08, 0.5]] }),
|
|
435
|
+
shove_two_hands: (take) => [
|
|
436
|
+
sceneNoise({ type: "bandpass", f: 950 * take.f, q: 0.9, a: 0.01, d: 0.13 * take.t, vol: 0.38 * take.v }),
|
|
437
|
+
sceneTone({ f: 100 * take.f, f2: 60, d: 0.1 * take.t, vol: 0.45 * take.v }),
|
|
438
|
+
sceneNoise({ type: "bandpass", f: 2300, q: 0.8, d: 0.16, vol: 0.12 * take.v, delay: 0.03 })
|
|
439
|
+
],
|
|
440
|
+
knife_swing: whoosh("blade", 1900, 4600, 0.12, 1.1, 2.2),
|
|
441
|
+
knife_stab: fleshHit({ slap: 0.2, slapF: 1200, thud: 0.4, thudF: 160, thudD: 0.06, wet: 0.5 }),
|
|
442
|
+
knife_slash: (take) => [
|
|
443
|
+
sceneNoise({ type: "highpass", f: 3200 * take.f, f2: 1800, d: 0.13 * take.t, vol: 0.35 * take.v }),
|
|
444
|
+
sceneNoise({ type: "bandpass", f: 1300 * take.f, f2: 600, q: 2.5, d: 0.12 * take.t, vol: 0.35 * take.v, delay: 0.02 })
|
|
445
|
+
],
|
|
446
|
+
knife_hit_object: knock({ clickF: 3200, click: 0.25, tones: [[2800, 0.08, 0.07], [4150, 0.06, 0.05]] }),
|
|
447
|
+
blunt_swing: whoosh("blunt", 220, 760, 0.28, 1.1, 1.5),
|
|
448
|
+
blunt_hit: fleshHit({ slap: 0.35, slapF: 900, thud: 1, thudF: 70, thudD: 0.18, crack: 0.3 }),
|
|
449
|
+
blunt_hit_object: knock({ clickF: 1400, click: 0.35, tones: [[300, 0.12, 0.25], [760, 0.08, 0.12]] }),
|
|
450
|
+
axe_swing: whoosh("chop", 190, 620, 0.3, 1.2, 1.4),
|
|
451
|
+
axe_chop: fleshHit({ slap: 0.3, slapF: 1400, thud: 0.75, thudF: 140, thudD: 0.1, crack: 0.35, wet: 0.45 }),
|
|
452
|
+
axe_hit_object: knock({ clickF: 2200, click: 0.4, tones: [[1500, 0.15, 0.1], [2300, 0.1, 0.06], [140, 0.1, 0.35]] })
|
|
453
|
+
};
|
|
454
|
+
var BODY_BUS = { player_hurt: "voices", player_death: "voices", player_breath_run: "voices", fall_damage: "voices" };
|
|
455
|
+
var built = [
|
|
456
|
+
...SURFACE_IDS.flatMap((surface) => GAIT_IDS.map((gait) => footstep(surface, gait))),
|
|
457
|
+
...SURFACE_IDS.flatMap((surface) => LANDING_IDS.map((l) => landing(surface, l))),
|
|
458
|
+
...BODY_SOUND_IDS.map((id) => takes(id, BODY[id], BODY_FALLOFF, id.endsWith("_swing") ? [0.94, 1.06] : [0.96, 1.04], BODY_BUS[id]))
|
|
459
|
+
];
|
|
460
|
+
var BODY_FOLEY_BANK = {
|
|
461
|
+
id: "body_foley",
|
|
462
|
+
sounds: built.flatMap((entry) => entry.sounds),
|
|
463
|
+
sets: built.map((entry) => entry.set)
|
|
464
|
+
};
|
|
465
|
+
var BODY_FOLEY_SET_IDS = [...FOOTSTEP_SOUND_IDS, ...LAND_SOUND_IDS, ...BODY_SOUND_IDS];
|
|
466
|
+
|
|
467
|
+
// src/audio/recipes.ts
|
|
468
|
+
var call = (o) => ({
|
|
469
|
+
id: o.id,
|
|
470
|
+
bus: "world",
|
|
471
|
+
order: "calls",
|
|
472
|
+
duration: o.seconds,
|
|
473
|
+
tail: 0.02,
|
|
474
|
+
// the page makes its gain and filter before it looks at the level
|
|
475
|
+
keepSilent: true,
|
|
476
|
+
layers: [
|
|
477
|
+
{
|
|
478
|
+
repeat: { count: o.count, spacing: o.spacing },
|
|
479
|
+
source: { kind: "osc", wave: o.wave, frequency: { from: o.frequency, to: o.frequency * o.drop, curve: "exp", over: "duration" } },
|
|
480
|
+
filters: { mode: "serial", bank: [{ type: "bandpass", frequency: { set: o.frequency * 1.2 }, q: 3 }] },
|
|
481
|
+
envelope: [
|
|
482
|
+
[0, 1e-4, "set", "fixed"],
|
|
483
|
+
[0.015, 1, "exp"],
|
|
484
|
+
["1d", 1e-4, "exp", "fixed"]
|
|
485
|
+
]
|
|
486
|
+
}
|
|
487
|
+
],
|
|
488
|
+
falloff: DISTANCE_CURVES.animals,
|
|
489
|
+
sources: [`jogo:L66625-66639 bichoSom('${o.team}')`]
|
|
490
|
+
});
|
|
491
|
+
var DOG_BARK = call({ id: "dog_bark", team: "latido", count: 2, spacing: 0.22, seconds: 0.12, wave: "square", frequency: 520, drop: 0.6 });
|
|
492
|
+
var LAPWING_CALL = call({ id: "lapwing_call", team: "queroquero", count: 3, spacing: 0.14, seconds: 0.09, wave: "square", frequency: 2400, drop: 0.6 });
|
|
493
|
+
var HEN_CLUCK = call({ id: "hen_cluck", team: "cacarejo", count: 4, spacing: 0.14, seconds: 0.09, wave: "square", frequency: 900, drop: 0.6 });
|
|
494
|
+
var COW_MOO = call({ id: "cow_moo", team: "mugido", count: 1, spacing: 0.14, seconds: 1.2, wave: "sawtooth", frequency: 140, drop: 0.8 });
|
|
495
|
+
var ANIMAL_SOUNDS = [DOG_BARK, LAPWING_CALL, HEN_CLUCK, COW_MOO];
|
|
496
|
+
var ANIMAL_SOUND_BANK = { id: "animals_three", sounds: ANIMAL_SOUNDS };
|
|
497
|
+
|
|
498
|
+
// src/audio/calls.json
|
|
499
|
+
var calls_default = {
|
|
500
|
+
sources: [
|
|
501
|
+
"jogo:L66677 galinha: cacarejo, 6 s between calls, noise 30 m",
|
|
502
|
+
"jogo:L66680 quero-quero: queroquero when the player is near (alarme), 8 s, noise 40 m",
|
|
503
|
+
"jogo:L66681 vaca: mugido, 30 s, noise 80 m",
|
|
504
|
+
"jogo:L66683 cachorro: latido when a zombie is within 12 m, 3 s, noise 60 m"
|
|
505
|
+
],
|
|
506
|
+
species: {
|
|
507
|
+
chicken: { sound: "hen_cluck", cooldown: 6, noiseMetres: 30 },
|
|
508
|
+
southern_lapwing: { sound: "lapwing_call", cooldown: 8, noiseMetres: 40 },
|
|
509
|
+
cow: { sound: "cow_moo", cooldown: 30, noiseMetres: 80 },
|
|
510
|
+
dog: { sound: "dog_bark", cooldown: 3, noiseMetres: 60 }
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
// src/audio/sound.ts
|
|
515
|
+
var DATA = calls_default;
|
|
516
|
+
var ANIMAL_CALLS = DATA.species;
|
|
517
|
+
var ANIMAL_CALL_SOURCES = DATA.sources;
|
|
518
|
+
function createAnimalSound(sink, options = {}) {
|
|
519
|
+
sink.register?.(ANIMAL_SOUND_BANK);
|
|
520
|
+
const calls = { ...ANIMAL_CALLS, ...options.calls };
|
|
521
|
+
const waiting = /* @__PURE__ */ new Map();
|
|
522
|
+
const callOf = (speciesId) => calls[speciesId] ?? void 0;
|
|
523
|
+
return {
|
|
524
|
+
callOf,
|
|
525
|
+
call(speciesId, position, o = {}) {
|
|
526
|
+
const found = callOf(speciesId);
|
|
527
|
+
if (!found) return false;
|
|
528
|
+
const key = o.key ?? speciesId;
|
|
529
|
+
if ((waiting.get(key) ?? 0) > 0) return false;
|
|
530
|
+
waiting.set(key, found.cooldown);
|
|
531
|
+
sink.play({ sound: found.sound, position, ...o.volume === void 0 ? {} : { volume: o.volume } });
|
|
532
|
+
return true;
|
|
533
|
+
},
|
|
534
|
+
update(dt) {
|
|
535
|
+
for (const [key, seconds] of waiting) {
|
|
536
|
+
if (seconds - dt <= 0) waiting.delete(key);
|
|
537
|
+
else waiting.set(key, seconds - dt);
|
|
538
|
+
}
|
|
539
|
+
},
|
|
540
|
+
dispose: () => waiting.clear()
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// src/context.ts
|
|
545
|
+
var createStream = (seed) => {
|
|
546
|
+
let state = seed;
|
|
547
|
+
return () => {
|
|
548
|
+
state |= 0;
|
|
549
|
+
state = state + 1831565813 | 0;
|
|
550
|
+
let t = Math.imul(state ^ state >>> 15, 1 | state);
|
|
551
|
+
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
|
|
552
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
553
|
+
};
|
|
554
|
+
};
|
|
555
|
+
var addMesh = (THREE, parent, geometry, material, x, y, z, rx, ry, rz) => {
|
|
556
|
+
const mesh2 = new THREE.Mesh(geometry, material);
|
|
557
|
+
mesh2.position.set(x || 0, y || 0, z || 0);
|
|
558
|
+
if (rx || ry || rz) mesh2.rotation.set(rx || 0, ry || 0, rz || 0);
|
|
559
|
+
mesh2.castShadow = true;
|
|
560
|
+
mesh2.receiveShadow = true;
|
|
561
|
+
parent.add(mesh2);
|
|
562
|
+
return mesh2;
|
|
563
|
+
};
|
|
564
|
+
var createRigTools = (THREE, rig) => {
|
|
565
|
+
const tools = {
|
|
566
|
+
material(color2, extras) {
|
|
567
|
+
const material = new THREE.MeshStandardMaterial(Object.assign({ color: color2, roughness: 0.8, metalness: 0, flatShading: false }, extras || {}));
|
|
568
|
+
material.userData.base = material.color.clone();
|
|
569
|
+
rig.materials.push(material);
|
|
570
|
+
return material;
|
|
571
|
+
},
|
|
572
|
+
ball(parent, radius, material, x, y, z, sx, sy, sz) {
|
|
573
|
+
const mesh2 = addMesh(THREE, parent, new THREE.SphereGeometry(radius, 16, 12), material, x, y, z);
|
|
574
|
+
if (sx) mesh2.scale.set(sx, sy, sz);
|
|
575
|
+
return mesh2;
|
|
576
|
+
},
|
|
577
|
+
limb: (parent, radius1, radius2, length, material) => addMesh(THREE, parent, new THREE.CylinderGeometry(radius2, radius1, length, 14, 1).translate(0, -length / 2, 0), material),
|
|
578
|
+
joint(parent, radius, material, x, y, z) {
|
|
579
|
+
const joint = tools.ball(parent, radius, material, x, y, z);
|
|
580
|
+
joint.userData.joint = 1;
|
|
581
|
+
rig.joints.push(joint);
|
|
582
|
+
return joint;
|
|
583
|
+
},
|
|
584
|
+
pivot(parent, x, y, z, offset) {
|
|
585
|
+
const group = new THREE.Group();
|
|
586
|
+
group.position.set(x, y, z);
|
|
587
|
+
parent.add(group);
|
|
588
|
+
rig.pivots.push({ group, rest: group.position.clone(), offset: offset || new THREE.Vector3() });
|
|
589
|
+
return group;
|
|
590
|
+
},
|
|
591
|
+
eyes(head, radius, x, y, z) {
|
|
592
|
+
const eyeMaterial = tools.material(1118481, { roughness: 0.25 });
|
|
593
|
+
rig.eyeMaterial = eyeMaterial;
|
|
594
|
+
for (const side of [-1, 1]) rig.eyes.push(tools.ball(head, radius, eyeMaterial, side * x, y, z));
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
return tools;
|
|
598
|
+
};
|
|
599
|
+
var createRig = (THREE, species, options) => {
|
|
600
|
+
const rig = {
|
|
601
|
+
species,
|
|
602
|
+
root: new THREE.Group(),
|
|
603
|
+
trunk: new THREE.Group(),
|
|
604
|
+
materials: [],
|
|
605
|
+
joints: [],
|
|
606
|
+
pivots: [],
|
|
607
|
+
legs: [],
|
|
608
|
+
tail: [],
|
|
609
|
+
ears: [],
|
|
610
|
+
infectionParts: [],
|
|
611
|
+
eyes: [],
|
|
612
|
+
wings: [],
|
|
613
|
+
segments: [],
|
|
614
|
+
phase: options.phase,
|
|
615
|
+
size: 1,
|
|
616
|
+
segmentLength: 0,
|
|
617
|
+
segmentCount: 0,
|
|
618
|
+
home: new THREE.Vector3(),
|
|
619
|
+
infected: false,
|
|
620
|
+
dead: false,
|
|
621
|
+
neckAngle: 0,
|
|
622
|
+
headAngle: 0,
|
|
623
|
+
triangles: 0
|
|
624
|
+
};
|
|
625
|
+
rig.root.add(rig.trunk);
|
|
626
|
+
return rig;
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
// src/extras.ts
|
|
630
|
+
var cow = ({ THREE, tools }, k) => {
|
|
631
|
+
tools.ball(k.bodyGroup, 0.2, k.main, 0, k.Rb * 1.1, k.L * 0.33, 0.95, 1.1, 1.1);
|
|
632
|
+
tools.ball(k.neck, 0.13, k.main, 0, 0.12, 0.08, 0.55, 1.4, 1.05);
|
|
633
|
+
for (const side of [-1, 1]) addMesh(THREE, k.head, new THREE.ConeGeometry(0.025, 0.13, 8), tools.material(13616808), side * 0.12, k.hd.r * 1.05, k.hd.r * 0.05, 0, 0, side * -0.9);
|
|
634
|
+
};
|
|
635
|
+
var horse = ({ THREE, rig, tools }, k) => {
|
|
636
|
+
for (let index = 0; index < 9; index++) addMesh(THREE, k.neck, new THREE.BoxGeometry(0.035, 0.16, 0.08), k.dark, 0, 0.06 + index * 0.065, -0.12 + index * 4e-3, -0.25, 0, 0);
|
|
637
|
+
addMesh(THREE, k.head, new THREE.BoxGeometry(0.03, 0.12, 0.06), k.dark, 0, k.hd.r * 1.05, k.hd.r * 0.3, 0.6, 0, 0);
|
|
638
|
+
const last = rig.tail[rig.tail.length - 1];
|
|
639
|
+
tools.ball(last, 0.08, k.dark, 0, -0.42, 0, 0.7, 4.5, 0.7);
|
|
640
|
+
};
|
|
641
|
+
var wildBoar = ({ THREE, tools }, k) => {
|
|
642
|
+
for (let index = 0; index < 12; index++) addMesh(THREE, k.bodyGroup, new THREE.BoxGeometry(0.03, 0.1, 0.06), k.dark, 0, k.Rb * 1.12 - index * 4e-3, k.L * 0.38 - index * 0.06, -0.2, 0, 0);
|
|
643
|
+
for (const side of [-1, 1])
|
|
644
|
+
addMesh(THREE, k.head, new THREE.ConeGeometry(0.012, 0.09, 6), tools.material(15261900), side * 0.07, k.hd.r * -0.25 + 0.03, k.hd.r * 0.25 + k.hd.r * k.hd.s[2] * 0.55 + 0.13, -0.6, 0, side * 0.5);
|
|
645
|
+
};
|
|
646
|
+
var chicken = ({ tools }, k) => {
|
|
647
|
+
const red = tools.material(12593182);
|
|
648
|
+
for (let index = 0; index < 4; index++) tools.ball(k.head, 0.014, red, 0, 0.045, -0.012 + index * 0.014, 0.5, 1, 0.8);
|
|
649
|
+
tools.ball(k.head, 0.012, red, 0, -0.04, 0.04, 0.5, 1.3, 0.7);
|
|
650
|
+
};
|
|
651
|
+
var southernLapwing = ({ THREE, tools }, k) => {
|
|
652
|
+
const black = tools.material(1447446);
|
|
653
|
+
tools.ball(k.bodyGroup, 0.05, black, 0, 0.03, 0.08, 1.1, 0.9, 0.6);
|
|
654
|
+
addMesh(THREE, k.head, new THREE.BoxGeometry(6e-3, 6e-3, 0.06).translate(0, 0, -0.03), black, 0, 0.025, -0.01, 0.5, 0, 0);
|
|
655
|
+
tools.ball(k.head, 0.026, black, 0, -5e-3, 0.02, 1.05, 0.7, 0.9);
|
|
656
|
+
};
|
|
657
|
+
var QUADRUPED_EXTRAS = { cow, horse, wild_boar: wildBoar };
|
|
658
|
+
var BIRD_EXTRAS = { chicken, southern_lapwing: southernLapwing };
|
|
659
|
+
|
|
48
660
|
// ../game-animals/dist/index.js
|
|
49
661
|
var gaits_default = {
|
|
50
662
|
walk: [
|
|
@@ -92,16 +704,27 @@ var GameAnimalsThree = (() => {
|
|
|
92
704
|
return outcome === "dies" ? "dead" : "alive";
|
|
93
705
|
};
|
|
94
706
|
|
|
95
|
-
//
|
|
96
|
-
var
|
|
97
|
-
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
707
|
+
// src/line-up.ts
|
|
708
|
+
var lineUpAnimals = (rigs, options = {}) => {
|
|
709
|
+
const start = options.start ?? -19;
|
|
710
|
+
const gap = options.gap ?? 0.85;
|
|
711
|
+
let cursor = start;
|
|
712
|
+
for (const rig of rigs) {
|
|
713
|
+
const length = lineUpLength(rig.species.body);
|
|
714
|
+
cursor += length / 2;
|
|
715
|
+
rig.root.position.set(cursor, 0, 0);
|
|
716
|
+
rig.home = rig.root.position.clone();
|
|
717
|
+
rig.root.rotation.y = rig.species.body.kind === "snake" ? options.snakeYaw ?? 2.2 : options.yaw ?? 1.1;
|
|
718
|
+
cursor += length / 2 + gap;
|
|
719
|
+
}
|
|
720
|
+
const offset = -(cursor - gap + start) / 2;
|
|
721
|
+
for (const rig of rigs) {
|
|
722
|
+
rig.root.position.x += offset;
|
|
723
|
+
rig.home.x += offset;
|
|
724
|
+
}
|
|
725
|
+
};
|
|
103
726
|
|
|
104
|
-
// ../game-shapes/dist/chunk-
|
|
727
|
+
// ../game-shapes/dist/chunk-IFXQIDSA.js
|
|
105
728
|
function canonicalJson(value) {
|
|
106
729
|
if (value === null) return "null";
|
|
107
730
|
if (typeof value === "number") return Object.is(value, -0) ? "-0" : Number.isFinite(value) ? String(value) : JSON.stringify(String(value));
|
|
@@ -1396,10 +2019,10 @@ var GameAnimalsThree = (() => {
|
|
|
1396
2019
|
return cached;
|
|
1397
2020
|
}
|
|
1398
2021
|
stats.misses++;
|
|
1399
|
-
const
|
|
1400
|
-
templates.set(key,
|
|
2022
|
+
const built2 = make(node.kind, parameters);
|
|
2023
|
+
templates.set(key, built2);
|
|
1401
2024
|
if (templates.size > templateLimit) templates.delete(templates.keys().next().value);
|
|
1402
|
-
return
|
|
2025
|
+
return built2;
|
|
1403
2026
|
}
|
|
1404
2027
|
var num = (v) => typeof v === "number" && Number.isFinite(v) ? null : "expected a finite number";
|
|
1405
2028
|
var bool = (v) => typeof v === "boolean" ? null : "expected a boolean";
|
|
@@ -1702,6 +2325,134 @@ var GameAnimalsThree = (() => {
|
|
|
1702
2325
|
return releaseObject3D(list2, { keep });
|
|
1703
2326
|
}
|
|
1704
2327
|
|
|
2328
|
+
// src/profile.ts
|
|
2329
|
+
var profileGeometry = (THREE, length, profile, segments) => {
|
|
2330
|
+
const points = profile.map((radius, index) => new THREE.Vector2(index / (profile.length - 1), radius));
|
|
2331
|
+
const curve = new THREE.SplineCurve(points);
|
|
2332
|
+
const outline = [];
|
|
2333
|
+
outline.push(new THREE.Vector2(1e-3, -length / 2 - 0));
|
|
2334
|
+
for (let step = 0; step <= 30; step++) {
|
|
2335
|
+
const point = curve.getPoint(step / 30);
|
|
2336
|
+
outline.push(new THREE.Vector2(Math.max(1e-3, point.y), -length / 2 + point.x * length));
|
|
2337
|
+
}
|
|
2338
|
+
outline.push(new THREE.Vector2(1e-3, length / 2));
|
|
2339
|
+
return new (shapeGeometries(THREE)).LatheGeometry(outline, segments || 22).rotateX(Math.PI / 2);
|
|
2340
|
+
};
|
|
2341
|
+
|
|
2342
|
+
// src/textures.ts
|
|
2343
|
+
var canvasTexture = (THREE, document2, width, height, draw) => {
|
|
2344
|
+
const canvas = document2.createElement("canvas");
|
|
2345
|
+
canvas.width = width;
|
|
2346
|
+
canvas.height = height;
|
|
2347
|
+
draw(canvas.getContext("2d"), width, height);
|
|
2348
|
+
const texture = new THREE.CanvasTexture(canvas);
|
|
2349
|
+
texture.colorSpace = THREE.SRGBColorSpace;
|
|
2350
|
+
return texture;
|
|
2351
|
+
};
|
|
2352
|
+
var spotsTexture = (THREE, document2, base, spot) => canvasTexture(THREE, document2, 256, 256, (painter, width, height) => {
|
|
2353
|
+
painter.fillStyle = base;
|
|
2354
|
+
painter.fillRect(0, 0, width, height);
|
|
2355
|
+
const next = createStream(11);
|
|
2356
|
+
for (let index = 0; index < 70; index++) {
|
|
2357
|
+
const x = next() * width;
|
|
2358
|
+
const y = next() * height;
|
|
2359
|
+
const radius = 5 + next() * 7;
|
|
2360
|
+
painter.strokeStyle = spot;
|
|
2361
|
+
painter.lineWidth = 3;
|
|
2362
|
+
painter.beginPath();
|
|
2363
|
+
painter.arc(x, y, radius, 0, 7);
|
|
2364
|
+
painter.stroke();
|
|
2365
|
+
painter.fillStyle = "rgba(120,70,20,.45)";
|
|
2366
|
+
painter.beginPath();
|
|
2367
|
+
painter.arc(x, y, radius * 0.6, 0, 7);
|
|
2368
|
+
painter.fill();
|
|
2369
|
+
}
|
|
2370
|
+
for (let index = 0; index < 60; index++) {
|
|
2371
|
+
painter.fillStyle = spot;
|
|
2372
|
+
painter.beginPath();
|
|
2373
|
+
painter.arc(next() * width, next() * height, 1.5 + next() * 2.5, 0, 7);
|
|
2374
|
+
painter.fill();
|
|
2375
|
+
}
|
|
2376
|
+
});
|
|
2377
|
+
var stripesTexture = (THREE, document2, base, stripe) => canvasTexture(THREE, document2, 128, 128, (painter, width) => {
|
|
2378
|
+
painter.fillStyle = base;
|
|
2379
|
+
painter.fillRect(0, 0, width, 128);
|
|
2380
|
+
painter.fillStyle = stripe;
|
|
2381
|
+
for (let index = 0; index < 9; index++) painter.fillRect(0, index * 14 + index % 2 * 3, width, 4);
|
|
2382
|
+
});
|
|
2383
|
+
var createCoatTexture = (THREE, document2, marker) => marker.kind === "stripes" ? stripesTexture(THREE, document2, marker.base, marker.stripe) : spotsTexture(THREE, document2, marker.base, marker.spot);
|
|
2384
|
+
|
|
2385
|
+
// src/visual-state.ts
|
|
2386
|
+
var INFECTED_TINT = 8227430;
|
|
2387
|
+
var POOL_COLOR = 3803142;
|
|
2388
|
+
var applyVisualState = (THREE, rig, state) => {
|
|
2389
|
+
rig.infected = state === "infected";
|
|
2390
|
+
rig.dead = state === "dead";
|
|
2391
|
+
const tint = new THREE.Color(INFECTED_TINT);
|
|
2392
|
+
rig.materials.forEach((material) => {
|
|
2393
|
+
if (material === rig.eyeMaterial || material === rig.woundMaterial) return;
|
|
2394
|
+
material.color.copy(material.userData.base);
|
|
2395
|
+
if (rig.infected) material.color.lerp(tint, 0.45).multiplyScalar(0.72);
|
|
2396
|
+
});
|
|
2397
|
+
const eye = rig.eyeMaterial;
|
|
2398
|
+
if (eye) {
|
|
2399
|
+
if (rig.infected) {
|
|
2400
|
+
eye.color.set(14473392);
|
|
2401
|
+
eye.emissive = new THREE.Color(9078368);
|
|
2402
|
+
eye.emissiveIntensity = 0.8;
|
|
2403
|
+
} else {
|
|
2404
|
+
eye.color.copy(eye.userData.base);
|
|
2405
|
+
eye.emissive = new THREE.Color(0);
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
rig.infectionParts.forEach((part) => part.visible = rig.infected);
|
|
2409
|
+
const firstEar = rig.ears[0];
|
|
2410
|
+
if (firstEar) firstEar.visible = !rig.infected;
|
|
2411
|
+
if (!rig.dead) {
|
|
2412
|
+
rig.root.rotation.z = 0;
|
|
2413
|
+
rig.root.position.y = 0;
|
|
2414
|
+
}
|
|
2415
|
+
if (rig.pool) {
|
|
2416
|
+
rig.pool.visible = rig.dead;
|
|
2417
|
+
return;
|
|
2418
|
+
}
|
|
2419
|
+
if (!rig.dead) return;
|
|
2420
|
+
const pool = new THREE.Mesh(new THREE.CircleGeometry(1, 22).rotateX(-Math.PI / 2), new THREE.MeshStandardMaterial({ color: POOL_COLOR, roughness: 0.25 }));
|
|
2421
|
+
pool.position.set(rig.home.x, 5e-3, rig.home.z + 0.1);
|
|
2422
|
+
pool.receiveShadow = true;
|
|
2423
|
+
pool.scale.setScalar(rig.size * 0.45);
|
|
2424
|
+
rig.root.parent?.add(pool);
|
|
2425
|
+
rig.pool = pool;
|
|
2426
|
+
};
|
|
2427
|
+
|
|
2428
|
+
// src/views.ts
|
|
2429
|
+
var setJointView = (rig, on, jointMaterial) => {
|
|
2430
|
+
rig.materials.forEach((material) => {
|
|
2431
|
+
if (material === rig.eyeMaterial) return;
|
|
2432
|
+
material.transparent = on;
|
|
2433
|
+
material.opacity = on ? 0.28 : 1;
|
|
2434
|
+
material.depthWrite = !on;
|
|
2435
|
+
material.needsUpdate = true;
|
|
2436
|
+
});
|
|
2437
|
+
rig.joints.forEach((joint) => {
|
|
2438
|
+
var _a;
|
|
2439
|
+
if (on) (_a = joint.userData).restMaterial ?? (_a.restMaterial = joint.material);
|
|
2440
|
+
joint.material = on ? jointMaterial : joint.userData.restMaterial;
|
|
2441
|
+
joint.renderOrder = on ? 2 : 0;
|
|
2442
|
+
});
|
|
2443
|
+
};
|
|
2444
|
+
var setSplit = (rig, on) => {
|
|
2445
|
+
rig.pivots.forEach((pivot) => {
|
|
2446
|
+
pivot.group.userData.target = on ? pivot.rest.clone().add(pivot.offset) : pivot.rest.clone();
|
|
2447
|
+
});
|
|
2448
|
+
};
|
|
2449
|
+
var updateSplit = (rig, delta) => {
|
|
2450
|
+
rig.pivots.forEach((pivot) => {
|
|
2451
|
+
const target = pivot.group.userData.target;
|
|
2452
|
+
if (target) pivot.group.position.lerp(target, Math.min(1, delta * 5));
|
|
2453
|
+
});
|
|
2454
|
+
};
|
|
2455
|
+
|
|
1705
2456
|
// ../game-props3d/dist/index.js
|
|
1706
2457
|
var T = (id, interior, w, d, h, y, solid, group) => ({ id, interior, w, d, h, y, solid, group });
|
|
1707
2458
|
var TYPE_DEFS = [
|
|
@@ -2069,105 +2820,20 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2069
2820
|
for (let index = 0; index < rig.segmentCount; index++) {
|
|
2070
2821
|
const group = rig.segments[index].group;
|
|
2071
2822
|
group.position.copy(at(index));
|
|
2072
|
-
const direction = index === 0 ? at(0).clone().sub(at(1)) : at(index - 1).clone().sub(at(index));
|
|
2073
|
-
group.rotation.set(0, Math.atan2(direction.x, direction.z), 0);
|
|
2074
|
-
group.rotateX(-Math.atan2(direction.y, Math.hypot(direction.x, direction.z)));
|
|
2075
|
-
}
|
|
2076
|
-
const head = rig.head;
|
|
2077
|
-
const headDirection = at(0).clone().sub(at(1)).normalize();
|
|
2078
|
-
head.position.copy(at(0)).addScaledVector(headDirection, 0.02);
|
|
2079
|
-
head.rotation.set(0, Math.atan2(headDirection.x, headDirection.z), 0);
|
|
2080
|
-
head.rotateX(-Math.atan2(headDirection.y, Math.hypot(headDirection.x, headDirection.z)) * 0.5);
|
|
2081
|
-
const jaw = rig.jaw;
|
|
2082
|
-
jaw.rotation.x = clip === "run" ? Math.max(0, Math.sin(t * 2.2)) ** 6 * 0.9 : 0;
|
|
2083
|
-
const tongue = rig.tongue;
|
|
2084
|
-
tongue.visible = Math.sin(t * 5) > 0.3;
|
|
2085
|
-
tongue.scale.z = 1 + Math.sin(t * 20) * 0.3;
|
|
2086
|
-
};
|
|
2087
|
-
|
|
2088
|
-
// src/context.ts
|
|
2089
|
-
var createStream = (seed) => {
|
|
2090
|
-
let state = seed;
|
|
2091
|
-
return () => {
|
|
2092
|
-
state |= 0;
|
|
2093
|
-
state = state + 1831565813 | 0;
|
|
2094
|
-
let t = Math.imul(state ^ state >>> 15, 1 | state);
|
|
2095
|
-
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
|
|
2096
|
-
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
2097
|
-
};
|
|
2098
|
-
};
|
|
2099
|
-
var addMesh = (THREE, parent, geometry, material, x, y, z, rx, ry, rz) => {
|
|
2100
|
-
const mesh2 = new THREE.Mesh(geometry, material);
|
|
2101
|
-
mesh2.position.set(x || 0, y || 0, z || 0);
|
|
2102
|
-
if (rx || ry || rz) mesh2.rotation.set(rx || 0, ry || 0, rz || 0);
|
|
2103
|
-
mesh2.castShadow = true;
|
|
2104
|
-
mesh2.receiveShadow = true;
|
|
2105
|
-
parent.add(mesh2);
|
|
2106
|
-
return mesh2;
|
|
2107
|
-
};
|
|
2108
|
-
var createRigTools = (THREE, rig) => {
|
|
2109
|
-
const tools = {
|
|
2110
|
-
material(color2, extras) {
|
|
2111
|
-
const material = new THREE.MeshStandardMaterial(Object.assign({ color: color2, roughness: 0.8, metalness: 0, flatShading: false }, extras || {}));
|
|
2112
|
-
material.userData.base = material.color.clone();
|
|
2113
|
-
rig.materials.push(material);
|
|
2114
|
-
return material;
|
|
2115
|
-
},
|
|
2116
|
-
ball(parent, radius, material, x, y, z, sx, sy, sz) {
|
|
2117
|
-
const mesh2 = addMesh(THREE, parent, new THREE.SphereGeometry(radius, 16, 12), material, x, y, z);
|
|
2118
|
-
if (sx) mesh2.scale.set(sx, sy, sz);
|
|
2119
|
-
return mesh2;
|
|
2120
|
-
},
|
|
2121
|
-
limb: (parent, radius1, radius2, length, material) => addMesh(THREE, parent, new THREE.CylinderGeometry(radius2, radius1, length, 14, 1).translate(0, -length / 2, 0), material),
|
|
2122
|
-
joint(parent, radius, material, x, y, z) {
|
|
2123
|
-
const joint = tools.ball(parent, radius, material, x, y, z);
|
|
2124
|
-
joint.userData.joint = 1;
|
|
2125
|
-
rig.joints.push(joint);
|
|
2126
|
-
return joint;
|
|
2127
|
-
},
|
|
2128
|
-
pivot(parent, x, y, z, offset) {
|
|
2129
|
-
const group = new THREE.Group();
|
|
2130
|
-
group.position.set(x, y, z);
|
|
2131
|
-
parent.add(group);
|
|
2132
|
-
rig.pivots.push({ group, rest: group.position.clone(), offset: offset || new THREE.Vector3() });
|
|
2133
|
-
return group;
|
|
2134
|
-
},
|
|
2135
|
-
eyes(head, radius, x, y, z) {
|
|
2136
|
-
const eyeMaterial = tools.material(1118481, { roughness: 0.25 });
|
|
2137
|
-
rig.eyeMaterial = eyeMaterial;
|
|
2138
|
-
for (const side of [-1, 1]) rig.eyes.push(tools.ball(head, radius, eyeMaterial, side * x, y, z));
|
|
2139
|
-
}
|
|
2140
|
-
};
|
|
2141
|
-
return tools;
|
|
2142
|
-
};
|
|
2143
|
-
var createRig = (THREE, species, options) => {
|
|
2144
|
-
const rig = {
|
|
2145
|
-
species,
|
|
2146
|
-
root: new THREE.Group(),
|
|
2147
|
-
trunk: new THREE.Group(),
|
|
2148
|
-
materials: [],
|
|
2149
|
-
joints: [],
|
|
2150
|
-
pivots: [],
|
|
2151
|
-
legs: [],
|
|
2152
|
-
tail: [],
|
|
2153
|
-
ears: [],
|
|
2154
|
-
infectionParts: [],
|
|
2155
|
-
eyes: [],
|
|
2156
|
-
wings: [],
|
|
2157
|
-
segments: [],
|
|
2158
|
-
phase: options.phase,
|
|
2159
|
-
size: 1,
|
|
2160
|
-
segmentLength: 0,
|
|
2161
|
-
segmentCount: 0,
|
|
2162
|
-
home: new THREE.Vector3(),
|
|
2163
|
-
infected: false,
|
|
2164
|
-
dead: false,
|
|
2165
|
-
neckAngle: 0,
|
|
2166
|
-
headAngle: 0,
|
|
2167
|
-
triangles: 0
|
|
2168
|
-
};
|
|
2169
|
-
rig.root.add(rig.trunk);
|
|
2170
|
-
return rig;
|
|
2823
|
+
const direction = index === 0 ? at(0).clone().sub(at(1)) : at(index - 1).clone().sub(at(index));
|
|
2824
|
+
group.rotation.set(0, Math.atan2(direction.x, direction.z), 0);
|
|
2825
|
+
group.rotateX(-Math.atan2(direction.y, Math.hypot(direction.x, direction.z)));
|
|
2826
|
+
}
|
|
2827
|
+
const head = rig.head;
|
|
2828
|
+
const headDirection = at(0).clone().sub(at(1)).normalize();
|
|
2829
|
+
head.position.copy(at(0)).addScaledVector(headDirection, 0.02);
|
|
2830
|
+
head.rotation.set(0, Math.atan2(headDirection.x, headDirection.z), 0);
|
|
2831
|
+
head.rotateX(-Math.atan2(headDirection.y, Math.hypot(headDirection.x, headDirection.z)) * 0.5);
|
|
2832
|
+
const jaw = rig.jaw;
|
|
2833
|
+
jaw.rotation.x = clip === "run" ? Math.max(0, Math.sin(t * 2.2)) ** 6 * 0.9 : 0;
|
|
2834
|
+
const tongue = rig.tongue;
|
|
2835
|
+
tongue.visible = Math.sin(t * 5) > 0.3;
|
|
2836
|
+
tongue.scale.z = 1 + Math.sin(t * 20) * 0.3;
|
|
2171
2837
|
};
|
|
2172
2838
|
|
|
2173
2839
|
// src/bird.ts
|
|
@@ -2254,94 +2920,6 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2254
2920
|
return rig;
|
|
2255
2921
|
};
|
|
2256
2922
|
|
|
2257
|
-
// src/extras.ts
|
|
2258
|
-
var cow = ({ THREE, tools }, k) => {
|
|
2259
|
-
tools.ball(k.bodyGroup, 0.2, k.main, 0, k.Rb * 1.1, k.L * 0.33, 0.95, 1.1, 1.1);
|
|
2260
|
-
tools.ball(k.neck, 0.13, k.main, 0, 0.12, 0.08, 0.55, 1.4, 1.05);
|
|
2261
|
-
for (const side of [-1, 1]) addMesh(THREE, k.head, new THREE.ConeGeometry(0.025, 0.13, 8), tools.material(13616808), side * 0.12, k.hd.r * 1.05, k.hd.r * 0.05, 0, 0, side * -0.9);
|
|
2262
|
-
};
|
|
2263
|
-
var horse = ({ THREE, rig, tools }, k) => {
|
|
2264
|
-
for (let index = 0; index < 9; index++) addMesh(THREE, k.neck, new THREE.BoxGeometry(0.035, 0.16, 0.08), k.dark, 0, 0.06 + index * 0.065, -0.12 + index * 4e-3, -0.25, 0, 0);
|
|
2265
|
-
addMesh(THREE, k.head, new THREE.BoxGeometry(0.03, 0.12, 0.06), k.dark, 0, k.hd.r * 1.05, k.hd.r * 0.3, 0.6, 0, 0);
|
|
2266
|
-
const last = rig.tail[rig.tail.length - 1];
|
|
2267
|
-
tools.ball(last, 0.08, k.dark, 0, -0.42, 0, 0.7, 4.5, 0.7);
|
|
2268
|
-
};
|
|
2269
|
-
var wildBoar = ({ THREE, tools }, k) => {
|
|
2270
|
-
for (let index = 0; index < 12; index++) addMesh(THREE, k.bodyGroup, new THREE.BoxGeometry(0.03, 0.1, 0.06), k.dark, 0, k.Rb * 1.12 - index * 4e-3, k.L * 0.38 - index * 0.06, -0.2, 0, 0);
|
|
2271
|
-
for (const side of [-1, 1])
|
|
2272
|
-
addMesh(THREE, k.head, new THREE.ConeGeometry(0.012, 0.09, 6), tools.material(15261900), side * 0.07, k.hd.r * -0.25 + 0.03, k.hd.r * 0.25 + k.hd.r * k.hd.s[2] * 0.55 + 0.13, -0.6, 0, side * 0.5);
|
|
2273
|
-
};
|
|
2274
|
-
var chicken = ({ tools }, k) => {
|
|
2275
|
-
const red = tools.material(12593182);
|
|
2276
|
-
for (let index = 0; index < 4; index++) tools.ball(k.head, 0.014, red, 0, 0.045, -0.012 + index * 0.014, 0.5, 1, 0.8);
|
|
2277
|
-
tools.ball(k.head, 0.012, red, 0, -0.04, 0.04, 0.5, 1.3, 0.7);
|
|
2278
|
-
};
|
|
2279
|
-
var southernLapwing = ({ THREE, tools }, k) => {
|
|
2280
|
-
const black = tools.material(1447446);
|
|
2281
|
-
tools.ball(k.bodyGroup, 0.05, black, 0, 0.03, 0.08, 1.1, 0.9, 0.6);
|
|
2282
|
-
addMesh(THREE, k.head, new THREE.BoxGeometry(6e-3, 6e-3, 0.06).translate(0, 0, -0.03), black, 0, 0.025, -0.01, 0.5, 0, 0);
|
|
2283
|
-
tools.ball(k.head, 0.026, black, 0, -5e-3, 0.02, 1.05, 0.7, 0.9);
|
|
2284
|
-
};
|
|
2285
|
-
var QUADRUPED_EXTRAS = { cow, horse, wild_boar: wildBoar };
|
|
2286
|
-
var BIRD_EXTRAS = { chicken, southern_lapwing: southernLapwing };
|
|
2287
|
-
|
|
2288
|
-
// src/textures.ts
|
|
2289
|
-
var canvasTexture = (THREE, document2, width, height, draw) => {
|
|
2290
|
-
const canvas = document2.createElement("canvas");
|
|
2291
|
-
canvas.width = width;
|
|
2292
|
-
canvas.height = height;
|
|
2293
|
-
draw(canvas.getContext("2d"), width, height);
|
|
2294
|
-
const texture = new THREE.CanvasTexture(canvas);
|
|
2295
|
-
texture.colorSpace = THREE.SRGBColorSpace;
|
|
2296
|
-
return texture;
|
|
2297
|
-
};
|
|
2298
|
-
var spotsTexture = (THREE, document2, base, spot) => canvasTexture(THREE, document2, 256, 256, (painter, width, height) => {
|
|
2299
|
-
painter.fillStyle = base;
|
|
2300
|
-
painter.fillRect(0, 0, width, height);
|
|
2301
|
-
const next = createStream(11);
|
|
2302
|
-
for (let index = 0; index < 70; index++) {
|
|
2303
|
-
const x = next() * width;
|
|
2304
|
-
const y = next() * height;
|
|
2305
|
-
const radius = 5 + next() * 7;
|
|
2306
|
-
painter.strokeStyle = spot;
|
|
2307
|
-
painter.lineWidth = 3;
|
|
2308
|
-
painter.beginPath();
|
|
2309
|
-
painter.arc(x, y, radius, 0, 7);
|
|
2310
|
-
painter.stroke();
|
|
2311
|
-
painter.fillStyle = "rgba(120,70,20,.45)";
|
|
2312
|
-
painter.beginPath();
|
|
2313
|
-
painter.arc(x, y, radius * 0.6, 0, 7);
|
|
2314
|
-
painter.fill();
|
|
2315
|
-
}
|
|
2316
|
-
for (let index = 0; index < 60; index++) {
|
|
2317
|
-
painter.fillStyle = spot;
|
|
2318
|
-
painter.beginPath();
|
|
2319
|
-
painter.arc(next() * width, next() * height, 1.5 + next() * 2.5, 0, 7);
|
|
2320
|
-
painter.fill();
|
|
2321
|
-
}
|
|
2322
|
-
});
|
|
2323
|
-
var stripesTexture = (THREE, document2, base, stripe) => canvasTexture(THREE, document2, 128, 128, (painter, width) => {
|
|
2324
|
-
painter.fillStyle = base;
|
|
2325
|
-
painter.fillRect(0, 0, width, 128);
|
|
2326
|
-
painter.fillStyle = stripe;
|
|
2327
|
-
for (let index = 0; index < 9; index++) painter.fillRect(0, index * 14 + index % 2 * 3, width, 4);
|
|
2328
|
-
});
|
|
2329
|
-
var createCoatTexture = (THREE, document2, marker) => marker.kind === "stripes" ? stripesTexture(THREE, document2, marker.base, marker.stripe) : spotsTexture(THREE, document2, marker.base, marker.spot);
|
|
2330
|
-
|
|
2331
|
-
// src/profile.ts
|
|
2332
|
-
var profileGeometry = (THREE, length, profile, segments) => {
|
|
2333
|
-
const points = profile.map((radius, index) => new THREE.Vector2(index / (profile.length - 1), radius));
|
|
2334
|
-
const curve = new THREE.SplineCurve(points);
|
|
2335
|
-
const outline = [];
|
|
2336
|
-
outline.push(new THREE.Vector2(1e-3, -length / 2 - 0));
|
|
2337
|
-
for (let step = 0; step <= 30; step++) {
|
|
2338
|
-
const point = curve.getPoint(step / 30);
|
|
2339
|
-
outline.push(new THREE.Vector2(Math.max(1e-3, point.y), -length / 2 + point.x * length));
|
|
2340
|
-
}
|
|
2341
|
-
outline.push(new THREE.Vector2(1e-3, length / 2));
|
|
2342
|
-
return new (shapeGeometries(THREE)).LatheGeometry(outline, segments || 22).rotateX(Math.PI / 2);
|
|
2343
|
-
};
|
|
2344
|
-
|
|
2345
2923
|
// src/quadruped.ts
|
|
2346
2924
|
var RIB_COUNT = 4;
|
|
2347
2925
|
var LEG_DEFINITIONS = [
|
|
@@ -2535,305 +3113,263 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2535
3113
|
tools.eyes(head, 6e-3, 0.03, 0.04, 0.045);
|
|
2536
3114
|
rig.tongue = addMesh(THREE, head, new THREE.BoxGeometry(4e-3, 2e-3, 0.05), tools.material(11542560), 0, 0.024, 0.1);
|
|
2537
3115
|
return rig;
|
|
2538
|
-
};
|
|
2539
|
-
|
|
2540
|
-
// src/
|
|
2541
|
-
var
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
const
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
} else {
|
|
2559
|
-
eye.color.copy(eye.userData.base);
|
|
2560
|
-
eye.emissive = new THREE.Color(0);
|
|
2561
|
-
}
|
|
2562
|
-
}
|
|
2563
|
-
rig.infectionParts.forEach((part) => part.visible = rig.infected);
|
|
2564
|
-
const firstEar = rig.ears[0];
|
|
2565
|
-
if (firstEar) firstEar.visible = !rig.infected;
|
|
2566
|
-
if (!rig.dead) {
|
|
2567
|
-
rig.root.rotation.z = 0;
|
|
2568
|
-
rig.root.position.y = 0;
|
|
2569
|
-
}
|
|
2570
|
-
if (rig.pool) {
|
|
2571
|
-
rig.pool.visible = rig.dead;
|
|
2572
|
-
return;
|
|
2573
|
-
}
|
|
2574
|
-
if (!rig.dead) return;
|
|
2575
|
-
const pool = new THREE.Mesh(new THREE.CircleGeometry(1, 22).rotateX(-Math.PI / 2), new THREE.MeshStandardMaterial({ color: POOL_COLOR, roughness: 0.25 }));
|
|
2576
|
-
pool.position.set(rig.home.x, 5e-3, rig.home.z + 0.1);
|
|
2577
|
-
pool.receiveShadow = true;
|
|
2578
|
-
pool.scale.setScalar(rig.size * 0.45);
|
|
2579
|
-
rig.root.parent?.add(pool);
|
|
2580
|
-
rig.pool = pool;
|
|
2581
|
-
};
|
|
2582
|
-
|
|
2583
|
-
// src/views.ts
|
|
2584
|
-
var setJointView = (rig, on, jointMaterial) => {
|
|
2585
|
-
rig.materials.forEach((material) => {
|
|
2586
|
-
if (material === rig.eyeMaterial) return;
|
|
2587
|
-
material.transparent = on;
|
|
2588
|
-
material.opacity = on ? 0.28 : 1;
|
|
2589
|
-
material.depthWrite = !on;
|
|
2590
|
-
material.needsUpdate = true;
|
|
2591
|
-
});
|
|
2592
|
-
rig.joints.forEach((joint) => {
|
|
2593
|
-
var _a;
|
|
2594
|
-
if (on) (_a = joint.userData).restMaterial ?? (_a.restMaterial = joint.material);
|
|
2595
|
-
joint.material = on ? jointMaterial : joint.userData.restMaterial;
|
|
2596
|
-
joint.renderOrder = on ? 2 : 0;
|
|
2597
|
-
});
|
|
2598
|
-
};
|
|
2599
|
-
var setSplit = (rig, on) => {
|
|
2600
|
-
rig.pivots.forEach((pivot) => {
|
|
2601
|
-
pivot.group.userData.target = on ? pivot.rest.clone().add(pivot.offset) : pivot.rest.clone();
|
|
2602
|
-
});
|
|
2603
|
-
};
|
|
2604
|
-
var updateSplit = (rig, delta) => {
|
|
2605
|
-
rig.pivots.forEach((pivot) => {
|
|
2606
|
-
const target = pivot.group.userData.target;
|
|
2607
|
-
if (target) pivot.group.position.lerp(target, Math.min(1, delta * 5));
|
|
2608
|
-
});
|
|
2609
|
-
};
|
|
2610
|
-
|
|
2611
|
-
// ../game-audio/dist/index.js
|
|
2612
|
-
var DISTANCE_CURVES = {
|
|
2613
|
-
/** The game's `sfx`: `vol / (1 + d² × 0.004)`, cutoff `/ (1 + d × 0.01)`, silent below 0.01 (jogo L62091–62092, L62101). */
|
|
2614
|
-
game_sfx: { model: "inverse_square", k: 4e-3, cutoffK: 0.01, minGain: 0.01 },
|
|
2615
|
-
/** The game's `grito`: `1 / (1 + d² × 0.006)`, silent below 0.02 (jogo L62129–62130). */
|
|
2616
|
-
game_scream: { model: "inverse_square", k: 6e-3, minGain: 0.02 },
|
|
2617
|
-
/** The game's `voz`: `1 / (1 + d² × 0.01)`, silent below 0.02 (jogo L62146–62147). */
|
|
2618
|
-
game_voice: { model: "inverse_square", k: 0.01, minGain: 0.02 },
|
|
2619
|
-
/** The game's `boom`: `1.4 / (1 + d² × 0.002)`, never silent (jogo L68280). */
|
|
2620
|
-
game_boom: { model: "inverse_square", k: 2e-3, scale: 1.4 },
|
|
2621
|
-
/** The art scene's `outAt`: `vol / (1 + d² × 0.008)` (cena L1320). */
|
|
2622
|
-
art_scene: { model: "inverse_square", k: 8e-3 },
|
|
2623
|
-
/** The game's animal calls: `max(0, 1 − d / 70) × 0.25`, silent at or below 0.005 (jogo L66627–66628). */
|
|
2624
|
-
animals: { model: "linear", range: 70, scale: 0.25, minGain: 5e-3 }
|
|
2625
|
-
};
|
|
2626
|
-
var mix_profiles_default = [
|
|
2627
|
-
{
|
|
2628
|
-
id: "game",
|
|
2629
|
-
master: 0.5,
|
|
2630
|
-
noise: { seconds: 1.5, create: "lazy" },
|
|
2631
|
-
sources: ["jogo:L62077-62081 master 0.5 to the output", "jogo:L62082-62088 noise 1.5 s made by the first sound that needs it"]
|
|
2632
|
-
},
|
|
2633
|
-
{
|
|
2634
|
-
id: "art_scene",
|
|
2635
|
-
master: 0.85,
|
|
2636
|
-
compressor: { threshold: -12, ratio: 5 },
|
|
2637
|
-
reverb: { seconds: 2.2, decay: 3.4, wet: 0.4 },
|
|
2638
|
-
noise: { seconds: 2, create: "eager" },
|
|
2639
|
-
sources: [
|
|
2640
|
-
"cena:L1308 compressor -12 dB, ratio 5",
|
|
2641
|
-
"cena:L1309 master 0.85",
|
|
2642
|
-
"cena:L1310 convolver, impulse 2.2 s of (1 - i/len)^3.4",
|
|
2643
|
-
"cena:L1311 wet 0.4",
|
|
2644
|
-
"cena:L1312 noise 2 s made with the chain"
|
|
2645
|
-
]
|
|
2646
|
-
}
|
|
2647
|
-
];
|
|
2648
|
-
var MIX_PROFILES = Object.fromEntries(
|
|
2649
|
-
mix_profiles_default.map((profile) => [profile.id, profile])
|
|
2650
|
-
);
|
|
2651
|
-
var game_sfx_default = {
|
|
2652
|
-
sources: ["jogo:L62089-62107"],
|
|
2653
|
-
note: "The game's sfx table P: [lowpass cutoff Hz, peak gain, seconds]. Played as a noise burst with the game's distance curve (falloff game_sfx) and a 0.05 s tail. Team names in `team`.",
|
|
2654
|
-
classes: [
|
|
2655
|
-
{ id: "pistol", team: "pistola", bus: "weapons", cutoff: 1800, gain: 0.9, seconds: 0.18 },
|
|
2656
|
-
{ id: "shotgun", team: "escopeta", bus: "weapons", cutoff: 900, gain: 1.2, seconds: 0.35 },
|
|
2657
|
-
{ id: "rifle", team: "fuzil", bus: "weapons", cutoff: 1400, gain: 1.1, seconds: 0.28 },
|
|
2658
|
-
{ id: "long_rifle", team: "rifle", bus: "weapons", cutoff: 1100, gain: 1.3, seconds: 0.45 },
|
|
2659
|
-
{ id: "impact", team: "impacto", bus: "world", cutoff: 2500, gain: 0.25, seconds: 0.05 },
|
|
2660
|
-
{ id: "flesh", team: "carne", bus: "world", cutoff: 600, gain: 0.35, seconds: 0.08 },
|
|
2661
|
-
{ id: "step", team: "passo", bus: "world", cutoff: 400, gain: 0.08, seconds: 0.05 },
|
|
2662
|
-
{ id: "glass", team: "vidro", bus: "world", cutoff: 5e3, gain: 0.5, seconds: 0.3 },
|
|
2663
|
-
{ id: "wood", team: "madeira", bus: "world", cutoff: 700, gain: 0.5, seconds: 0.2 },
|
|
2664
|
-
{ id: "reload", team: "recarga", bus: "weapons", cutoff: 3e3, gain: 0.15, seconds: 0.06 },
|
|
2665
|
-
{ id: "empty", team: "vazio", bus: "weapons", cutoff: 4e3, gain: 0.12, seconds: 0.03 },
|
|
2666
|
-
{ id: "explosion", team: "explosao", bus: "world", cutoff: 200, gain: 1.6, seconds: 1.4 }
|
|
2667
|
-
],
|
|
2668
|
-
fallback: { id: "unknown", team: "(any other name)", bus: "world", cutoff: 1e3, gain: 0.5, seconds: 0.1 }
|
|
2669
|
-
};
|
|
2670
|
-
var GAME_SFX = game_sfx_default;
|
|
2671
|
-
var GAME_SFX_CLASSES = GAME_SFX.classes;
|
|
2672
|
-
var GAME_SFX_FALLBACK = GAME_SFX.fallback;
|
|
2673
|
-
function noiseClassRecipe(row, id = `sfx_${row.id}`) {
|
|
2674
|
-
return {
|
|
2675
|
-
id,
|
|
2676
|
-
bus: row.bus,
|
|
2677
|
-
order: "burst",
|
|
2678
|
-
duration: row.seconds,
|
|
2679
|
-
tail: 0.05,
|
|
2680
|
-
layers: [
|
|
2681
|
-
{
|
|
2682
|
-
source: { kind: "noise", offset: "random" },
|
|
2683
|
-
filters: { mode: "serial", bank: [{ type: "lowpass", frequency: { set: row.cutoff } }] },
|
|
2684
|
-
envelope: [
|
|
2685
|
-
[0, row.gain, "set"],
|
|
2686
|
-
["1d", 1e-3, "exp", "fixed"]
|
|
2687
|
-
]
|
|
2688
|
-
}
|
|
2689
|
-
],
|
|
2690
|
-
falloff: DISTANCE_CURVES.game_sfx,
|
|
2691
|
-
sources: [...GAME_SFX.sources.map((source) => `${source} ${row.team}`)]
|
|
3116
|
+
};
|
|
3117
|
+
|
|
3118
|
+
// src/animals-three.ts
|
|
3119
|
+
var countTriangles = (root) => {
|
|
3120
|
+
let triangles = 0;
|
|
3121
|
+
root.traverse((object2) => {
|
|
3122
|
+
const mesh2 = object2;
|
|
3123
|
+
if (!mesh2.isMesh) return;
|
|
3124
|
+
const geometry = mesh2.geometry;
|
|
3125
|
+
triangles += geometry.index ? geometry.index.count / 3 : geometry.attributes.position.count / 3;
|
|
3126
|
+
});
|
|
3127
|
+
return Math.round(triangles);
|
|
3128
|
+
};
|
|
3129
|
+
var createAnimalsThree = (host, options = {}) => {
|
|
3130
|
+
const THREE = shapeGeometries(host);
|
|
3131
|
+
const random = options.random ?? createStream(options.seed ?? 7);
|
|
3132
|
+
const documentOf = () => {
|
|
3133
|
+
const found = options.document ?? globalThis.document;
|
|
3134
|
+
if (!found) throw new Error("game-animals-three: a species with a coat texture needs `options.document` (no global document found)");
|
|
3135
|
+
return found;
|
|
2692
3136
|
};
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
envelope: [
|
|
2709
|
-
[0, 1e-4, "set", "fixed"],
|
|
2710
|
-
[2e-3, 1, "exp"],
|
|
2711
|
-
["1d", 1e-4, "exp", "fixed"]
|
|
2712
|
-
]
|
|
2713
|
-
}
|
|
2714
|
-
],
|
|
2715
|
-
falloff: DISTANCE_CURVES.art_scene,
|
|
2716
|
-
sources: ["sdk: bench probe, a 880 Hz ping through the art scene output stage"]
|
|
3137
|
+
const jointMaterial = new THREE.MeshStandardMaterial({ color: 14722376, emissive: 14722376, emissiveIntensity: 0.8, roughness: 0.4 });
|
|
3138
|
+
const gaits = GAIT_PHASES;
|
|
3139
|
+
return {
|
|
3140
|
+
jointMaterial,
|
|
3141
|
+
build(species, buildOptions = {}) {
|
|
3142
|
+
const rig = createRig(THREE, species, { phase: buildOptions.phase ?? random() * 6 });
|
|
3143
|
+
if (species.body.kind === "snake") buildSnake(THREE, rig);
|
|
3144
|
+
else if (species.body.kind === "bird") buildBird(THREE, rig, { extra: BIRD_EXTRAS[species.id] });
|
|
3145
|
+
else buildQuadruped(THREE, rig, { document: species.body.texture ? documentOf() : void 0, extra: QUADRUPED_EXTRAS[species.id] });
|
|
3146
|
+
rig.triangles = countTriangles(rig.root);
|
|
3147
|
+
markKitOrigin(rig.root, { owner: "game-animals-three", kind: "animal", id: species.id });
|
|
3148
|
+
rig.root.traverse((object2) => {
|
|
3149
|
+
if (object2.isMesh) object2.userData.speciesId = species.id;
|
|
3150
|
+
});
|
|
3151
|
+
return rig;
|
|
2717
3152
|
},
|
|
2718
|
-
{
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
[2e-3, 1, "exp"],
|
|
2731
|
-
["1d", 1e-4, "exp", "fixed"]
|
|
2732
|
-
]
|
|
2733
|
-
}
|
|
2734
|
-
],
|
|
2735
|
-
falloff: DISTANCE_CURVES.art_scene,
|
|
2736
|
-
sources: ["sdk: bench probe, a highpass hiss of random length"]
|
|
2737
|
-
}
|
|
2738
|
-
]
|
|
3153
|
+
animate(rig, params) {
|
|
3154
|
+
const kind = rig.species.body.kind;
|
|
3155
|
+
if (kind === "snake") animateSnake(THREE, rig, params);
|
|
3156
|
+
else if (kind === "bird") animateBird(rig, params);
|
|
3157
|
+
else animateQuadruped(rig, params, gaits);
|
|
3158
|
+
},
|
|
3159
|
+
setVisualState: (rig, state) => applyVisualState(THREE, rig, state),
|
|
3160
|
+
setJointView: (rig, on) => setJointView(rig, on, jointMaterial),
|
|
3161
|
+
setSplit,
|
|
3162
|
+
updateSplit,
|
|
3163
|
+
createSkin: (rig) => createNodeSkin(THREE, rig.root, { nodes: collectReferencedNodes(rig, ["species"]) })
|
|
3164
|
+
};
|
|
2739
3165
|
};
|
|
2740
3166
|
|
|
2741
|
-
//
|
|
2742
|
-
var
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
{
|
|
2752
|
-
repeat: { count: o.count, spacing: o.spacing },
|
|
2753
|
-
source: { kind: "osc", wave: o.wave, frequency: { from: o.frequency, to: o.frequency * o.drop, curve: "exp", over: "duration" } },
|
|
2754
|
-
filters: { mode: "serial", bank: [{ type: "bandpass", frequency: { set: o.frequency * 1.2 }, q: 3 }] },
|
|
2755
|
-
envelope: [
|
|
2756
|
-
[0, 1e-4, "set", "fixed"],
|
|
2757
|
-
[0.015, 1, "exp"],
|
|
2758
|
-
["1d", 1e-4, "exp", "fixed"]
|
|
2759
|
-
]
|
|
2760
|
-
}
|
|
2761
|
-
],
|
|
2762
|
-
falloff: DISTANCE_CURVES.animals,
|
|
2763
|
-
sources: [`jogo:L66625-66639 bichoSom('${o.team}')`]
|
|
2764
|
-
});
|
|
2765
|
-
var DOG_BARK = call({ id: "dog_bark", team: "latido", count: 2, spacing: 0.22, seconds: 0.12, wave: "square", frequency: 520, drop: 0.6 });
|
|
2766
|
-
var LAPWING_CALL = call({ id: "lapwing_call", team: "queroquero", count: 3, spacing: 0.14, seconds: 0.09, wave: "square", frequency: 2400, drop: 0.6 });
|
|
2767
|
-
var HEN_CLUCK = call({ id: "hen_cluck", team: "cacarejo", count: 4, spacing: 0.14, seconds: 0.09, wave: "square", frequency: 900, drop: 0.6 });
|
|
2768
|
-
var COW_MOO = call({ id: "cow_moo", team: "mugido", count: 1, spacing: 0.14, seconds: 1.2, wave: "sawtooth", frequency: 140, drop: 0.8 });
|
|
2769
|
-
var ANIMAL_SOUNDS = [DOG_BARK, LAPWING_CALL, HEN_CLUCK, COW_MOO];
|
|
2770
|
-
var ANIMAL_SOUND_BANK = { id: "animals_three", sounds: ANIMAL_SOUNDS };
|
|
2771
|
-
|
|
2772
|
-
// src/audio/calls.json
|
|
2773
|
-
var calls_default = {
|
|
2774
|
-
sources: [
|
|
2775
|
-
"jogo:L66677 galinha: cacarejo, 6 s between calls, noise 30 m",
|
|
2776
|
-
"jogo:L66680 quero-quero: queroquero when the player is near (alarme), 8 s, noise 40 m",
|
|
2777
|
-
"jogo:L66681 vaca: mugido, 30 s, noise 80 m",
|
|
2778
|
-
"jogo:L66683 cachorro: latido when a zombie is within 12 m, 3 s, noise 60 m"
|
|
2779
|
-
],
|
|
2780
|
-
species: {
|
|
2781
|
-
chicken: { sound: "hen_cluck", cooldown: 6, noiseMetres: 30 },
|
|
2782
|
-
southern_lapwing: { sound: "lapwing_call", cooldown: 8, noiseMetres: 40 },
|
|
2783
|
-
cow: { sound: "cow_moo", cooldown: 30, noiseMetres: 80 },
|
|
2784
|
-
dog: { sound: "dog_bark", cooldown: 3, noiseMetres: 60 }
|
|
3167
|
+
// ../game-render-three/dist/index.js
|
|
3168
|
+
var DEFAULT_ANGLE = Math.PI / 3;
|
|
3169
|
+
var EFFECT_STEP_SECONDS = 1 / 50;
|
|
3170
|
+
var BATCHED_LAYER = 30;
|
|
3171
|
+
var MATRIX_EPSILON = 1e-6;
|
|
3172
|
+
var ATTRIBUTES = ["position", "normal", "uv", "color"];
|
|
3173
|
+
var isShown = (object2, root) => {
|
|
3174
|
+
for (let node = object2; node; node = node.parent) {
|
|
3175
|
+
if (node === root) return true;
|
|
3176
|
+
if (!node.visible) return false;
|
|
2785
3177
|
}
|
|
3178
|
+
return false;
|
|
2786
3179
|
};
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
const
|
|
2795
|
-
const
|
|
2796
|
-
|
|
3180
|
+
var isBatchable = (mesh2) => {
|
|
3181
|
+
const flags = mesh2;
|
|
3182
|
+
if (flags.isInstancedMesh === true || flags.isSkinnedMesh === true || Array.isArray(mesh2.material)) return false;
|
|
3183
|
+
const geometry = mesh2.geometry;
|
|
3184
|
+
return geometry.attributes.position !== void 0 && Object.keys(geometry.morphAttributes).length === 0;
|
|
3185
|
+
};
|
|
3186
|
+
var signatureOf = (mesh2) => {
|
|
3187
|
+
const { attributes } = mesh2.geometry;
|
|
3188
|
+
const present = ATTRIBUTES.filter((name) => attributes[name] !== void 0).map((name) => `${name}${attributes[name].itemSize}`);
|
|
3189
|
+
return `${mesh2.material.uuid}|${present.join(",")}|${mesh2.castShadow ? 1 : 0}${mesh2.receiveShadow ? 1 : 0}`;
|
|
3190
|
+
};
|
|
3191
|
+
var sameMatrix = (a, b) => a.elements.every((value, index) => Math.abs(value - b.elements[index]) < MATRIX_EPSILON);
|
|
3192
|
+
function createStaticBatcher(THREE, root, options = {}) {
|
|
3193
|
+
const include = options.include ?? (() => true);
|
|
3194
|
+
const follow = options.followMeshes === true;
|
|
3195
|
+
root.updateMatrixWorld(true);
|
|
3196
|
+
const inverse = new THREE.Matrix4().copy(root.matrixWorld).invert();
|
|
3197
|
+
const groups = /* @__PURE__ */ new Map();
|
|
3198
|
+
root.traverse((object2) => {
|
|
3199
|
+
const mesh2 = object2;
|
|
3200
|
+
if (!mesh2.isMesh || !isShown(mesh2, root) || !isBatchable(mesh2) || !include(mesh2)) return;
|
|
3201
|
+
const key = signatureOf(mesh2);
|
|
3202
|
+
groups.set(key, [...groups.get(key) ?? [], mesh2]);
|
|
3203
|
+
});
|
|
3204
|
+
const group = new THREE.Group();
|
|
3205
|
+
group.name = "static-batches";
|
|
3206
|
+
const sources = [];
|
|
3207
|
+
const pending = [...groups.values()].filter((meshes) => meshes.length >= 2);
|
|
3208
|
+
const mergeSome = (deadline) => {
|
|
3209
|
+
while (pending.length > 0) {
|
|
3210
|
+
const meshes = pending.shift();
|
|
3211
|
+
if (meshes.every((mesh2) => isShown(mesh2, root))) sources.push(...mergeGroup(THREE, { meshes, inverse: new THREE.Matrix4().copy(root.matrixWorld).invert(), group, follow }));
|
|
3212
|
+
if (performance.now() >= deadline) return;
|
|
3213
|
+
}
|
|
3214
|
+
};
|
|
3215
|
+
if (options.budgetMs === void 0) mergeSome(Number.POSITIVE_INFINITY);
|
|
3216
|
+
root.add(group);
|
|
3217
|
+
const scratch = new THREE.Matrix4();
|
|
3218
|
+
let released = 0;
|
|
3219
|
+
const release = (source) => {
|
|
3220
|
+
source.released = true;
|
|
3221
|
+
source.mesh.layers.mask = source.mask;
|
|
3222
|
+
const { index } = source.batch;
|
|
3223
|
+
const first = index.array[source.start];
|
|
3224
|
+
for (let at = source.start; at < source.start + source.count; at++) index.array[at] = first;
|
|
3225
|
+
index.needsUpdate = true;
|
|
3226
|
+
if (--source.batch.live === 0) source.batch.mesh.visible = false;
|
|
3227
|
+
released++;
|
|
3228
|
+
};
|
|
3229
|
+
const hasChanged = (source) => {
|
|
3230
|
+
const { mesh: mesh2 } = source;
|
|
3231
|
+
if (mesh2.geometry !== source.geometry || mesh2.material !== source.material || !isShown(mesh2, root)) return true;
|
|
3232
|
+
if (mesh2.geometry.attributes.position.version !== source.version) return true;
|
|
3233
|
+
if (follow || sameMatrix(mesh2.matrixWorld, source.world)) return false;
|
|
3234
|
+
if (!sameMatrix(scratch.multiplyMatrices(inverse, mesh2.matrixWorld), source.local)) return true;
|
|
3235
|
+
source.world.copy(mesh2.matrixWorld);
|
|
3236
|
+
return false;
|
|
3237
|
+
};
|
|
2797
3238
|
return {
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
if (
|
|
2804
|
-
|
|
2805
|
-
sink.play({ sound: found.sound, position, ...o.volume === void 0 ? {} : { volume: o.volume } });
|
|
2806
|
-
return true;
|
|
3239
|
+
group,
|
|
3240
|
+
update() {
|
|
3241
|
+
if (pending.length > 0) mergeSome(performance.now() + (options.budgetMs ?? Number.POSITIVE_INFINITY));
|
|
3242
|
+
const before = released;
|
|
3243
|
+
inverse.copy(root.matrixWorld).invert();
|
|
3244
|
+
for (const source of sources) if (!source.released && hasChanged(source)) release(source);
|
|
3245
|
+
return released - before;
|
|
2807
3246
|
},
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
3247
|
+
stats: () => ({ batches: group.children.length, batched: sources.filter((source) => !source.released).length, released }),
|
|
3248
|
+
dispose() {
|
|
3249
|
+
for (const source of sources) if (!source.released) source.mesh.layers.mask = source.mask;
|
|
3250
|
+
group.removeFromParent();
|
|
3251
|
+
for (const child of group.children) {
|
|
3252
|
+
;
|
|
3253
|
+
child.geometry.dispose();
|
|
3254
|
+
child.skeleton?.dispose();
|
|
2812
3255
|
}
|
|
2813
|
-
}
|
|
2814
|
-
dispose: () => waiting.clear()
|
|
3256
|
+
}
|
|
2815
3257
|
};
|
|
2816
3258
|
}
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
const
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
cursor += length / 2;
|
|
2826
|
-
rig.root.position.set(cursor, 0, 0);
|
|
2827
|
-
rig.home = rig.root.position.clone();
|
|
2828
|
-
rig.root.rotation.y = rig.species.body.kind === "snake" ? options.snakeYaw ?? 2.2 : options.yaw ?? 1.1;
|
|
2829
|
-
cursor += length / 2 + gap;
|
|
3259
|
+
function copyAttribute(name, attribute, target, offset, matrix, normalMatrix2) {
|
|
3260
|
+
const size = attribute.itemSize;
|
|
3261
|
+
const source = attribute.array;
|
|
3262
|
+
const flat = !attribute.isInterleavedBufferAttribute && source.length === attribute.count * size;
|
|
3263
|
+
if (name !== "position" && name !== "normal") {
|
|
3264
|
+
if (flat) target.set(source, offset * size);
|
|
3265
|
+
else for (let at = 0; at < attribute.count; at++) for (let k = 0; k < size; k++) target[(offset + at) * size + k] = attribute.getComponent(at, k);
|
|
3266
|
+
return;
|
|
2830
3267
|
}
|
|
2831
|
-
const
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
3268
|
+
const e = (name === "position" ? matrix : normalMatrix2).elements;
|
|
3269
|
+
const isNormal = name === "normal";
|
|
3270
|
+
for (let at = 0; at < attribute.count; at++) {
|
|
3271
|
+
const x = attribute.getX(at);
|
|
3272
|
+
const y = attribute.getY(at);
|
|
3273
|
+
const z = attribute.getZ(at);
|
|
3274
|
+
const out = (offset + at) * 3;
|
|
3275
|
+
if (isNormal) {
|
|
3276
|
+
const nx = e[0] * x + e[3] * y + e[6] * z;
|
|
3277
|
+
const ny = e[1] * x + e[4] * y + e[7] * z;
|
|
3278
|
+
const nz = e[2] * x + e[5] * y + e[8] * z;
|
|
3279
|
+
const length = Math.hypot(nx, ny, nz) || 1;
|
|
3280
|
+
target[out] = nx / length;
|
|
3281
|
+
target[out + 1] = ny / length;
|
|
3282
|
+
target[out + 2] = nz / length;
|
|
3283
|
+
} else {
|
|
3284
|
+
target[out] = e[0] * x + e[4] * y + e[8] * z + e[12];
|
|
3285
|
+
target[out + 1] = e[1] * x + e[5] * y + e[9] * z + e[13];
|
|
3286
|
+
target[out + 2] = e[2] * x + e[6] * y + e[10] * z + e[14];
|
|
3287
|
+
}
|
|
2835
3288
|
}
|
|
2836
|
-
}
|
|
3289
|
+
}
|
|
3290
|
+
function skinnedBatch(THREE, merged, material, meshes) {
|
|
3291
|
+
const vertices = merged.attributes.position.count;
|
|
3292
|
+
const skinIndex = new Uint16Array(vertices * 4);
|
|
3293
|
+
const skinWeight = new Float32Array(vertices * 4);
|
|
3294
|
+
let at = 0;
|
|
3295
|
+
meshes.forEach((mesh22, bone) => {
|
|
3296
|
+
for (let k = 0; k < mesh22.geometry.attributes.position.count; k++, at++) {
|
|
3297
|
+
skinIndex[at * 4] = bone;
|
|
3298
|
+
skinWeight[at * 4] = 1;
|
|
3299
|
+
}
|
|
3300
|
+
});
|
|
3301
|
+
merged.setAttribute("skinIndex", new THREE.BufferAttribute(skinIndex, 4));
|
|
3302
|
+
merged.setAttribute("skinWeight", new THREE.BufferAttribute(skinWeight, 4));
|
|
3303
|
+
const mesh2 = new THREE.SkinnedMesh(merged, material);
|
|
3304
|
+
const identities = meshes.map(() => new THREE.Matrix4());
|
|
3305
|
+
mesh2.bind(new THREE.Skeleton(meshes, identities), new THREE.Matrix4());
|
|
3306
|
+
mesh2.frustumCulled = false;
|
|
3307
|
+
return mesh2;
|
|
3308
|
+
}
|
|
3309
|
+
function mergeGroup(THREE, { meshes, inverse: rootInverse, group, follow }) {
|
|
3310
|
+
const identity = new THREE.Matrix4();
|
|
3311
|
+
const inverse = follow ? identity : rootInverse;
|
|
3312
|
+
const first = meshes[0];
|
|
3313
|
+
const names = ATTRIBUTES.filter((name) => first.geometry.attributes[name] !== void 0);
|
|
3314
|
+
const pieces = meshes.map((mesh22) => {
|
|
3315
|
+
const local = new THREE.Matrix4().multiplyMatrices(inverse, mesh22.matrixWorld);
|
|
3316
|
+
const vertices = mesh22.geometry.attributes.position.count;
|
|
3317
|
+
const indexCount = mesh22.geometry.index ? mesh22.geometry.index.count : vertices;
|
|
3318
|
+
return { mesh: mesh22, local, vertices, indexCount };
|
|
3319
|
+
});
|
|
3320
|
+
const totalVertices = pieces.reduce((sum, piece) => sum + piece.vertices, 0);
|
|
3321
|
+
const totalIndices = pieces.reduce((sum, piece) => sum + piece.indexCount, 0);
|
|
3322
|
+
const merged = new THREE.BufferGeometry();
|
|
3323
|
+
const normalMatrix2 = new THREE.Matrix3();
|
|
3324
|
+
for (const name of names) {
|
|
3325
|
+
const size = first.geometry.attributes[name].itemSize;
|
|
3326
|
+
const array = new Float32Array(totalVertices * size);
|
|
3327
|
+
let offset = 0;
|
|
3328
|
+
for (const piece of pieces) {
|
|
3329
|
+
const matrix = follow ? identity : piece.local;
|
|
3330
|
+
copyAttribute(name, piece.mesh.geometry.attributes[name], array, offset, matrix, normalMatrix2.getNormalMatrix(matrix));
|
|
3331
|
+
offset += piece.vertices;
|
|
3332
|
+
}
|
|
3333
|
+
merged.setAttribute(name, new THREE.BufferAttribute(array, size));
|
|
3334
|
+
}
|
|
3335
|
+
const indexArray2 = totalVertices > 65535 ? new Uint32Array(totalIndices) : new Uint16Array(totalIndices);
|
|
3336
|
+
const indexAttribute = new THREE.BufferAttribute(indexArray2, 1);
|
|
3337
|
+
merged.setIndex(indexAttribute);
|
|
3338
|
+
const mesh2 = follow ? skinnedBatch(THREE, merged, first.material, meshes) : new THREE.Mesh(merged, first.material);
|
|
3339
|
+
mesh2.name = `batch:${first.material.name || first.material.type}`;
|
|
3340
|
+
mesh2.castShadow = first.castShadow;
|
|
3341
|
+
mesh2.receiveShadow = first.receiveShadow;
|
|
3342
|
+
mesh2.raycast = () => void 0;
|
|
3343
|
+
merged.computeBoundingBox();
|
|
3344
|
+
merged.computeBoundingSphere();
|
|
3345
|
+
group.add(mesh2);
|
|
3346
|
+
const batch = { mesh: mesh2, live: pieces.length, index: indexAttribute };
|
|
3347
|
+
const sources = [];
|
|
3348
|
+
let vertexOffset = 0;
|
|
3349
|
+
let indexOffset = 0;
|
|
3350
|
+
for (const piece of pieces) {
|
|
3351
|
+
const index = piece.mesh.geometry.index;
|
|
3352
|
+
if (index) for (let at = 0; at < piece.indexCount; at++) indexArray2[indexOffset + at] = index.getX(at) + vertexOffset;
|
|
3353
|
+
else for (let at = 0; at < piece.indexCount; at++) indexArray2[indexOffset + at] = at + vertexOffset;
|
|
3354
|
+
sources.push({
|
|
3355
|
+
mesh: piece.mesh,
|
|
3356
|
+
geometry: piece.mesh.geometry,
|
|
3357
|
+
material: piece.mesh.material,
|
|
3358
|
+
version: piece.mesh.geometry.attributes.position.version,
|
|
3359
|
+
local: piece.local,
|
|
3360
|
+
world: piece.mesh.matrixWorld.clone(),
|
|
3361
|
+
mask: piece.mesh.layers.mask,
|
|
3362
|
+
batch,
|
|
3363
|
+
start: indexOffset,
|
|
3364
|
+
count: piece.indexCount,
|
|
3365
|
+
released: false
|
|
3366
|
+
});
|
|
3367
|
+
piece.mesh.layers.set(BATCHED_LAYER);
|
|
3368
|
+
vertexOffset += piece.vertices;
|
|
3369
|
+
indexOffset += piece.indexCount;
|
|
3370
|
+
}
|
|
3371
|
+
return sources;
|
|
3372
|
+
}
|
|
2837
3373
|
|
|
2838
3374
|
// src/test-area/scenarios.ts
|
|
2839
3375
|
var SKIN_COUNT = 40;
|
|
@@ -2960,6 +3496,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2960
3496
|
var SKIN_COUNT2 = 40;
|
|
2961
3497
|
var SKIN_FIELD = { x0: -18, z0: -10, columns: 8, gap: 4.5 };
|
|
2962
3498
|
var DEFAULT_TIME_SCALE = 60;
|
|
3499
|
+
var BATCH_BUDGET_MS = 1;
|
|
2963
3500
|
function createAnimalsTestModule(options = {}) {
|
|
2964
3501
|
const locale = options.locale ?? "pt-BR";
|
|
2965
3502
|
const text = TEXT[locale] ?? TEXT["pt-BR"];
|
|
@@ -2988,14 +3525,24 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
2988
3525
|
outbreak = options.createOutbreak ? options.createOutbreak({ species, enabled: settings.outbreak, timeScale: settings.timeScale }) : null;
|
|
2989
3526
|
};
|
|
2990
3527
|
rebuildOutbreak();
|
|
3528
|
+
const batch = (entry) => {
|
|
3529
|
+
entry.batcher?.dispose();
|
|
3530
|
+
if (three) entry.batcher = createStaticBatcher(three, entry.rig.root, { followMeshes: true, budgetMs: BATCH_BUDGET_MS });
|
|
3531
|
+
};
|
|
3532
|
+
const look = (entry, state) => {
|
|
3533
|
+
animals?.setVisualState(entry.rig, state);
|
|
3534
|
+
batch(entry);
|
|
3535
|
+
};
|
|
2991
3536
|
const item = (animal) => ({
|
|
2992
3537
|
id: `${ANIMAL_ITEM_PREFIX}${animal.id}`,
|
|
2993
3538
|
name: animal.name[locale] ?? animal.id,
|
|
2994
3539
|
movable: false,
|
|
2995
3540
|
build: (THREE) => {
|
|
2996
3541
|
const rig = ensure(THREE).build(animal);
|
|
2997
|
-
|
|
3542
|
+
const entry = { id: rig.root.uuid, rig };
|
|
3543
|
+
placed.set(rig.root.uuid, entry);
|
|
2998
3544
|
if (settings.visual !== "alive") animals?.setVisualState(rig, settings.visual);
|
|
3545
|
+
batch(entry);
|
|
2999
3546
|
return rig.root;
|
|
3000
3547
|
}
|
|
3001
3548
|
});
|
|
@@ -3004,7 +3551,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
3004
3551
|
const state = outbreak.stateOf(entry.fate, clock);
|
|
3005
3552
|
if (state === "incubating") return;
|
|
3006
3553
|
entry.counted = state === "turned" ? "turned" : "dead";
|
|
3007
|
-
|
|
3554
|
+
look(entry, visualStateOf(entry.rig.species.outcome, true, state === "dead"));
|
|
3008
3555
|
};
|
|
3009
3556
|
const clearRings = () => {
|
|
3010
3557
|
discardObject3D(rings);
|
|
@@ -3055,7 +3602,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
3055
3602
|
const applyVisual = () => {
|
|
3056
3603
|
for (const entry of placed.values()) {
|
|
3057
3604
|
if (entry.fate) continue;
|
|
3058
|
-
|
|
3605
|
+
look(entry, settings.visual);
|
|
3059
3606
|
}
|
|
3060
3607
|
};
|
|
3061
3608
|
const onChange = (change) => {
|
|
@@ -3064,13 +3611,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
3064
3611
|
if (change.id === "bite_all") {
|
|
3065
3612
|
for (const entry of placed.values()) {
|
|
3066
3613
|
entry.fate = outbreak?.bite(entry.rig.species.id, random, clock);
|
|
3067
|
-
if (entry.fate)
|
|
3614
|
+
if (entry.fate) look(entry, visualStateOf(entry.rig.species.outcome, true));
|
|
3068
3615
|
}
|
|
3069
3616
|
} else if (change.id === "recover") {
|
|
3070
3617
|
for (const entry of placed.values()) {
|
|
3071
3618
|
delete entry.fate;
|
|
3072
3619
|
delete entry.counted;
|
|
3073
|
-
|
|
3620
|
+
look(entry, settings.visual);
|
|
3074
3621
|
}
|
|
3075
3622
|
} else if (change.id === "call" && sound) {
|
|
3076
3623
|
for (const [id, entry] of placed) {
|
|
@@ -3110,12 +3657,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
3110
3657
|
sound?.update(dt);
|
|
3111
3658
|
for (const [id, entry] of placed) {
|
|
3112
3659
|
if (!entry.rig.root.parent) {
|
|
3660
|
+
entry.batcher?.dispose();
|
|
3113
3661
|
placed.delete(id);
|
|
3114
3662
|
continue;
|
|
3115
3663
|
}
|
|
3116
3664
|
statusOf(entry);
|
|
3117
3665
|
animals?.animate(entry.rig, { time, delta: dt * settings.speed, clip: settings.gait, split: host?.bench?.layer("split") ?? false });
|
|
3118
3666
|
animals?.updateSplit(entry.rig, dt);
|
|
3667
|
+
entry.batcher?.update();
|
|
3119
3668
|
}
|
|
3120
3669
|
for (const { rig, skin } of skins) {
|
|
3121
3670
|
animals?.animate(rig, { time, delta: dt * settings.speed, clip: settings.gait });
|
|
@@ -3219,55 +3768,6 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
3219
3768
|
}
|
|
3220
3769
|
};
|
|
3221
3770
|
}
|
|
3222
|
-
|
|
3223
|
-
// src/index.ts
|
|
3224
|
-
var countTriangles = (root) => {
|
|
3225
|
-
let triangles = 0;
|
|
3226
|
-
root.traverse((object2) => {
|
|
3227
|
-
const mesh2 = object2;
|
|
3228
|
-
if (!mesh2.isMesh) return;
|
|
3229
|
-
const geometry = mesh2.geometry;
|
|
3230
|
-
triangles += geometry.index ? geometry.index.count / 3 : geometry.attributes.position.count / 3;
|
|
3231
|
-
});
|
|
3232
|
-
return Math.round(triangles);
|
|
3233
|
-
};
|
|
3234
|
-
var createAnimalsThree = (host, options = {}) => {
|
|
3235
|
-
const THREE = shapeGeometries(host);
|
|
3236
|
-
const random = options.random ?? createStream(options.seed ?? 7);
|
|
3237
|
-
const documentOf = () => {
|
|
3238
|
-
const found = options.document ?? globalThis.document;
|
|
3239
|
-
if (!found) throw new Error("game-animals-three: a species with a coat texture needs `options.document` (no global document found)");
|
|
3240
|
-
return found;
|
|
3241
|
-
};
|
|
3242
|
-
const jointMaterial = new THREE.MeshStandardMaterial({ color: 14722376, emissive: 14722376, emissiveIntensity: 0.8, roughness: 0.4 });
|
|
3243
|
-
const gaits = GAIT_PHASES;
|
|
3244
|
-
return {
|
|
3245
|
-
jointMaterial,
|
|
3246
|
-
build(species, buildOptions = {}) {
|
|
3247
|
-
const rig = createRig(THREE, species, { phase: buildOptions.phase ?? random() * 6 });
|
|
3248
|
-
if (species.body.kind === "snake") buildSnake(THREE, rig);
|
|
3249
|
-
else if (species.body.kind === "bird") buildBird(THREE, rig, { extra: BIRD_EXTRAS[species.id] });
|
|
3250
|
-
else buildQuadruped(THREE, rig, { document: species.body.texture ? documentOf() : void 0, extra: QUADRUPED_EXTRAS[species.id] });
|
|
3251
|
-
rig.triangles = countTriangles(rig.root);
|
|
3252
|
-
markKitOrigin(rig.root, { owner: "game-animals-three", kind: "animal", id: species.id });
|
|
3253
|
-
rig.root.traverse((object2) => {
|
|
3254
|
-
if (object2.isMesh) object2.userData.speciesId = species.id;
|
|
3255
|
-
});
|
|
3256
|
-
return rig;
|
|
3257
|
-
},
|
|
3258
|
-
animate(rig, params) {
|
|
3259
|
-
const kind = rig.species.body.kind;
|
|
3260
|
-
if (kind === "snake") animateSnake(THREE, rig, params);
|
|
3261
|
-
else if (kind === "bird") animateBird(rig, params);
|
|
3262
|
-
else animateQuadruped(rig, params, gaits);
|
|
3263
|
-
},
|
|
3264
|
-
setVisualState: (rig, state) => applyVisualState(THREE, rig, state),
|
|
3265
|
-
setJointView: (rig, on) => setJointView(rig, on, jointMaterial),
|
|
3266
|
-
setSplit,
|
|
3267
|
-
updateSplit,
|
|
3268
|
-
createSkin: (rig) => createNodeSkin(THREE, rig.root, { nodes: collectReferencedNodes(rig, ["species"]) })
|
|
3269
|
-
};
|
|
3270
|
-
};
|
|
3271
3771
|
return __toCommonJS(index_exports);
|
|
3272
3772
|
})();
|
|
3273
3773
|
//# sourceMappingURL=index.global.js.map
|