Add background music selection and update game assets

Add configurable background music per level with song selector in the
level editor General tab. Update ship model, add base3 model, add
song2/song3 audio tracks, and clean up level config formatting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Michael Mainguy 2026-03-03 06:13:37 -06:00
parent a7799a9c71
commit 208d735ef4
29 changed files with 476 additions and 519 deletions

View File

@ -106,15 +106,15 @@
"applyGravity": false,
"updateUpVectorFromRotation": false,
"rotation": [
0.23466138679888465,
0.48668946590326523,
0.3870449848810084,
0.05980234407784223,
0
],
"speed": 2000,
"speed": 10,
"position": [
-19666.901457088374,
17401.223711429564,
-55872.0430330369
-19.027983524409535,
129.4532146827724,
-317.01273902922264
],
"upVector": [
0,

View File

@ -1,279 +0,0 @@
{
"meshes": [
{
"name": "New Box",
"id": "1679685b-ca9c-4a1c-8161-9f6064cb1d7c",
"uniqueId": 1764787809874,
"type": "Mesh",
"position": [
0,
0,
0
],
"rotation": [
0,
0,
0
],
"scaling": [
1,
1,
1
],
"localMatrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
],
"isEnabled": true,
"isVisible": true,
"infiniteDistance": false,
"pickable": true,
"receiveShadows": true,
"billboardMode": 0,
"visibility": 1,
"alwaysSelectAsActiveMesh": false,
"checkCollisions": false,
"ellipsoid": [
0.5,
1,
0.5
],
"ellipsoidOffset": [
0,
0,
0
],
"doNotSyncBoundingInfo": false,
"isBlocker": false,
"sideOrientation": 1,
"isUnIndexed": false,
"geometryUniqueId": 1764787809875,
"geometryId": "76c7442d-fb7e-4a05-b1c5-9c27b0beb0dc",
"subMeshes": null,
"materialUniqueId": 46,
"materialId": "default material",
"metadata": {
"type": "Box",
"width": 100,
"depth": 100,
"height": 100,
"sideOrientation": 0
},
"instances": [],
"animations": [],
"ranges": [],
"layerMask": 268435455,
"alphaIndex": 1.7976931348623157e+308,
"hasVertexAlpha": false,
"overlayAlpha": 1,
"overlayColor": [
0,
0,
0
],
"applyFog": true,
"delayLoadingFile": "assets/example.scene/geometries/76c7442d-fb7e-4a05-b1c5-9c27b0beb0dc.babylonbinarymeshdata",
"boundingBoxMaximum": [
50,
50,
50
],
"boundingBoxMinimum": [
-50,
-50,
-50
],
"_binaryInfo": {
"positionsAttrDesc": {
"count": 72,
"stride": 3,
"offset": 0,
"dataType": 1
},
"normalsAttrDesc": {
"count": 72,
"stride": 3,
"offset": 288,
"dataType": 1
},
"uvsAttrDesc": {
"count": 48,
"stride": 2,
"offset": 576,
"dataType": 1
},
"indicesAttrDesc": {
"count": 36,
"stride": 1,
"offset": 768,
"dataType": 0
},
"subMeshesAttrDesc": {
"count": 1,
"stride": 5,
"offset": 912,
"dataType": 0
}
},
"positions": null,
"normals": null,
"uvs": null,
"hasUVs": true,
"indices": null
}
],
"transformNodes": [],
"cameras": [],
"lights": [],
"materials": [
{
"tags": null,
"ambient": [
0,
0,
0
],
"diffuse": [
1,
1,
1
],
"specular": [
1,
1,
1
],
"emissive": [
0,
0,
0
],
"specularPower": 64,
"useAlphaFromDiffuseTexture": false,
"useEmissiveAsIllumination": false,
"linkEmissiveWithDiffuse": false,
"useSpecularOverAlpha": false,
"useReflectionOverAlpha": false,
"disableLighting": false,
"useObjectSpaceNormalMap": false,
"useParallax": false,
"useParallaxOcclusion": false,
"parallaxScaleBias": 0.05,
"roughness": 0,
"indexOfRefraction": 0.98,
"invertRefractionY": true,
"alphaCutOff": 0.4,
"useLightmapAsShadowmap": false,
"useReflectionFresnelFromSpecular": false,
"useGlossinessFromSpecularMapAlpha": false,
"maxSimultaneousLights": 32,
"invertNormalMapX": false,
"invertNormalMapY": false,
"twoSidedLighting": false,
"applyDecalMapAfterDetailMap": false,
"id": "default material",
"name": "default material",
"checkReadyOnEveryCall": false,
"checkReadyOnlyOnce": false,
"state": "",
"alpha": 1,
"backFaceCulling": true,
"cullBackFaces": true,
"_alphaMode": [
2
],
"_needDepthPrePass": false,
"disableDepthWrite": false,
"disableColorWrite": false,
"forceDepthWrite": false,
"depthFunction": 0,
"separateCullingPass": false,
"fogEnabled": true,
"pointSize": 1,
"zOffset": 0,
"zOffsetUnits": 0,
"pointsCloud": false,
"fillMode": 0,
"_isVertexOutputInvariant": false,
"stencil": {
"tags": null,
"func": 519,
"backFunc": 519,
"funcRef": 1,
"funcMask": 255,
"opStencilFail": 7680,
"opDepthFail": 7680,
"opStencilDepthPass": 7681,
"backOpStencilFail": 7680,
"backOpDepthFail": 7680,
"backOpStencilDepthPass": 7681,
"mask": 255,
"enabled": false
},
"uniqueId": 46,
"plugins": {
"DetailMapConfiguration": {
"tags": null,
"diffuseBlendLevel": 1,
"roughnessBlendLevel": 1,
"bumpLevel": 1,
"normalBlendMethod": 0,
"isEnabled": false,
"name": "DetailMap",
"priority": 140,
"resolveIncludes": false,
"registerForExtraEvents": false
}
}
}
],
"geometries": {
"boxes": [],
"spheres": [],
"cylinders": [],
"toruses": [],
"grounds": [],
"planes": [],
"torusKnots": [],
"vertexData": []
},
"metadata": {
"type": "Box",
"width": 100,
"depth": 100,
"height": 100,
"sideOrientation": 0
},
"basePoseMatrix": [
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
0,
0,
0,
0,
1
]
}

View File

@ -16,9 +16,9 @@
0
],
"scaling": [
100.00000000000159,
-100,
100.00000000000159
1,
-1,
1
],
"localMatrix": [
1,

View File

@ -17,9 +17,9 @@
0
],
"scaling": [
100,
100,
-100
1,
1,
-1
],
"localMatrix": [
1,

View File

@ -17,9 +17,9 @@
0
],
"scaling": [
100,
100,
-100
1,
1,
-1
],
"localMatrix": [
1,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 74 KiB

File diff suppressed because one or more lines are too long

View File

@ -5,13 +5,13 @@
import { loadScene, scriptsDictionary, scriptAssetsCache, _applyScriptsForObject, _removeRegisteredScriptInstance, _preloadScriptsAssets } from "babylonjs-editor-tools";
import * as scripts_editorScripts_AsteroidComponent from "./scripts/editorScripts/AsteroidComponent";
import * as scripts_editorScripts_BaseComponent from "./scripts/editorScripts/BaseComponent";
import * as scripts_editorScripts_ShipComponent from "./scripts/editorScripts/ShipComponent";
import * as scripts_editorScripts_BaseComponent from "./scripts/editorScripts/BaseComponent";
export const scriptsMap = {
"scripts/editorScripts/AsteroidComponent.ts": scripts_editorScripts_AsteroidComponent,
"scripts/editorScripts/BaseComponent.ts": scripts_editorScripts_BaseComponent,
"scripts/editorScripts/ShipComponent.ts": scripts_editorScripts_ShipComponent
"scripts/editorScripts/ShipComponent.ts": scripts_editorScripts_ShipComponent,
"scripts/editorScripts/BaseComponent.ts": scripts_editorScripts_BaseComponent
};
export { loadScene, scriptsDictionary, scriptAssetsCache, _applyScriptsForObject, _removeRegisteredScriptInstance, _preloadScriptsAssets };

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -9,273 +9,270 @@
"type": "default"
},
"ship": {
"position": [
0,
1,
0
],
"rotation": [
0,
0,
0
],
"linearVelocity": [
0,
0,
0
],
"angularVelocity": [
0,
0,
0
]
"position": [0, 1, 0],
"rotation": [0, 0, 0]
},
"startBase": {
"position": [
0,
0,
0
],
"position": [0, 0, 0],
"baseGlbPath": "base.glb"
},
"sun": {
"position": [
0,
0,
400
],
"diameter": 50,
"intensity": 1000000
"position": [0, 0, 400],
"diameter": 50
},
"planets": [],
"targets": [
{
"id": "ORBIT",
"name": "ORBIT",
"position": [0, 0, 0]
},
{
"id": "LINEAR",
"name": "LINEAR",
"position": [0, 0, 0]
}
],
"asteroids": [
{
"id": "asteroid-0",
"position": [
242.60734209985543,
-114.56996058926651,
5.575229357062
],
"mass": 40,
"scale": 2,
"linearVelocity": [
-170.167175139332553,
80.177863609194048,
-0.39450965492725215
],
"angularVelocity": [
-0.834980024785148,
0.9648009938830251,
0.8185653748494373
]
"position": [75, 85, -65],
"linearVelocity": [-20, 15, 25],
"angularVelocity": [-0.8, 0.9, 0.8],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-1",
"position": [
145.90971366777896,
42.273817290099984,
-244.80503221456152
],
"mass": 120,
"scale": 6,
"linearVelocity": [
-14.737555578618144,
-42.168846343154079,
240.72643991613985
],
"angularVelocity": [
0.575649251710729,
-2.8551046445434349,
-0.9477761112717422
]
"position": [-120, 110, -100],
"linearVelocity": [18, -12, 22],
"angularVelocity": [0.5, -2.8, -0.9],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-2",
"position": [
195.05992969157123,
-311.0584087077698,
-22.40662780090249
],
"mass": 80,
"scale": 4,
"linearVelocity": [
-160.81570103491442,
9.660316715266058,
160.9316276535952197
],
"angularVelocity": [
0.8587973467645904,
0.25620436829463733,
-0.7705721105608303
]
"position": [160, -140, 100],
"linearVelocity": [-25, 20, -15],
"angularVelocity": [0.8, 0.2, -0.7],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-3",
"position": [
-0.9357515100775112,
85.76554222686204,
249.4670613777975
],
"mass": 347,
"scale": 17.34408913479813,
"linearVelocity": [
0.07109432360434195,
-6.440116659897093,
-18.953420645560346
],
"angularVelocity": [
0.19650221972006143,
0.4226089665809898,
-0.9419176203015098
]
"position": [-180, 200, -160],
"linearVelocity": [12, -8, 15],
"angularVelocity": [0.1, 0.4, -0.9],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-4",
"position": [
-254.14456477364413,
54.65967750105119,
82.65652287437858
],
"mass": 80,
"scale": 4,
"linearVelocity": [
22.372081486064396,
-400.723605553550473,
-7.2761676675924445
],
"angularVelocity": [
-0.22039903827783025,
0.03062354927084643,
0.3628209366655213
]
"position": [90, -80, 85],
"linearVelocity": [-22, 18, -20],
"angularVelocity": [-0.2, 0.03, 0.3],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-5",
"position": [
-257.7249224576784,
-112.97325792551102,
-92.25372143357285
],
"mass": 240,
"scale": 12,
"linearVelocity": [
17.764361846647077,
7.855903788127005,
6.358828139777149
],
"angularVelocity": [
-0.27982741337355455,
0.2465507084870353,
-0.8489416083688623
]
"position": [-200, 140, -120],
"linearVelocity": [15, -10, 18],
"angularVelocity": [-0.2, 0.2, -0.8],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-6",
"position": [
-61.74000302102928,
103.75532261403117,
-224.6843746923246
],
"mass": 289,
"scale": 14.438006716048399,
"linearVelocity": [
4.573571795825104,
-7.611901885044768,
16.644154013167135
],
"angularVelocity": [
-0.41949593751738457,
-0.5881266007071146,
0.2671577602439994
]
"position": [220, -230, 150],
"linearVelocity": [-10, 8, -12],
"angularVelocity": [-0.4, -0.5, 0.2],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-7",
"position": [
16.846663100767792,
72.36836836065181,
-271.36235273889974
],
"mass": 200,
"scale": 10,
"linearVelocity": [
220.2776861733199087,
-345.412726361379603,
-20.580688530433683
],
"angularVelocity": [
-0.5793176374486806,
0.8207961833131412,
-0.034658037798875885
]
"position": [-100, 120, -85],
"linearVelocity": [20, -15, 18],
"angularVelocity": [-0.5, 0.8, -0.03],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-8",
"position": [
129.11110725214024,
91.10691458736655,
205.0668479159754
],
"mass": 200,
"scale": 10,
"linearVelocity": [
-10.330594112594069,
-7.209743461671342,
160.4080567261488
],
"angularVelocity": [
-2.572098306083443,
0.6581860817605101,
-0.7141435682550208
]
"position": [170, 150, -100],
"linearVelocity": [-12, -18, 22],
"angularVelocity": [-2.5, 0.6, -0.7],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-9",
"position": [
-300.953057070289603,
225.21952155696817,
139.05608152400566
],
"mass": 283,
"scale": 14.151176153817078,
"linearVelocity": [
1.9861965590557589,
-314.387724003424648,
-8.922954201633985
],
"angularVelocity": [
0.7016416714654072,
-4.8069811132136699,
-0.16093262088047533
]
"position": [-240, 180, 140],
"linearVelocity": [8, -12, -10],
"angularVelocity": [0.7, -4.8, -0.1],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-10",
"position": [
300.953057070289603,
225.21952155696817,
139.05608152400566
],
"mass": 240,
"scale": 12,
"linearVelocity": [
100.9861965590557589,
-314.387724003424648,
-240.922954201633985
],
"angularVelocity": [
0.7016416714654072,
-4.8069811132136699,
-0.16093262088047533
]
"position": [280, -200, 150],
"linearVelocity": [-15, 10, -8],
"angularVelocity": [0.7, -4.8, -0.1],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-11",
"position": [
300.953057070289603,
-225.21952155696817,
69.05608152400566
],
"mass": 600,
"scale": 30,
"linearVelocity": [
100.9861965590557589,
-214.387724003424648,
140.922954201633985
],
"angularVelocity": [
0.7016416714654072,
-4.8069811132136699,
-0.16093262088047533
]
"position": [-300, 200, -150],
"linearVelocity": [10, -6, 8],
"angularVelocity": [0.7, -4.8, -0.1],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-12",
"mass": 100,
"scale": 5,
"position": [130, -95, 70],
"linearVelocity": [-55, 40, 65],
"angularVelocity": [1.2, -0.8, 0.5],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-13",
"mass": 160,
"scale": 8,
"position": [-85, 160, 120],
"linearVelocity": [48, -35, 58],
"angularVelocity": [-0.6, 1.5, -1.2],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-14",
"mass": 60,
"scale": 3,
"position": [210, 95, -180],
"linearVelocity": [-62, 50, -42],
"angularVelocity": [0.9, 0.4, -1.8],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-15",
"mass": 180,
"scale": 9,
"position": [-145, -175, 85],
"linearVelocity": [38, 52, -45],
"angularVelocity": [-1.1, -0.7, 0.9],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-16",
"mass": 140,
"scale": 7,
"position": [55, 230, -195],
"linearVelocity": [-45, -58, 52],
"angularVelocity": [0.3, 2.1, -0.6],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-17",
"mass": 220,
"scale": 11,
"position": [-270, -110, -160],
"linearVelocity": [52, 38, 48],
"angularVelocity": [-0.8, 0.5, 1.4],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-18",
"mass": 80,
"scale": 4,
"position": [185, -250, 95],
"linearVelocity": [-48, 62, -38],
"angularVelocity": [1.6, -1.2, -0.4],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-19",
"mass": 260,
"scale": 13,
"position": [-110, 85, 280],
"linearVelocity": [35, -42, -55],
"angularVelocity": [-0.5, 0.9, 1.1],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-20",
"mass": 120,
"scale": 6,
"position": [320, 140, -85],
"linearVelocity": [-58, -45, 40],
"angularVelocity": [0.7, -1.8, 0.3],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-21",
"mass": 300,
"scale": 15,
"position": [-195, -290, 120],
"linearVelocity": [42, 55, -48],
"angularVelocity": [-1.3, 0.6, -0.9],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-22",
"mass": 160,
"scale": 8,
"position": [95, -65, -310],
"linearVelocity": [-40, 58, 65],
"angularVelocity": [0.4, -0.3, 2.2],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "asteroid-23",
"mass": 200,
"scale": 10,
"position": [-350, 165, 90],
"linearVelocity": [55, -38, -52],
"angularVelocity": [-0.9, 1.7, 0.5],
"targetId": "ORBIT",
"targetMode": "orbit"
}
]
}

189
public/levels/template.json Normal file
View File

@ -0,0 +1,189 @@
{
"sun": {
"diameter": 50,
"position": [
0,
0,
400
]
},
"ship": {
"position": [
0,
2,
0
],
"rotation": [
0,
0,
0
]
},
"planets": [],
"version": "1.0",
"metadata": {
"author": "BabylonJS Editor",
"description": "Exported from Editor"
},
"targets": [
{
"id": "ORBIT",
"name": "ORBIT",
"position": [
0,
0,
0
]
},
{
"id": "LINEAR",
"name": "LINEAR",
"position": [
0,
-46.40267541850123,
0
]
}
],
"asteroids": [
{
"id": "Asteroid",
"mass": 100,
"scale": 5,
"position": [
0,
55.91356273231697,
-84.76095007459317
],
"linearVelocity": [
0,
0,
-30
],
"angularVelocity": [
0,
0,
5
],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "Asteroid (Mesh Instance)",
"mass": 100,
"scale": 5,
"position": [
-216.86571629860342,
6.395638981779044,
0
],
"linearVelocity": [
0,
0,
20
],
"angularVelocity": [
1,
0,
0
]
},
{
"id": "Asteroid (Mesh Instance)",
"mass": 100,
"scale": 5,
"position": [
125.92973388713749,
0,
0
],
"linearVelocity": [
0,
0,
30
],
"angularVelocity": [
0,
0,
0
],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "Asteroid (Mesh Instance)",
"mass": 1,
"scale": 25,
"position": [
121.55444252370417,
3.373869538878104,
-350.47951942991017
],
"linearVelocity": [
0,
0,
50
],
"angularVelocity": [
0,
0,
10
],
"targetId": "ORBIT",
"targetMode": "orbit"
},
{
"id": "Asteroid (Mesh Instance)",
"mass": 100,
"scale": 5,
"position": [
-50.27889543892182,
2.934664213442815,
57.70721855086853
],
"linearVelocity": [
100,
0,
10
],
"angularVelocity": [
0,
2,
0
]
},
{
"id": "Asteroid (Mesh Instance)",
"mass": 210,
"scale": 5,
"position": [
-154.4148281169747,
-133.4543443541567,
-230.29621395184932
],
"linearVelocity": [
0,
30,
0
],
"angularVelocity": [
0.1,
1,
-1
],
"targetId": "ORBIT",
"targetMode": "orbit"
}
],
"startBase": {
"position": [
0,
0,
0
],
"baseGlbPath": "base.glb"
},
"timestamp": "2025-12-05T14:49:29.176Z",
"difficulty": "rookie",
"useOrbitConstraints": true
}

View File

@ -22,7 +22,7 @@
let level: CloudLevelEntry | null = null;
let config: LevelConfig | null = null;
let error = '';
let activeTab = 'ship';
let activeTab = 'general';
// Message state
let message = '';
@ -30,6 +30,7 @@
let showMessage = false;
const tabs = [
{ id: 'general', label: '⚙️ General' },
{ id: 'ship', label: '🚀 Ship' },
{ id: 'base', label: '🛬 Base' },
{ id: 'sun', label: '☀️ Sun' },
@ -39,6 +40,8 @@
{ id: 'planets', label: '🪐 Planets' }
];
const musicOptions = ['song1.mp3', 'song2.mp3','song3.mp3'];
onMount(async () => {
await loadLevel();
});
@ -84,7 +87,12 @@
try {
const service = CloudLevelService.getInstance();
const updated = await service.updateLevelAsAdmin(level.id, { config });
// Convert empty strings to undefined before saving
const cleanConfig = {
...config,
backgroundMusic: config.backgroundMusic || undefined
};
const updated = await service.updateLevelAsAdmin(level.id, { config: cleanConfig });
if (updated) {
level = updated;
@ -170,7 +178,23 @@
<!-- Tab Content -->
<div class="tab-content">
{#if activeTab === 'ship'}
{#if activeTab === 'general'}
<Section title="General Settings">
<div class="field-row">
<label for="backgroundMusic">Background Music</label>
<select id="backgroundMusic" bind:value={config.backgroundMusic}>
<option value="">Default (song1.mp3)</option>
{#each musicOptions as song}
<option value={song}>{song}</option>
{/each}
</select>
</div>
<div class="field-row">
<label for="difficulty">Difficulty</label>
<input id="difficulty" type="text" bind:value={config.difficulty} />
</div>
</Section>
{:else if activeTab === 'ship'}
<ShipConfigEditor bind:config={config.ship} />
{:else if activeTab === 'base'}
<BaseConfigEditor config={config.startBase} onToggle={handleBaseToggle} />
@ -234,4 +258,27 @@
.tab-content {
min-height: 300px;
}
.field-row {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 0.75rem;
}
.field-row label {
min-width: 150px;
color: var(--color-text-secondary, #888);
}
.field-row select,
.field-row input {
flex: 1;
padding: 0.5rem;
background: var(--color-bg-tertiary, #252540);
border: 1px solid var(--color-border, #333);
border-radius: 4px;
color: var(--color-text-primary, #fff);
max-width: 300px;
}
</style>

View File

@ -9,14 +9,10 @@ if (queryLevel && ['debug', 'info', 'warn', 'error'].includes(queryLevel)) {
// Check localStorage for custom level (enables production debugging)
const storedLevel = localStorage.getItem('log-level');
console.log(storedLevel);
// Set level: localStorage override > environment default
if (storedLevel) {
log.setLevel(storedLevel as log.LogLevelDesc);
} else {
const isDev = window.location.hostname === 'localhost' ||
window.location.hostname.includes('dev.');
log.setLevel(isDev ? 'debug' : 'warn');
}
export default log;

View File

@ -64,6 +64,9 @@ function createMainScene(engine: Engine): void {
//DefaultScene.MainScene.performancePriority = ScenePerformancePriority.Intermediate;
DefaultScene.MainScene.autoClear = false;
DefaultScene.MainScene.autoClearDepthAndStencil = false;
//const hdrTexture = new HDRCubeTexture("/assets/untitled.hdr", DefaultScene.MainScene, 2048);
//DefaultScene.MainScene.environmentTexture = hdrTexture;
//DefaultScene.MainScene.createDefaultSkybox(hdrTexture, true, 1000);
}
async function setupPhysics(): Promise<void> {

View File

@ -144,6 +144,7 @@ export interface LevelConfig {
version: string;
difficulty: string;
timestamp?: string; // ISO date string
backgroundMusic?: string; // Audio filename e.g., "song1.mp3" - defaults to "song1.mp3"
metadata?: {
author?: string;
description?: string;

View File

@ -358,7 +358,9 @@ export class Level1 implements Level {
this._hintSystem.setAudioEngine(audioEngine);
// Load background music (uses prefetched audio if available)
const musicUrl = "/assets/themes/default/audio/song1.mp3";
const musicFile = this._levelConfig.backgroundMusic || "song1.mp3";
log.debug(musicFile);
const musicUrl = `/assets/themes/default/audio/${musicFile}`;
this._backgroundMusic = await audioEngine.createSoundAsync(
"background",
getAudioSource(musicUrl),

View File

@ -9,6 +9,7 @@ const AUDIO_FILES = [
`${AUDIO_BASE}/shot.mp3`,
`${AUDIO_BASE}/collision.mp3`,
`${AUDIO_BASE}/song1.mp3`,
`${AUDIO_BASE}/song2.mp3`,
];
// Cache for prefetched audio buffers

BIN
themes/default/Untitled.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

BIN
themes/default/base3.blend Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.