Files
NubzukiJump/src/CameraControl.svelte
2026-04-29 15:59:34 +09:00

148 lines
3.2 KiB
Svelte

<script>
import {
initCameraControl,
updateCameraControl,
cameraInput,
} from "./game/cameraControl.js";
let videoContainer;
let enabled = $state(false);
let loading = $state(false);
let zone = $state("center");
let error = $state("");
async function enableCamera() {
try {
loading = true;
error = "";
const video = await initCameraControl();
videoContainer.innerHTML = "";
videoContainer.appendChild(video);
await video.play();
enabled = true;
loading = false;
requestAnimationFrame(updateLoop);
} catch (e) {
console.error(e);
error = "Camera could not be started";
loading = false;
}
}
async function updateLoop() {
if (!enabled) return;
await updateCameraControl();
zone = cameraInput.zone;
requestAnimationFrame(updateLoop);
}
</script>
<div class="camera-card">
<h2>Camera Control</h2>
<p>
Enable camera and move your head to control the game, or use the arrows.
</p>
<div class="camera-view">
<div class="video-holder" bind:this={videoContainer}></div>
{#if !enabled}
<button onclick={enableCamera} disabled={loading}>
{loading ? "Loading..." : "Enable camera"}
</button>
{/if}
<div class="zones">
<div class:active={zone === "left"}>GO LEFT</div>
<div class:active={zone === "center"}>STAY</div>
<div class:active={zone === "right"}>GO RIGHT</div>
</div>
</div>
{#if error}
<p class="error">{error}</p>
{/if}
</div>
<style>
.camera-card h2 {
margin: 0;
font-size: 28px;
font-weight: bold;
}
.camera-card {
background: rgba(255, 255, 255, 0.12);
border-radius: 16px;
padding: 16px;
color: white;
width: 320px;
height: 340px;
}
.camera-view {
position: relative;
width: 320px;
height: 240px;
background: #111;
border-radius: 16px;
margin-top: 0;
overflow: hidden;
}
.video-holder :global(video) {
width: 100%;
height: 100%;
}
.video-holder :global(video) {
width: 100%;
height: 100%;
object-fit: cover;
transform: scaleX(-1);
}
button {
position: absolute;
inset: 50% auto auto 50%;
transform: translate(-50%, -50%);
z-index: 5;
padding: 10px 16px;
border: none;
border-radius: 999px;
cursor: pointer;
font-weight: bold;
}
.zones {
position: absolute;
inset: auto 0 0 0;
display: grid;
grid-template-columns: repeat(3, 1fr);
font-size: 11px;
font-weight: bold;
z-index: 4;
}
.zones div {
padding: 6px 0;
background: rgba(0, 0, 0, 0.45);
}
.zones .active {
background: rgba(255, 255, 255, 0.8);
color: #111;
}
.error {
color: #ffb3b3;
font-size: 13px;
}
</style>