diff --git a/public/favicon.png b/public/favicon.png
deleted file mode 100644
index 7e6f5eb..0000000
Binary files a/public/favicon.png and /dev/null differ
diff --git a/public/index.html b/public/index.html
index 6296fab..4b692ad 100644
--- a/public/index.html
+++ b/public/index.html
@@ -7,7 +7,7 @@
Svelte app
-
+
diff --git a/src/game/cameraControl.js b/src/game/cameraControl.js
index e896ebc..c588045 100644
--- a/src/game/cameraControl.js
+++ b/src/game/cameraControl.js
@@ -1,91 +1,89 @@
-import { FaceDetector, FilesetResolver } from '@mediapipe/tasks-vision';
+import { FaceLandmarker, FilesetResolver } from '@mediapipe/tasks-vision';
export const cameraInput = {
left: false,
right: false,
active: false,
- zone: 'center',
- x: 0.5
+ zone: 'center'
};
let video;
-let faceDetector;
+let faceLandmarker;
+let lastTime = 0;
-// 🔥 NARROW CENTER ZONE:
-// 0.48 and 0.52 means the center is only 4% of the screen width.
-// Adjust these if it's still too hard to trigger movement.
-const LEFT_THRESHOLD = 0.48;
-const RIGHT_THRESHOLD = 0.52;
+const DETECTION_INTERVAL = 60;
export async function initCameraControl() {
- if (cameraInput.active) return video;
+ if (cameraInput.active)
+ return video;
video = document.createElement('video');
video.autoplay = true;
video.playsInline = true;
video.muted = true;
+ // Set low resolution and frame rate for better performance
const stream = await navigator.mediaDevices.getUserMedia({
- video: {
- width: 160,
- height: 120,
- frameRate: { ideal: 20 } // Slightly higher for faster reaction
+ video: {
+ width: { ideal: 160 },
+ height: { ideal: 120 },
+ frameRate: { ideal: 30 }
}
});
video.srcObject = stream;
+ //load models for face landmark detection
const vision = await FilesetResolver.forVisionTasks(
'https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision/wasm'
);
-
- faceDetector = await FaceDetector.createFromOptions(vision, {
+ faceLandmarker = await FaceLandmarker.createFromOptions(vision, {
baseOptions: {
- modelAssetPath: `https://storage.googleapis.com/mediapipe-models/face_detector/blaze_face_short_range/float16/1/blaze_face_short_range.task`,
- delegate: 'GPU'
+ modelAssetPath:
+ 'https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/latest/face_landmarker.task',
},
- runningMode: 'VIDEO'
- });
-
- video.addEventListener('loadeddata', () => {
- cameraInput.active = true;
- startDetectionLoop();
+ runningMode: 'VIDEO',
+ numFaces: 1
});
+ cameraInput.active = true;
return video;
}
-function startDetectionLoop() {
- const detect = (now) => {
- const result = faceDetector.detectForVideo(video, now);
+export function updateCameraControl() {
+ const now = performance.now();
- if (result.detections.length > 0) {
- const box = result.detections[0].boundingBox;
- // Calculate raw center point (0 to 1)
- const rawX = (box.originX + box.width / 2) / 160;
-
- cameraInput.x = rawX;
+ // Limit detection frequency to improve performance
+ if (now - lastTime < DETECTION_INTERVAL)
+ return;
+ lastTime = now;
- // INSTANT LOGIC (No smoothing)
- if (rawX < LEFT_THRESHOLD) {
- updateZones(false, true, 'right'); // Mirrored: Face on left of cam = move right
- } else if (rawX > RIGHT_THRESHOLD) {
- updateZones(true, false, 'left'); // Mirrored: Face on right of cam = move left
- } else {
- updateZones(false, false, 'center');
- }
- } else {
- updateZones(false, false, 'center');
- }
+ if (!faceLandmarker || !video || video.readyState < 2)
+ return;
- video.requestVideoFrameCallback(detect);
- };
+ const result = faceLandmarker.detectForVideo(video, now);
- video.requestVideoFrameCallback(detect);
-}
+ // If no face is detected, reset to center
+ if (!result.faceLandmarks.length) {
+ cameraInput.left = false;
+ cameraInput.right = false;
+ cameraInput.zone = 'center';
+ return;
+ }
-function updateZones(l, r, z) {
- cameraInput.left = l;
- cameraInput.right = r;
- cameraInput.zone = z;
+ // look at the nose and determine zone
+ const x = result.faceLandmarks[0][1].x;
+ if (x < 0.4) {
+ cameraInput.left = false;
+ cameraInput.right = true;
+ cameraInput.zone = 'right';
+ } else if (x > 0.6) {
+ cameraInput.left = true;
+ cameraInput.right = false;
+ cameraInput.zone = 'left';
+ } else {
+ cameraInput.left = false;
+ cameraInput.right = false;
+ cameraInput.zone = 'center';
+ }
}
\ No newline at end of file
diff --git a/src/game/constants.js b/src/game/constants.js
index 01d6a88..fa36be8 100644
--- a/src/game/constants.js
+++ b/src/game/constants.js
@@ -16,4 +16,4 @@ export const PLAT_TYPE = {
MOVING: 'moving',
SPRING: 'spring',
ONE_TIME: 'one-time'
-};
+};
\ No newline at end of file