diff --git a/index.html b/index.html index cdce99d..86c4c08 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,7 @@ - Babylon.js Project + Truligon - Anomaly + Card System - - - - - + \ No newline at end of file diff --git a/package.json b/package.json index a1925c2..aed46b1 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,22 @@ { - "name": "babylonjs-project", + "name": "truligon", "version": "1.0.0", - "description": "A Babylon.js 3D project", - "main": "app.js", + "description": "Truligon Game - Anomaly + Card System", + "type": "module", "scripts": { - "start": "http-server -c-1 -p 5687" + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview" }, "dependencies": { - "http-server": "^14.1.1" + "@babylonjs/core": "^6.47.0", + "@babylonjs/gui": "^6.47.0", + "@babylonjs/loaders": "^6.47.0", + "@babylonjs/materials": "^6.47.0" + }, + "devDependencies": { + "typescript": "^5.3.3", + "vite": "^5.0.12", + "@types/node": "^20.11.0" } } \ No newline at end of file diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..96c0fda --- /dev/null +++ b/src/main.ts @@ -0,0 +1,95 @@ +import { Engine, Scene, Vector3, MeshBuilder, Color4, FreeCamera, HemisphericLight, ActionManager, ExecuteCodeAction } from "@babylonjs/core"; +import "@babylonjs/loaders"; +import { AdvancedDynamicTexture, Button, Control } from "@babylonjs/gui"; + +// 1) Boilerplate +const canvas = document.getElementById("renderCanvas") as HTMLCanvasElement; +const engine = new Engine(canvas, true); +const scene = new Scene(engine); + +// 2) Camera & Light +const camera = new FreeCamera("cam", new Vector3(0, 5, -10), scene); +camera.setTarget(Vector3.Zero()); +camera.attachControl(canvas, true); +new HemisphericLight("light", new Vector3(0, 1, 0), scene); + +// 3) Ground & Zone +MeshBuilder.CreateGround("ground", { width: 20, height: 20 }, scene); +const zone = MeshBuilder.CreateBox("zone", { size: 4 }, scene); +zone.position = new Vector3(0, 1, 0); +zone.isVisible = false; + +// 4) Anomaly state +let inAnomaly = false; +const ANOMALY_DUR = 5000; // 5 s +const normalSpeed = 1; +let currentSpeed = normalSpeed; + +// 5) GUI – single "Freeze Time" card +const guiTex = AdvancedDynamicTexture.CreateFullscreenUI("UI"); +const btn = Button.CreateSimpleButton("card", "❄️ Freeze Time"); +btn.width = "150px"; +btn.height = "40px"; +btn.color = "white"; +btn.background = "#444"; +btn.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_RIGHT; +btn.verticalAlignment = Control.VERTICAL_ALIGNMENT_BOTTOM; +btn.top = "-20px"; +btn.left = "-20px"; +guiTex.addControl(btn); + +// 6) Card effect: pause physics 3 s +btn.onPointerUpObservable.add(() => { + if (!inAnomaly) return; + scene.getPhysicsEngine()?.setTimeStep(0); // pause + setTimeout(() => { + scene.getPhysicsEngine()?.setTimeStep(1/60); // resume + }, 3000); +}); + +// 7) Enter/Exit Anomaly +zone.actionManager = new ActionManager(scene); +zone.actionManager.registerAction( + new ExecuteCodeAction( + { trigger: ActionManager.OnIntersectionEnterTrigger, parameter: zone }, + () => startAnomaly() + ) +); + +// 8) Anomaly logic +function startAnomaly() { + if (inAnomaly) return; + inAnomaly = true; + // fog + scene.fogMode = Scene.FOGMODE_EXP; + scene.fogColor = new Color4(0.05, 0.05, 0.1, 1); + scene.fogDensity = 0.1; + // slow-mo + currentSpeed = normalSpeed * 0.5; + + // automatically end + setTimeout(endAnomaly, ANOMALY_DUR); +} + +function endAnomaly() { + inAnomaly = false; + scene.fogDensity = 0; + currentSpeed = normalSpeed; +} + +// 9) Simple "movement" demo (WASD) +scene.onBeforeRenderObservable.add(() => { + const dt = engine.getDeltaTime() / 1000; + const dir = new Vector3( + (camera._keys.shift().includes(68) ? 1 : camera._keys.shift().includes(65) ? -1 : 0), + 0, + (camera._keys.shift().includes(83) ? 1 : camera._keys.shift().includes(87) ? -1 : 0) + ); + camera.position.addInPlace(dir.normalize().scale(currentSpeed * dt * 5)); +}); + +// 10) Render loop +engine.runRenderLoop(() => scene.render()); + +// 11) Resize handler +window.addEventListener("resize", () => engine.resize()); \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a00bb2c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } + }, + "include": ["src"] +} \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..8a885da --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from 'vite'; +import { resolve } from 'path'; + +export default defineConfig({ + server: { + port: 5687 + }, + resolve: { + alias: { + '@': resolve(__dirname, './src') + } + } +}); \ No newline at end of file