<!DOCTYPE html>
<html>
<head>
<title>VRテスト環境 Ver3.3</title>
<script src="https://aframe.io/releases/1.5.0/aframe.min.js"></script>
<script src="https://unpkg.com/aframe-look-at-component@0.8.0/dist/aframe-look-at-component.min.js"></script>
<script src="https://unpkg.com/aframe-troika-text/dist/aframe-troika-text.min.js"></script>
<script>
// --- Component: Player Controls ---
AFRAME.registerComponent('camera-relative-controls', {
schema: {
targetSpeed: { type: 'number', default: 5 },
acceleration: { type: 'number', default: 10 },
damping: { type: 'number', default: 8 },
brakingDeceleration: { type: 'number', default: 20 },
enabled: { type: 'boolean', default: true },
rotationSpeed: { type: 'number', default: 1.5 },
pitchLimit: { type: 'number', default: 85 },
verticalSpeed: { type: 'number', default: 30 },
groundY: { type: 'number', default: 0 },
ceilingY: { type: 'number', default: 50 },
gravity: { type: 'number', default: 0.5 }
},
init: function () {
this.keys = {};
this.leftThumbstickInput = { x: 0, y: 0 };
this.rightThumbstickInput = { x: 0, y: 0 };
this.currentVelocity = new THREE.Vector3();
this.ZERO_VECTOR = new THREE.Vector3();
this.cameraDirection = new THREE.Vector3();
this.cameraRight = new THREE.Vector3();
this.moveDirection = new THREE.Vector3();
this.desiredVelocity = new THREE.Vector3();
this.cameraWorldQuaternion = new THREE.Quaternion();
this.rigEl = this.el;
this.cameraEl = this.el.querySelector('[camera]');
this.isReady = false;
if (!this.cameraEl) { console.error('camera-relative-controls: カメラエンティティが見つかりません。'); }
this.el.sceneEl.addEventListener('loaded', () => {
this.leftHand = document.getElementById('leftHand');
if (this.leftHand) { this.leftHand.addEventListener('thumbstickmoved', this.onLeftThumbstickMoved.bind(this)); }
this.rightHand = document.getElementById('rightHand');
if (this.rightHand) { this.rightHand.addEventListener('thumbstickmoved', this.onRightThumbstickMoved.bind(this)); }
});
this.onKeyDown = this.onKeyDown.bind(this);
this.onKeyUp = this.onKeyUp.bind(this);
window.addEventListener('keydown', this.onKeyDown);
window.addEventListener('keyup', this.onKeyUp);
},
remove: function () {
window.removeEventListener('keydown', this.onKeyDown);
window.removeEventListener('keyup', this.onKeyUp);
if (this.leftHand) { try { this.leftHand.removeEventListener('thumbstickmoved', this.onLeftThumbstickMoved.bind(this)); } catch(e){} }
if (this.rightHand) { try { this.rightHand.removeEventListener('thumbstickmoved', this.onRightThumbstickMoved.bind(this)); } catch(e){} }
},
onLeftThumbstickMoved: function (evt) { this.leftThumbstickInput.x = evt.detail.x; this.leftThumbstickInput.y = evt.detail.y; },
onRightThumbstickMoved: function (evt) { this.rightThumbstickInput.x = evt.detail.x; this.rightThumbstickInput.y = evt.detail.y; },
tick: function (time, timeDelta) {
if (!this.data.enabled) return;
if (!this.isReady) {
if (this.cameraEl && this.cameraEl.object3D && this.cameraEl.object3D.matrixWorld) { this.isReady = true; }
else { return; }
}
if (!this.cameraEl || !this.cameraEl.object3D || !this.rigEl || !this.rigEl.object3D) { return; }
const data = this.data;
const dt = timeDelta / 1000;
const position = this.rigEl.object3D.position;
if (this.rigEl.sceneEl.is('vr-mode')) {
if (Math.abs(this.rightThumbstickInput.x) > 0.1) { this.rigEl.object3D.rotation.y += -this.rightThumbstickInput.x * data.rotationSpeed * dt; }
}
const cameraObject = this.cameraEl.object3D;
cameraObject.getWorldQuaternion(this.cameraWorldQuaternion);
this.cameraDirection.set(0, 0, -1).applyQuaternion(this.cameraWorldQuaternion); this.cameraDirection.normalize();
this.cameraRight.set(1, 0, 0).applyQuaternion(this.cameraWorldQuaternion); this.cameraRight.y = 0; this.cameraRight.normalize();
this.moveDirection.set(0, 0, 0);
if (this.keys['KeyW'] || this.keys['ArrowUp']) { this.moveDirection.add(this.cameraDirection); }
if (this.keys['KeyS'] || this.keys['ArrowDown']) { this.moveDirection.sub(this.cameraDirection); }
if (this.keys['KeyA'] || this.keys['ArrowLeft']) { this.moveDirection.sub(this.cameraRight); }
if (this.keys['KeyD'] || this.keys['ArrowRight']) { this.moveDirection.add(this.cameraRight); }
if (Math.abs(this.leftThumbstickInput.y) > 0.1) { this.moveDirection.add(this.cameraDirection.clone().multiplyScalar(-this.leftThumbstickInput.y)); }
if (Math.abs(this.leftThumbstickInput.x) > 0.1) { this.moveDirection.add(this.cameraRight.clone().multiplyScalar(this.leftThumbstickInput.x)); }
const isInputting = this.moveDirection.lengthSq() > 0.0001;
let lerpFactor = data.damping;
if (isInputting) {
if (this.currentVelocity.dot(this.moveDirection) < -0.1) { this.desiredVelocity.set(0,0,0); lerpFactor = data.brakingDeceleration; }
else { this.desiredVelocity.copy(this.moveDirection).multiplyScalar(data.targetSpeed); lerpFactor = data.acceleration; }
} else { this.desiredVelocity.set(0,0,0); lerpFactor = data.damping; }
const effectiveLerpFactor = 1.0 - Math.exp(-lerpFactor * dt);
this.currentVelocity.lerp(this.desiredVelocity, effectiveLerpFactor);
if (this.currentVelocity.lengthSq() < 0.0001) { this.currentVelocity.set(0,0,0); }
if (this.currentVelocity.lengthSq() > 0) {
const deltaPosition = this.currentVelocity.clone().multiplyScalar(dt);
position.add(deltaPosition);
}
let verticalMovement = 0;
if (this.rigEl.sceneEl.is('vr-mode') && Math.abs(this.rightThumbstickInput.y) > 0.1) {
verticalMovement = -this.rightThumbstickInput.y * data.verticalSpeed * dt;
}
let newY = position.y + verticalMovement;
if (position.y > data.groundY) {
newY -= data.gravity * dt;
}
position.y = Math.max(data.groundY, Math.min(newY, data.ceilingY));
},
onKeyDown: function (event) { if (!this.data.enabled) { return; } if (['KeyW', 'ArrowUp', 'KeyS', 'ArrowDown', 'KeyA', 'ArrowLeft', 'KeyD', 'ArrowRight'].includes(event.code)) { this.keys[event.code] = true; } },
onKeyUp: function (event) { if (this.keys[event.code] !== undefined) { delete this.keys[event.code]; } }
});
AFRAME.registerComponent('hand-grab', {
schema: {
enabled: { type: 'boolean', default: false },
grabRadius: { type: 'number', default: 0.1 }
},
init: function () {
this.grabbedEl = null;
this.objectContainer = document.getElementById('object-container');
this.handPos = new THREE.Vector3();
this.objPos = new THREE.Vector3();
this.onTriggerDown = this.onTriggerDown.bind(this);
this.onTriggerUp = this.onTriggerUp.bind(this);
this.el.addEventListener('triggerdown', this.onTriggerDown);
this.el.addEventListener('triggerup', this.onTriggerUp);
},
onTriggerDown: function () {
if (!this.data.enabled || this.grabbedEl) return;
this.el.object3D.getWorldPosition(this.handPos);
const grabbableEls = this.objectContainer.children;
let closestEl = null;
let closestDistSq = this.data.grabRadius * this.data.grabRadius;
for (let i = 0; i < grabbableEls.length; i++) {
const el = grabbableEls[i];
el.object3D.getWorldPosition(this.objPos);
const distSq = this.handPos.distanceToSquared(this.objPos);
if (distSq < closestDistSq) {
closestDistSq = distSq;
closestEl = el;
}
}
if (closestEl) {
this.grabbedEl = closestEl;
this.el.object3D.attach(this.grabbedEl.object3D);
}
},
onTriggerUp: function () {
if (!this.data.enabled || !this.grabbedEl) return;
this.objectContainer.object3D.attach(this.grabbedEl.object3D);
window.alignSingleObject(this.grabbedEl);
this.grabbedEl = null;
}
});
</script>
<style>
#hud-pc {
position: fixed; bottom: 20px; left: 20px; color: white;
background-color: rgba(0, 0, 0, 0.4); padding: 20px; border-radius: 10px;
font-family: sans-serif; font-size: 26px; font-weight: bold; z-index: 10; min-width: 250px;
}
#hud-pc > div:not(:last-child) { margin-bottom: 12px; }
.hud-buttons { display: flex; gap: 10px; }
.hud-buttons > div {
flex-grow: 1; cursor: pointer; padding: 10px; text-align: center; border-radius: 5px;
}
#replay-button-pc { background-color: #C0392B; }
#replay-button-pc:hover { background-color: #A93226; }
#create-box-button-pc { background-color: #2980B9; }
#create-box-button-pc:hover { background-color: #2471A3; }
#create-sphere-button-pc { background-color: #27AE60; }
#create-sphere-button-pc:hover { background-color: #229954; }
</style>
</head>
<body>
<div id="hud-pc">
<div id="hud-main-content-pc">
<div id="score-display-pc">SCORE: 0</div>
<div id="hiscore-display-pc">HI SCORE: 0</div>
<div id="time-display-pc">残り時間: 150</div>
<div class="hud-buttons">
<div id="replay-button-pc" onclick="handleStartReplayClick()">スタート</div>
<div id="create-box-button-pc">四角</div>
<div id="create-sphere-button-pc">球</div>
</div>
</div>
</div>
<a-scene id="myScene" vr-mode-ui="enabled: true" background="color: #87CEEB" cursor="rayOrigin: mouse">
<a-assets></a-assets>
<a-entity id="rig" position="0 0 5" camera-relative-controls="targetSpeed: 10; acceleration: 12; damping: 10; groundY: 0; gravity: 1.0;">
<a-entity id="player" position="0 0 0">
<a-entity id="camera" camera="far: 20000;" look-controls="pointerLockEnabled: false; touchEnabled: false" position="0 1.6 0">
<a-entity id="mouseCursor" cursor="rayOrigin: mouse;" raycaster="objects: .clickable, .grabbable;" position="0 0 -1" geometry="primitive: ring; radiusInner: 0.02; radiusOuter: 0.03;" material="color: black; shader: flat; opacity: 0.7;"></a-entity>
</a-entity>
<a-entity id="leftHand" hand-controls="hand: left;">
<a-entity id="vr-hud" position="0.02 0.04 -0.35" rotation="-60 0 0">
<a-plane id="hud-background" width="0.4" height="0.22" color="#FAFAFA" opacity="0.8" side="double"></a-plane>
<a-entity id="vr-hud-main-content">
<a-entity id="score-display-vr" troika-text="value: SCORE: 0; color: black; fontSize: 0.015; align: center; anchorX: center;" position="0 0.07 0.01"></a-entity>
<a-entity id="hiscore-display-vr" troika-text="value: HI SCORE: 0; color: black; fontSize: 0.015; align: center; anchorX: center;" position="0 0.03 0.01"></a-entity>
<a-entity id="time-display-vr" troika-text="value: 残り時間: 150; color: black; fontSize: 0.015; align: center; anchorX: center;" position="0 -0.01 0.01"></a-entity>
</a-entity>
<a-sphere id="replay-sphere-vr" class="clickable" radius="0.025" position="-0.15 -0.07 0.01" material="color: red; shader: flat">
<a-entity troika-text="value: スタート; color: white; fontSize: 0.012; align: center; anchor: center;" position="0 0.035 0"></a-entity>
</a-sphere>
<a-sphere id="create-box-sphere-vr" class="clickable" radius="0.025" position="-0.05 -0.07 0.01" material="color: #3498DB; shader: flat">
<a-entity troika-text="value: 四角; color: white; fontSize: 0.012; align: center; anchor: center;" position="0 0.035 0"></a-entity>
</a-sphere>
<a-sphere id="create-sphere-sphere-vr" class="clickable" radius="0.025" position="0.05 -0.07 0.01" material="color: #27AE60; shader: flat">
<a-entity troika-text="value: 球; color: white; fontSize: 0.012; align: center; anchor: center;" position="0 0.035 0"></a-entity>
</a-sphere>
<a-sphere id="toggle-grab-mode-vr" class="clickable" radius="0.025" position="0.15 -0.07 0.01" material="color: yellow; shader: flat">
<a-entity troika-text="value: モード; color: black; fontSize: 0.012; align: center; anchor: center;" position="0 0.035 0"></a-entity>
</a-sphere>
</a-entity>
</a-entity>
<a-entity id="rightHand"
hand-controls="hand: right;"
laser-controls="hand: right; model: false;"
raycaster="objects: .clickable, .grabbable; lineColor: white; lineOpacity: 0.75"
hand-grab>
</a-entity>
</a-entity>
</a-entity>
<a-entity light="type: ambient; color: #888"></a-entity>
<a-entity light="type: directional; color: #FFF; intensity: 0.8;" position="-100 200 100"></a-entity>
<a-plane id="ground" position="0 0 0" rotation="-90 0 0" width="500" height="500" color="#7BC8A4"></a-plane>
<a-entity id="object-container"></a-entity>
</a-scene>
<script>
// --- Main Scene Logic ---
document.addEventListener('DOMContentLoaded', function () {
const sceneEl = document.querySelector('a-scene');
let isGameOver = false;
let isGameStarted = false;
let gameTimer = null;
let score = 0;
let hiScore = 0;
let remainingTime = 0;
let createdObjectCounter = 0;
let grabbedObject = null;
let draggedObject = null;
let dragDistance = 0;
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
const worldPosition = new THREE.Vector3();
let isLaserGrabMode = true;
const rightHand = document.getElementById('rightHand');
const rigEl = document.getElementById('rig');
const objectContainer = document.getElementById('object-container');
const createBoxButtonPC = document.getElementById('create-box-button-pc');
const createSphereButtonPC = document.getElementById('create-sphere-button-pc');
function handleStartReplayClick() {
if (!isGameStarted) {
startGame();
} else {
replayGame();
}
}
window.handleStartReplayClick = handleStartReplayClick;
function startGame() {
if (isGameStarted) return;
isGameStarted = true;
console.log("Game started!");
document.getElementById('replay-button-pc').textContent = 'リプレイ';
const replaySphereVRText = document.querySelector('#replay-sphere-vr > a-entity');
if (replaySphereVRText) replaySphereVRText.setAttribute('troika-text', 'value', 'リプレイ');
replayGame();
}
function replayGame() {
console.log("Replaying game...");
checkAndSetHiScore();
isGameOver = false;
score = 0;
objectContainer.innerHTML = '';
createdObjectCounter = 0;
if (rigEl && rigEl.components['camera-relative-controls']) {
rigEl.setAttribute('camera-relative-controls', 'enabled', true);
}
rigEl.setAttribute('position', '0 0 5');
rigEl.setAttribute('rotation', '0 0 0');
initializeHUD();
}
function updateScoreDisplay() {
const scoreText = `SCORE: ${score}`;
document.getElementById('score-display-pc').textContent = scoreText;
document.getElementById('score-display-vr').setAttribute('troika-text', 'value', scoreText);
}
function updateHiScoreDisplay() {
const hiScoreText = `HI SCORE: ${hiScore}`;
document.getElementById('hiscore-display-pc').textContent = hiScoreText;
document.getElementById('hiscore-display-vr').setAttribute('troika-text', 'value', hiScoreText);
}
function checkAndSetHiScore() {
if (score > hiScore) {
hiScore = score;
localStorage.setItem('testHiScore', hiScore);
updateHiScoreDisplay();
}
}
function createBox(position) {
const box = document.createElement('a-box');
box.setAttribute('id', `box-${createdObjectCounter++}`);
box.classList.add('grabbable');
box.setAttribute('position', position);
box.setAttribute('width', 0.1);
box.setAttribute('height', 0.1);
box.setAttribute('depth', 0.1);
box.setAttribute('color', `#${Math.floor(Math.random()*16777215).toString(16).padStart(6, '0')}`);
objectContainer.appendChild(box);
score += 10;
updateScoreDisplay();
}
function createSphere(position) {
const sphere = document.createElement('a-sphere');
sphere.setAttribute('id', `sphere-${createdObjectCounter++}`);
sphere.classList.add('grabbable');
sphere.setAttribute('position', position);
sphere.setAttribute('radius', 0.05);
sphere.setAttribute('color', `#${Math.floor(Math.random()*16777215).toString(16).padStart(6, '0')}`);
objectContainer.appendChild(sphere);
score += 10;
updateScoreDisplay();
}
function alignSingleObject(obj) {
if (!obj) return;
const pos = obj.getAttribute('position');
let snapSize = 1;
if (obj.tagName.toLowerCase() === 'a-box') {
snapSize = obj.getAttribute('width');
} else if (obj.tagName.toLowerCase() === 'a-sphere') {
snapSize = obj.getAttribute('radius') * 2;
}
const newPos = {
x: Math.round(pos.x / snapSize) * snapSize,
y: Math.round(pos.y / snapSize) * snapSize,
z: Math.round(pos.z / snapSize) * snapSize
};
obj.setAttribute('position', newPos);
obj.setAttribute('rotation', '0 0 0');
}
window.alignSingleObject = alignSingleObject;
// ★ 修正点: VR掴みモード切替ロジックを修正
function toggleGrabMode() {
isLaserGrabMode = !isLaserGrabMode;
console.log("Grab mode toggled. Laser enabled:", isLaserGrabMode);
const lineEl = rightHand.querySelector('[line]');
if (isLaserGrabMode) {
rightHand.setAttribute('laser-controls', 'enabled', true);
rightHand.setAttribute('hand-grab', 'enabled', false);
if (lineEl) lineEl.setAttribute('visible', true);
} else {
rightHand.setAttribute('laser-controls', 'enabled', false);
rightHand.setAttribute('hand-grab', 'enabled', true);
if (lineEl) lineEl.setAttribute('visible', false);
}
}
function onMouseMove(event) {
if (!draggedObject) return;
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
const camera = sceneEl.camera;
raycaster.setFromCamera(mouse, camera);
raycaster.ray.at(dragDistance, worldPosition);
draggedObject.object3D.parent.worldToLocal(worldPosition);
draggedObject.object3D.position.copy(worldPosition);
}
function onMouseUp() {
if (draggedObject) {
alignSingleObject(draggedObject);
}
draggedObject = null;
dragDistance = 0;
window.removeEventListener('mousemove', onMouseMove);
window.removeEventListener('mouseup', onMouseUp);
}
function setupGame() {
hiScore = localStorage.getItem('testHiScore') || 0;
updateHiScoreDisplay();
sceneEl.addEventListener('mousedown', function(evt) {
if (sceneEl.is('vr-mode') || !isGameStarted || isGameOver) return;
const intersectedEl = evt.detail.intersectedEl;
if (intersectedEl && intersectedEl.classList.contains('grabbable')) {
draggedObject = intersectedEl;
const intersection = evt.detail.intersection;
if (!intersection) return;
dragDistance = intersection.distance;
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('mouseup', onMouseUp);
}
});
if (rightHand) {
rightHand.addEventListener('triggerdown', function () {
// ★ 修正点: Raycasterでの検知は常に行うように変更
const raycasterComponent = rightHand.components.raycaster;
const intersectedEls = raycasterComponent ? raycasterComponent.intersectedEls : [];
if (intersectedEls.length === 0) return;
const hitEl = intersectedEls[0];
// --- HUDボタンの処理(モードに関わらず常に有効) ---
if (hitEl.id === 'replay-sphere-vr') {
handleStartReplayClick();
return;
}
if (hitEl.id === 'toggle-grab-mode-vr') {
toggleGrabMode();
return;
}
if (hitEl.id === 'create-box-sphere-vr' || hitEl.id === 'create-sphere-sphere-vr') {
if (isGameStarted && !isGameOver) {
const controllerPos = new THREE.Vector3();
rightHand.object3D.getWorldPosition(controllerPos);
if (hitEl.id === 'create-box-sphere-vr') createBox(controllerPos);
else createSphere(controllerPos);
}
return;
}
// --- オブジェクト掴み処理(レーザーモード時のみ) ---
if (isLaserGrabMode && isGameStarted && !isGameOver) {
if (hitEl.classList.contains('grabbable') && !grabbedObject) {
grabbedObject = hitEl;
rightHand.object3D.attach(grabbedObject.object3D);
}
}
});
rightHand.addEventListener('triggerup', function () {
if (isLaserGrabMode && grabbedObject) {
objectContainer.object3D.attach(grabbedObject.object3D);
alignSingleObject(grabbedObject);
grabbedObject = null;
}
});
}
createBoxButtonPC.addEventListener('click', () => {
if (isGameOver || !isGameStarted) return;
const camera = document.getElementById('camera');
const worldPos = new THREE.Vector3();
const direction = new THREE.Vector3();
camera.object3D.getWorldPosition(worldPos);
camera.object3D.getWorldDirection(direction);
worldPos.add(direction.multiplyScalar(-0.5));
createBox(worldPos);
});
createSphereButtonPC.addEventListener('click', () => {
if (isGameOver || !isGameStarted) return;
const camera = document.getElementById('camera');
const worldPos = new THREE.Vector3();
const direction = new THREE.Vector3();
camera.object3D.getWorldPosition(worldPos);
camera.object3D.getWorldDirection(direction);
worldPos.add(direction.multiplyScalar(-0.5));
createSphere(worldPos);
});
const pcHud = document.getElementById('hud-pc');
if(pcHud) {
sceneEl.addEventListener('enter-vr', () => { pcHud.style.display = 'none'; });
sceneEl.addEventListener('exit-vr', () => { pcHud.style.display = 'block'; });
}
}
function initializeHUD() {
if (gameTimer) { clearInterval(gameTimer); }
updateScoreDisplay();
const timeElementPC = document.getElementById('time-display-pc');
const timeElementVR = document.getElementById('time-display-vr');
remainingTime = 150;
const timeText = `残り時間: ${remainingTime}`;
if (timeElementPC) timeElementPC.textContent = timeText;
if (timeElementVR) timeElementVR.setAttribute('troika-text', 'value', timeText);
gameTimer = setInterval(() => {
if (isGameOver) {
clearInterval(gameTimer);
return;
}
if (remainingTime > 0) {
remainingTime--;
const newTimeText = `残り時間: ${remainingTime}`;
if (timeElementPC) timeElementPC.textContent = newTimeText;
if (timeElementVR) timeElementVR.setAttribute('troika-text', 'value', newTimeText);
} else {
const newTimeText = '残り時間: 0';
if (timeElementPC) timeElementPC.textContent = newTimeText;
if (timeElementVR) timeElementVR.setAttribute('troika-text', 'value', newTimeText);
clearInterval(gameTimer);
triggerGameOver("時間切れ");
}
}, 1000);
}
window.triggerGameOver = function(reason) {
if (isGameOver) return;
isGameOver = true;
console.log(`GAME OVER: ${reason}`);
checkAndSetHiScore();
if (rigEl && rigEl.components['camera-relative-controls']) {
rigEl.setAttribute('camera-relative-controls', 'enabled', false);
}
}
if (sceneEl.hasLoaded) { setupGame(); } else { sceneEl.addEventListener('loaded', setupGame, {once: true}); }
});
</script>
</body>
</html>
使用変数
-------( Function ) | |
alignSingleObject -------( Function ) | |
alignSingleObject | |
background | |
box | |
camera | |
cameraDirection | |
cameraEl | |
cameraObject | |
cameraRight | |
checkAndSetHiScore -------( Function ) | |
class | |
closestDistSq | |
closestEl | |
color | |
controllerPos | |
controls | |
createBox -------( Function ) | |
createBoxButtonPC | |
createSphere -------( Function ) | |
currentVelocity | |
cursor | |
data | |
deltaPosition | |
desiredVelocity | |
direction | |
display | |
distSq | |
dragDistance | |
draggedObject | |
dt | |
eatedObjectCounter | |
eateSphereButtonPC | |
eftThumbstickInput | |
el | |
eraWorldQuaternion | |
evt) { if -------( Function ) | |
ffectiveLerpFactor | |
gameTimer | |
geometry | |
ghtThumbstickInput | |
grabbableEls | |
grabbedEl | |
grabbedObject | |
handleStartReplayClick -------( Function ) | |
handPos | |
height | |
hiScore | |
hiScoreText | |
hitEl | |
i | |
id | |
initializeHUD -------( Function ) | |
innerHTML | |
intersectedEl | |
intersectedEls | |
intersection | |
isGameOver | |
isGameStarted | |
isInputting | |
isLaserGrabMode | |
isReady | |
keys | |
leftHand | |
length | |
lerpFactor | |
leStartReplayClick | |
light | |
lineEl | |
material | |
mouse | |
moveDirection | |
newPos | |
newTimeText | |
newY | |
objectContainer | |
objPos | |
onclick | |
onKeyDown | |
onKeyUp | |
onMouseMove -------( Function ) | |
onMouseUp -------( Function ) | |
onTriggerDown | |
onTriggerUp | |
opacity | |
pcHud | |
pos | |
position | |
radius | |
raycaster | |
raycasterComponent | |
remainingTime | |
replayGame -------( Function ) | |
replaySphereVRText | |
rigEl | |
rightHand | |
rotation | |
sceneEl | |
score | |
scoreText | |
setupGame -------( Function ) | |
side | |
snapSize | |
sphere | |
src | |
startGame -------( Function ) | |
text | |
textContent | |
timeElementPC | |
timeElementVR | |
timeText | |
toggleGrabMode -------( Function ) | |
triggerGameOver | |
ui | |
updateHiScoreDisplay -------( Function ) | |
updateScoreDisplay -------( Function ) | |
verticalMovement | |
width | |
worldPos | |
worldPosition | |
x | |
y | |
ZERO_VECTOR |