@adatechnology/game-weather 0.1.1 → 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/README.md +36 -2
- package/dist/index.d.ts +181 -2
- package/dist/index.global.js +376 -17
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +210 -17
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -771,6 +771,177 @@ function createTimeline(options) {
|
|
|
771
771
|
};
|
|
772
772
|
}
|
|
773
773
|
|
|
774
|
+
// src/audio/recipes.ts
|
|
775
|
+
import { sceneNoise, sceneTone } from "@adatechnology/game-audio";
|
|
776
|
+
var RAIN_LOOP = {
|
|
777
|
+
id: "rain_loop",
|
|
778
|
+
bus: "weather",
|
|
779
|
+
order: "chain_loop",
|
|
780
|
+
source: { kind: "noise", loop: true },
|
|
781
|
+
filters: {
|
|
782
|
+
mode: "serial",
|
|
783
|
+
bank: [
|
|
784
|
+
{ type: "highpass", frequency: { set: 600 } },
|
|
785
|
+
{ type: "lowpass", frequency: { set: 6e3 } }
|
|
786
|
+
]
|
|
787
|
+
},
|
|
788
|
+
sources: ["cena:L1314"]
|
|
789
|
+
};
|
|
790
|
+
var WIND_LOOP = {
|
|
791
|
+
id: "wind_loop",
|
|
792
|
+
bus: "weather",
|
|
793
|
+
order: "chain_loop",
|
|
794
|
+
source: { kind: "noise", loop: true },
|
|
795
|
+
filters: { mode: "serial", bank: [{ type: "lowpass", frequency: { set: 320 } }] },
|
|
796
|
+
modulators: [{ target: "gain", rate: 0.07, depth: 0.035 }],
|
|
797
|
+
sources: ["cena:L1315"]
|
|
798
|
+
};
|
|
799
|
+
var RAIN_HISS_GAME = {
|
|
800
|
+
id: "rain_hiss_game",
|
|
801
|
+
bus: "weather",
|
|
802
|
+
order: "game_loop",
|
|
803
|
+
source: { kind: "noise", loop: true },
|
|
804
|
+
filters: { mode: "serial", bank: [{ type: "highpass", frequency: { set: 2500 } }] },
|
|
805
|
+
sources: ["jogo:L62116 chuva"]
|
|
806
|
+
};
|
|
807
|
+
var THUNDER = {
|
|
808
|
+
id: "thunder",
|
|
809
|
+
bus: "weather",
|
|
810
|
+
pan: true,
|
|
811
|
+
layers: [sceneTone({ f: 70, f2: 28, d: 1.2, vol: 1 }), sceneNoise({ f: 260, f2: 50, d: 3.2, vol: 0.9, wet: 0.8 })],
|
|
812
|
+
falloff: { model: "inverse_square", k: 1e-5, scale: 1.4 },
|
|
813
|
+
sources: ["jogo:L68278-68285 boom", "sdk: rumble and falloff"]
|
|
814
|
+
};
|
|
815
|
+
var WEATHER_BANK = { id: "weather", sounds: [THUNDER], loops: [RAIN_LOOP, WIND_LOOP, RAIN_HISS_GAME] };
|
|
816
|
+
var WEATHER_SOUNDS = WEATHER_BANK.sounds ?? [];
|
|
817
|
+
var WEATHER_LOOPS = WEATHER_BANK.loops ?? [];
|
|
818
|
+
|
|
819
|
+
// src/audio/sound.ts
|
|
820
|
+
var DEFAULT_RAIN_SOUND = { light: 0.035, heavy: 0.06, lightAt: 2.5, heavyAt: 15 };
|
|
821
|
+
var DEFAULT_WIND_SOUND = { base: 0.05, referenceSpeed: 3.8, max: 0.12 };
|
|
822
|
+
function rainVolume(rain, options = {}) {
|
|
823
|
+
if (!(rain > 0)) return 0;
|
|
824
|
+
const { light, heavy, lightAt, heavyAt } = { ...DEFAULT_RAIN_SOUND, ...options };
|
|
825
|
+
if (heavyAt <= lightAt) return rain >= heavyAt ? heavy : light;
|
|
826
|
+
const t = Math.min(1, Math.max(0, (rain - lightAt) / (heavyAt - lightAt)));
|
|
827
|
+
return light + (heavy - light) * t;
|
|
828
|
+
}
|
|
829
|
+
function windVolume(speed, options = {}) {
|
|
830
|
+
const { base, referenceSpeed, max } = { ...DEFAULT_WIND_SOUND, ...options };
|
|
831
|
+
return Math.min(max, base * Math.max(0, speed) / referenceSpeed);
|
|
832
|
+
}
|
|
833
|
+
function strikePosition(strike, origin = [0, 0, 0]) {
|
|
834
|
+
const angle = strike.bearing * Math.PI / 180;
|
|
835
|
+
return [origin[0] + Math.sin(angle) * strike.distance, origin[1], origin[2] - Math.cos(angle) * strike.distance];
|
|
836
|
+
}
|
|
837
|
+
function createWeatherSound(sink, options = {}) {
|
|
838
|
+
if (sink && options.register !== false) sink.register?.(WEATHER_BANK);
|
|
839
|
+
const rainSound = options.style === "game" ? "rain_hiss_game" : "rain_loop";
|
|
840
|
+
const loops = /* @__PURE__ */ new Map();
|
|
841
|
+
const set = (id, volume) => {
|
|
842
|
+
let loop = loops.get(id);
|
|
843
|
+
if (!loop) {
|
|
844
|
+
if (!(volume > 0) || !sink?.loop) return;
|
|
845
|
+
loop = sink.loop(id);
|
|
846
|
+
loops.set(id, loop);
|
|
847
|
+
}
|
|
848
|
+
loop.set({ volume });
|
|
849
|
+
};
|
|
850
|
+
return {
|
|
851
|
+
update(sample) {
|
|
852
|
+
set(rainSound, rainVolume(sample.rain, options.rain));
|
|
853
|
+
set("wind_loop", windVolume(sample.windSpeed, options.wind));
|
|
854
|
+
},
|
|
855
|
+
thunder(strike) {
|
|
856
|
+
sink?.play({ sound: "thunder", position: strikePosition(strike, options.listener?.()), ...options.thunderVolume === void 0 ? {} : { volume: options.thunderVolume } });
|
|
857
|
+
},
|
|
858
|
+
dispose() {
|
|
859
|
+
for (const loop of loops.values()) loop.stop();
|
|
860
|
+
loops.clear();
|
|
861
|
+
}
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
// src/bridges.ts
|
|
866
|
+
var DEFAULT_BRIDGE_RULES = { filmRainFullAt: 2.5, washFrom: 15, washBelow: 0.5, washEvery: 1, windFull: 20 };
|
|
867
|
+
function environmentOf(sample) {
|
|
868
|
+
return {
|
|
869
|
+
rain: sample.rain,
|
|
870
|
+
windX: sample.windX,
|
|
871
|
+
windZ: sample.windZ,
|
|
872
|
+
windSpeed: sample.windSpeed,
|
|
873
|
+
gust: sample.gust,
|
|
874
|
+
fogFar: sample.fogFar,
|
|
875
|
+
visibility: sample.effects.visibility,
|
|
876
|
+
nightFactor: sample.nightFactor,
|
|
877
|
+
temperatureC: sample.temperatureC,
|
|
878
|
+
wetness: sample.groundWetness
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
function createWeatherBridges(targets, options = {}) {
|
|
882
|
+
const rules = { ...DEFAULT_BRIDGE_RULES, ...options };
|
|
883
|
+
const sound = options.sound === false || !targets.audio ? void 0 : createWeatherSound(targets.audio, options.sound ?? {});
|
|
884
|
+
let weather;
|
|
885
|
+
let offThunder;
|
|
886
|
+
let sinceWash = 0;
|
|
887
|
+
let last = {};
|
|
888
|
+
const push = () => {
|
|
889
|
+
if (!weather) return;
|
|
890
|
+
const sample = weather.sample();
|
|
891
|
+
const { film, interactables, vegetation, vfx, environment } = targets;
|
|
892
|
+
environment?.set(environmentOf(sample));
|
|
893
|
+
if (film) {
|
|
894
|
+
const rain = Math.min(1, Math.max(0, sample.rain / rules.filmRainFullAt));
|
|
895
|
+
const drying = sample.effects.dryingScale;
|
|
896
|
+
if (rain !== last.filmRain || drying !== last.drying) film.setWeather({ rain, drying });
|
|
897
|
+
last.filmRain = rain;
|
|
898
|
+
last.drying = drying;
|
|
899
|
+
}
|
|
900
|
+
if (interactables && sample.rain !== last.rain) interactables.water.setRain(sample.rain);
|
|
901
|
+
const windChanged = sample.windX !== last.windX || sample.windZ !== last.windZ;
|
|
902
|
+
if (windChanged) {
|
|
903
|
+
interactables?.setWind(sample.windX, sample.windZ);
|
|
904
|
+
vfx?.setWind([sample.windX, 0, sample.windZ]);
|
|
905
|
+
if (vegetation) {
|
|
906
|
+
const wind = { strength: Math.min(1, sample.windSpeed / rules.windFull), gust: Math.min(1, sample.gust / rules.windFull) };
|
|
907
|
+
vegetation.setWind(sample.windSpeed > 1e-6 ? { direction: [sample.windX, sample.windZ], ...wind } : wind);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
last = { ...last, rain: sample.rain, windX: sample.windX, windZ: sample.windZ };
|
|
911
|
+
sound?.update(sample);
|
|
912
|
+
};
|
|
913
|
+
const onThunder = (strike) => sound?.thunder(strike);
|
|
914
|
+
return {
|
|
915
|
+
bind(next) {
|
|
916
|
+
offThunder?.();
|
|
917
|
+
weather = next;
|
|
918
|
+
offThunder = next.on("thunder", onThunder);
|
|
919
|
+
last = {};
|
|
920
|
+
sinceWash = 0;
|
|
921
|
+
push();
|
|
922
|
+
},
|
|
923
|
+
update(dt) {
|
|
924
|
+
push();
|
|
925
|
+
if (!weather || !targets.film?.wash) return;
|
|
926
|
+
if (weather.sample().rain < rules.washFrom) {
|
|
927
|
+
sinceWash = 0;
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
sinceWash += dt;
|
|
931
|
+
if (sinceWash >= rules.washEvery) {
|
|
932
|
+
sinceWash = 0;
|
|
933
|
+
targets.film.wash(rules.washBelow);
|
|
934
|
+
}
|
|
935
|
+
},
|
|
936
|
+
dispose() {
|
|
937
|
+
offThunder?.();
|
|
938
|
+
offThunder = void 0;
|
|
939
|
+
weather = void 0;
|
|
940
|
+
sound?.dispose();
|
|
941
|
+
}
|
|
942
|
+
};
|
|
943
|
+
}
|
|
944
|
+
|
|
774
945
|
// src/bench/locale.ts
|
|
775
946
|
var EN = {
|
|
776
947
|
group: "Weather",
|
|
@@ -873,9 +1044,12 @@ var FOG_NEAR = 1;
|
|
|
873
1044
|
function createWeatherTestModule(options = {}) {
|
|
874
1045
|
const locale = options.locale ?? "pt-BR";
|
|
875
1046
|
const text = weatherBenchTextOf(locale);
|
|
876
|
-
const { locale: _locale, translate, weather: given, fog: _fog, ...weatherOptions } = options;
|
|
1047
|
+
const { locale: _locale, translate, weather: given, fog: _fog, targets: _targets, sound: _sound, visual: _visual, ...weatherOptions } = options;
|
|
877
1048
|
void _locale;
|
|
878
1049
|
void _fog;
|
|
1050
|
+
void _targets;
|
|
1051
|
+
void _sound;
|
|
1052
|
+
void _visual;
|
|
879
1053
|
const state = {
|
|
880
1054
|
seed: options.seed ?? 1,
|
|
881
1055
|
hour: options.startHour ?? 8,
|
|
@@ -887,6 +1061,8 @@ function createWeatherTestModule(options = {}) {
|
|
|
887
1061
|
let host = null;
|
|
888
1062
|
let strikes = 0;
|
|
889
1063
|
let offStrike;
|
|
1064
|
+
let bridges;
|
|
1065
|
+
let visual;
|
|
890
1066
|
let weather = given ?? createWeather({ ...weatherOptions, autoSchedule: state.auto, ...state.auto ? { timeScale: FAST_SCALE } : {} });
|
|
891
1067
|
const watch = () => {
|
|
892
1068
|
offStrike?.();
|
|
@@ -899,19 +1075,8 @@ function createWeatherTestModule(options = {}) {
|
|
|
899
1075
|
weather = createWeather({ ...weatherOptions, seed: state.seed, start: current, startHour: state.hour, autoSchedule: state.auto, timeScale: state.auto ? FAST_SCALE : NORMAL_SCALE });
|
|
900
1076
|
strikes = 0;
|
|
901
1077
|
watch();
|
|
1078
|
+
bridges?.bind(weather);
|
|
902
1079
|
};
|
|
903
|
-
const toEnvironment = (sample) => ({
|
|
904
|
-
rain: sample.rain,
|
|
905
|
-
windX: sample.windX,
|
|
906
|
-
windZ: sample.windZ,
|
|
907
|
-
windSpeed: sample.windSpeed,
|
|
908
|
-
gust: sample.gust,
|
|
909
|
-
fogFar: sample.fogFar,
|
|
910
|
-
visibility: sample.effects.visibility,
|
|
911
|
-
nightFactor: sample.nightFactor,
|
|
912
|
-
temperatureC: sample.temperatureC,
|
|
913
|
-
wetness: sample.groundWetness
|
|
914
|
-
});
|
|
915
1080
|
const applyFog = (far) => {
|
|
916
1081
|
const scene = host?.scene;
|
|
917
1082
|
const Fog = host?.THREE?.Fog;
|
|
@@ -922,12 +1087,13 @@ function createWeatherTestModule(options = {}) {
|
|
|
922
1087
|
};
|
|
923
1088
|
const publish = () => {
|
|
924
1089
|
const sample = weather.sample();
|
|
925
|
-
if (state.environment) host?.environment?.set(
|
|
926
|
-
if (state.fog) applyFog(sample.fogFar);
|
|
1090
|
+
if (state.environment) host?.environment?.set(environmentOf(sample));
|
|
1091
|
+
if (state.fog && !visual) applyFog(sample.fogFar);
|
|
927
1092
|
};
|
|
928
1093
|
const onChange = (change) => {
|
|
929
1094
|
if (change.kind === "layer") {
|
|
930
1095
|
if (change.id === "environment" || change.id === "fog") state[change.id] = change.on;
|
|
1096
|
+
visual?.setLayer(change.id, change.on);
|
|
931
1097
|
return;
|
|
932
1098
|
}
|
|
933
1099
|
if (change.kind === "action") return;
|
|
@@ -965,7 +1131,8 @@ function createWeatherTestModule(options = {}) {
|
|
|
965
1131
|
];
|
|
966
1132
|
const layers = () => [
|
|
967
1133
|
{ id: "environment", name: text.layers.environment },
|
|
968
|
-
{ id: "fog", name: text.layers.fog, default: state.fog }
|
|
1134
|
+
{ id: "fog", name: text.layers.fog, default: state.fog },
|
|
1135
|
+
...options.visual?.layers(locale) ?? []
|
|
969
1136
|
];
|
|
970
1137
|
const metrics = () => [
|
|
971
1138
|
{ id: "current_state", name: text.metrics.state, read: () => nameOf(weather.state()) },
|
|
@@ -1054,14 +1221,24 @@ function createWeatherTestModule(options = {}) {
|
|
|
1054
1221
|
attach(lent) {
|
|
1055
1222
|
host = lent;
|
|
1056
1223
|
const off = lent.bench?.onChange(onChange);
|
|
1224
|
+
bridges = createWeatherBridges({ ...options.targets, ...lent.audio ? { audio: lent.audio } : {} }, { sound: options.sound ?? {} });
|
|
1225
|
+
bridges.bind(weather);
|
|
1226
|
+
visual = options.visual?.create({ host: lent, locale, weather: { sample: () => weather.sample() } });
|
|
1227
|
+
if (visual && !state.fog) visual.setLayer("fog", false);
|
|
1057
1228
|
publish();
|
|
1058
1229
|
const offFrame = lent.onFrame((dt) => {
|
|
1059
1230
|
weather.advance(dt);
|
|
1060
1231
|
publish();
|
|
1232
|
+
bridges?.update(dt);
|
|
1233
|
+
visual?.update(dt);
|
|
1061
1234
|
});
|
|
1062
1235
|
return () => {
|
|
1236
|
+
visual?.dispose();
|
|
1237
|
+
visual = void 0;
|
|
1063
1238
|
off?.();
|
|
1064
1239
|
offFrame();
|
|
1240
|
+
bridges?.dispose();
|
|
1241
|
+
bridges = void 0;
|
|
1065
1242
|
host = null;
|
|
1066
1243
|
};
|
|
1067
1244
|
}
|
|
@@ -1071,17 +1248,27 @@ function createWeatherTestModule(options = {}) {
|
|
|
1071
1248
|
export {
|
|
1072
1249
|
CLIMATES,
|
|
1073
1250
|
DAY_REAL_SECONDS,
|
|
1251
|
+
DEFAULT_BRIDGE_RULES,
|
|
1074
1252
|
DEFAULT_DRY_OUT_SECONDS,
|
|
1253
|
+
DEFAULT_RAIN_SOUND,
|
|
1075
1254
|
DEFAULT_START_HOUR,
|
|
1076
1255
|
DEFAULT_TIME_SCALE,
|
|
1077
1256
|
DEFAULT_WET_RISE_SECONDS,
|
|
1257
|
+
DEFAULT_WIND_SOUND,
|
|
1078
1258
|
DRY_VISIBILITY_METERS,
|
|
1079
1259
|
FLASH_END_SECONDS,
|
|
1080
1260
|
GAME_DAY_SECONDS,
|
|
1081
1261
|
NIGHT_SIGHT_LOSS,
|
|
1262
|
+
RAIN_HISS_GAME,
|
|
1263
|
+
RAIN_LOOP,
|
|
1082
1264
|
SPEED_OF_SOUND,
|
|
1083
1265
|
STATE_VALUE_KEYS,
|
|
1266
|
+
THUNDER,
|
|
1267
|
+
WEATHER_BANK,
|
|
1268
|
+
WEATHER_LOOPS,
|
|
1269
|
+
WEATHER_SOUNDS,
|
|
1084
1270
|
WEATHER_STATES,
|
|
1271
|
+
WIND_LOOP,
|
|
1085
1272
|
blendValues,
|
|
1086
1273
|
createLightningStream,
|
|
1087
1274
|
createRng,
|
|
@@ -1089,18 +1276,24 @@ export {
|
|
|
1089
1276
|
createStream,
|
|
1090
1277
|
createTimeline,
|
|
1091
1278
|
createWeather,
|
|
1279
|
+
createWeatherBridges,
|
|
1092
1280
|
createWeatherRegistry,
|
|
1281
|
+
createWeatherSound,
|
|
1093
1282
|
createWeatherTestModule,
|
|
1094
1283
|
createWetness,
|
|
1095
1284
|
dayFractionAt,
|
|
1096
1285
|
daylight,
|
|
1097
1286
|
deriveEffects,
|
|
1287
|
+
environmentOf,
|
|
1098
1288
|
flashIntensity,
|
|
1099
1289
|
heatIndexC,
|
|
1100
1290
|
heatStress,
|
|
1291
|
+
rainVolume,
|
|
1101
1292
|
streamSeed,
|
|
1293
|
+
strikePosition,
|
|
1102
1294
|
thunderDelay,
|
|
1103
1295
|
valuesOf,
|
|
1104
|
-
weatherBenchTextOf
|
|
1296
|
+
weatherBenchTextOf,
|
|
1297
|
+
windVolume
|
|
1105
1298
|
};
|
|
1106
1299
|
//# sourceMappingURL=index.js.map
|