Skip to content

Commit 5695fbb

Browse files
committed
perf: optimize engine performance by scaling particle counts, resolution, and hand tracking frequency based on device tier
1 parent 5a0b905 commit 5695fbb

2 files changed

Lines changed: 30 additions & 27 deletions

File tree

app.min.js

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
const DEVICE_THREAD_HINT = navigator.hardwareConcurrency || 4;
77
const DEVICE_MEMORY_HINT = navigator.deviceMemory || 4;
88
const PERF_TIER = Math.min(2, DEVICE_THREAD_HINT / 4) * Math.min(1.5, DEVICE_MEMORY_HINT / 4);
9-
const PARTICLE_COUNT = 8000;
10-
const BATTLE_PARTICLE_SCALE = PERF_TIER >= 1.5 ? 0.58 : 0.5;
9+
const PARTICLE_COUNT = PERF_TIER >= 1.5 ? 6000 : 4200;
10+
const BATTLE_PARTICLE_SCALE = PERF_TIER >= 1.5 ? 0.46 : 0.36;
1111
const SWARM_FORCE = 0.5;
1212
const SHAPE_FORCE = 0.2;
1313
const DAMPING = 0.96;
@@ -32,7 +32,8 @@ const COLOR_NEBULA = { r: 0.72, g: 0.32, b: 1.0 };
3232
const COLOR_NEBULA_CORE = { r: 0.96, g: 0.9, b: 1.0 };
3333
const COLOR_FLASH = { r: 1.0, g: 1.0, b: 1.0 };
3434
const COLOR_BATTLE = { r: 1.0, g: 0.9, b: 0.2 };
35-
const RENDER_PIXEL_RATIO = Math.min(window.devicePixelRatio || 1, PERF_TIER >= 1.4 ? 1.15 : 1.0);
35+
const RENDER_PIXEL_RATIO = Math.min(window.devicePixelRatio || 1, PERF_TIER >= 1.5 ? 1.0 : 0.85);
36+
const HAND_TRACK_INTERVAL_MS = PERF_TIER >= 1.5 ? 38 : 55;
3637
const HAND_PERSIST_MS = 900; // keep hand "active" briefly after tracker flicker
3738
const MAX_GPU_EXPLOSIONS = 4;
3839

@@ -69,15 +70,15 @@ const particleOwner = new Uint8Array(PARTICLE_COUNT);
6970
for (let i = 0; i < PARTICLE_COUNT; i++) particleOwner[i] = i % 2;
7071

7172
// === BATTLE / KAMEHAMEHA 2.0 — Two-Player Combat ===
72-
const BATTLE_PROJECTILE_COUNT = Math.floor(PARTICLE_COUNT * (PERF_TIER >= 1.5 ? 0.065 : 0.05));
73+
const BATTLE_PROJECTILE_COUNT = Math.floor(PARTICLE_COUNT * (PERF_TIER >= 1.5 ? 0.05 : 0.038));
7374
const BATTLE_SHIELD_RADIUS = 155;
74-
const BATTLE_PROJECTILE_SPEED = 24;
75+
const BATTLE_PROJECTILE_SPEED = 18;
7576
const BATTLE_HIT_RADIUS = 60;
7677
const BATTLE_ARROW_LENGTH = 520;
7778
const BATTLE_ARROW_HEAD = 170;
7879
const BATTLE_ARROW_RECOVER_TIME = 0.22;
7980
const BATTLE_DESPAWN_MARGIN = 360;
80-
const BATTLE_EXPLOSION_MASK = 15;
81+
const BATTLE_EXPLOSION_MASK = PERF_TIER >= 1.5 ? 31 : 63;
8182
const BATTLE_TINT_P1 = { r: 0.44, g: 0.36, b: 1.0 };
8283
const BATTLE_TINT_P2 = { r: 0.82, g: 0.28, b: 1.0 };
8384
const BATTLE_EXPLOSION_DEFAULT = { r: 1, g: 0.7, b: 0.2 };
@@ -213,7 +214,7 @@ scene.add(particles);
213214

214215
// --- Starfield ---
215216
const starGeo = new THREE.BufferGeometry();
216-
const STAR_COUNT = 5000;
217+
const STAR_COUNT = PERF_TIER >= 1.5 ? 3500 : 2200;
217218
const sPos = new Float32Array(STAR_COUNT * 3);
218219
const sCol = new Float32Array(STAR_COUNT * 3);
219220
for (let i = 0; i < STAR_COUNT; i++) {
@@ -555,8 +556,7 @@ function chooseSingleHandSide(d) {
555556

556557
function applyHandDetection(side, d, now) {
557558
const targetHand = hands[side];
558-
// Much snappier lerp so particles feel like they follow the finger instantly
559-
const lerpFactor = (now - targetHand.lastSeen > 250) ? 0.7 : 0.82;
559+
const lerpFactor = (now - targetHand.lastSeen > 280) ? 0.45 : 0.56;
560560
const prevX = targetHand.pos.x;
561561
const prevY = targetHand.pos.y;
562562
const prevZ = targetHand.pos.z;
@@ -572,7 +572,7 @@ function applyHandDetection(side, d, now) {
572572
if (hadPrevious) {
573573
targetHand.vel.set(targetHand.pos.x - prevX, targetHand.pos.y - prevY, targetHand.pos.z - prevZ);
574574
const frameSpeed = targetHand.vel.length() * (16.67 / dt);
575-
targetHand.speed += (frameSpeed - targetHand.speed) * 0.35;
575+
targetHand.speed += (frameSpeed - targetHand.speed) * 0.22;
576576
} else {
577577
targetHand.vel.set(0, 0, 0);
578578
targetHand.speed = 0;
@@ -1097,17 +1097,20 @@ function onResults(results) {
10971097

10981098
const handTracker = new Hands({ locateFile: (file) => `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}` });
10991099
// Lower confidence so single extended index finger is reliably detected
1100-
handTracker.setOptions({ maxNumHands: 2, modelComplexity: 1, minDetectionConfidence: 0.35, minTrackingConfidence: 0.3 });
1100+
handTracker.setOptions({ maxNumHands: 2, modelComplexity: PERF_TIER >= 1.5 ? 1 : 0, minDetectionConfidence: 0.35, minTrackingConfidence: 0.3 });
11011101
handTracker.onResults(onResults);
11021102
let isProcessingFrame = false;
1103+
let lastHandFrameAt = 0;
11031104
const cameraUtils = new Camera(videoElement, {
11041105
onFrame: async () => {
1105-
if (isProcessingFrame) return;
1106+
const now = performance.now();
1107+
if (isProcessingFrame || now - lastHandFrameAt < HAND_TRACK_INTERVAL_MS) return;
1108+
lastHandFrameAt = now;
11061109
isProcessingFrame = true;
11071110
try { await handTracker.send({ image: videoElement }); } catch (e) {}
11081111
finally { isProcessingFrame = false; }
11091112
},
1110-
width: 640, height: 480
1113+
width: 480, height: 360
11111114
});
11121115
cameraUtils.start();
11131116

@@ -1124,25 +1127,25 @@ function updateBattleState(hasTwoHands) {
11241127
battle.p2.targetTimer = (battle.p2.targetTimer || 0) - 1;
11251128
const cpuDx = battle.p2.targetPos.x - battle.p2.pos.x;
11261129
const cpuDy = battle.p2.targetPos.y - battle.p2.pos.y;
1127-
if (battle.p2.targetTimer <= 0 || cpuDx * cpuDx + cpuDy * cpuDy < 9000) {
1128-
battle.p2.targetPos.set((Math.random() - 0.5) * width * 0.55, (Math.random() - 0.5) * height * 0.5, 0);
1129-
battle.p2.targetTimer = 140 + Math.floor(Math.random() * 120);
1130+
if (battle.p2.targetTimer <= 0 || cpuDx * cpuDx + cpuDy * cpuDy < 6400) {
1131+
battle.p2.targetPos.set((Math.random() - 0.5) * width * 0.42, (Math.random() - 0.5) * height * 0.38, 0);
1132+
battle.p2.targetTimer = 220 + Math.floor(Math.random() * 160);
11301133
}
1131-
battle.p2.pos.lerp(battle.p2.targetPos, 0.018);
1134+
battle.p2.pos.lerp(battle.p2.targetPos, 0.01);
11321135

11331136
if (!battle.roundOver && battle.p1.active) {
1134-
if (!battle.p2.charging && Math.random() < 0.006) battle.p2.charging = true;
1137+
if (!battle.p2.charging && Math.random() < 0.004) battle.p2.charging = true;
11351138
if (battle.p2.charging) {
11361139
battle.p2.chargeAmount = Math.min(1, battle.p2.chargeAmount + 0.012);
1137-
if (battle.p2.chargeAmount > 0.72 && Math.random() < 0.025) {
1140+
if (battle.p2.chargeAmount > 0.78 && Math.random() < 0.018) {
11381141
const attacks = ['normal', 'volley', 'fireball'];
11391142
fireBattleBeam(battle.p2, battle.p1, attacks[Math.floor(Math.random()*attacks.length)]);
11401143
}
11411144
} else {
11421145
battle.p2.chargeAmount *= 0.9;
1143-
if (Math.random() < 0.006) battle.p2.shielding = true;
1144-
if (battle.p2.shielding && Math.random() < 0.035) battle.p2.shielding = false;
1145-
battle.p2.shieldStrength += ((battle.p2.shielding ? 1.0 : 0) - battle.p2.shieldStrength) * 0.18;
1146+
if (Math.random() < 0.004) battle.p2.shielding = true;
1147+
if (battle.p2.shielding && Math.random() < 0.025) battle.p2.shielding = false;
1148+
battle.p2.shieldStrength += ((battle.p2.shielding ? 1.0 : 0) - battle.p2.shieldStrength) * 0.12;
11461149
}
11471150
}
11481151
} else {
@@ -1161,11 +1164,11 @@ function updateBattleState(hasTwoHands) {
11611164
battle.p2.targetTimer = (battle.p2.targetTimer || 0) - 1;
11621165
const dx = battle.p2.targetPos.x - battle.p2.pos.x;
11631166
const dy = battle.p2.targetPos.y - battle.p2.pos.y;
1164-
if (battle.p2.targetTimer <= 0 || dx * dx + dy * dy < 6400) {
1165-
battle.p2.targetPos.set(width * (0.18 + Math.random() * 0.22), (Math.random() - 0.5) * height * 0.45, 0);
1166-
battle.p2.targetTimer = 160 + Math.floor(Math.random() * 140);
1167+
if (battle.p2.targetTimer <= 0 || dx * dx + dy * dy < 4900) {
1168+
battle.p2.targetPos.set(width * (0.16 + Math.random() * 0.18), (Math.random() - 0.5) * height * 0.36, 0);
1169+
battle.p2.targetTimer = 240 + Math.floor(Math.random() * 160);
11671170
}
1168-
battle.p2.pos.lerp(battle.p2.targetPos, 0.012);
1171+
battle.p2.pos.lerp(battle.p2.targetPos, 0.008);
11691172
}
11701173
}
11711174

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@
115115

116116
<div id="footer">Created by <b>Yogender</b> · Quantum Flux v2.1</div>
117117

118-
<script src="app.min.js?v=2.3.4"></script>
118+
<script src="app.min.js?v=2.3.5"></script>
119119
</body>
120120

121121
</html>

0 commit comments

Comments
 (0)