249 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 确保在DOM加载完成后执行
window.addEventListener('DOMContentLoaded', function() {
console.log('DOMContentLoaded - Joycon.js executing');
// 游戏手柄相关变量
let gamepad = null;
let lastDirection = 'stop';
// 使用全局变量与control.js和record.js保持一致
// let isRecording = false;
// let isPlaying = false;
// let recordedActions = [];
// let recordingStartTime = 0;
// 按键状态标志(用于检测按键按下事件)
let recordButtonPressed = false;
let playbackButtonPressed = false;
// 获取状态元素
const status = document.getElementById('status');
// 检查浏览器是否支持游戏手柄API
if (!('getGamepads' in navigator)) {
status.innerHTML = '<p>您的浏览器不支持游戏手柄API</p>';
console.log('Gamepad API not supported');
return;
}
// 连接游戏手柄
window.addEventListener('gamepadconnected', function(e) {
gamepad = e.gamepad;
status.innerHTML = `<p>已连接游戏手柄: ${gamepad.id}</p>`;
console.log('Gamepad connected:', gamepad);
// 开始监听游戏手柄输入
requestAnimationFrame(updateGamepad);
});
// 断开游戏手柄
window.addEventListener('gamepaddisconnected', function(e) {
status.innerHTML = '<p>游戏手柄已断开连接</p>';
console.log('Gamepad disconnected:', e.gamepad);
gamepad = null;
});
// 游戏手柄输入更新函数
function updateGamepad() {
if (!gamepad) {
requestAnimationFrame(updateGamepad);
return;
}
// 获取游戏手柄状态
const gamepads = navigator.getGamepads();
gamepad = gamepads[gamepad.index];
if (!gamepad) {
requestAnimationFrame(updateGamepad);
return;
}
// 处理摇杆输入 (通常是0号摇杆左摇杆)
const leftStickX = gamepad.axes[0];
const leftStickY = gamepad.axes[1];
// 处理按键输入
const buttons = gamepad.buttons;
// 摇杆死区
const deadzone = 0.3;
// 确定移动方向
let direction = 'stop';
if (Math.abs(leftStickX) > deadzone || Math.abs(leftStickY) > deadzone) {
// 计算角度
const angle = Math.atan2(leftStickY, leftStickX) * 180 / Math.PI;
// 根据角度确定方向(修复:交换前后方向,修复:使用下划线分隔的方向值)
if (angle >= -22.5 && angle < 22.5) {
direction = 'right'; // 右
} else if (angle >= 22.5 && angle < 67.5) {
direction = 'backward_right'; // 右后
} else if (angle >= 67.5 && angle < 112.5) {
direction = 'backward'; // 后
} else if (angle >= 112.5 && angle < 157.5) {
direction = 'backward_left'; // 左后
} else if (angle >= 157.5 || angle < -157.5) {
direction = 'left'; // 左
} else if (angle >= -157.5 && angle < -112.5) {
direction = 'forward_left'; // 左前
} else if (angle >= -112.5 && angle < -67.5) {
direction = 'forward'; // 前
} else if (angle >= -67.5 && angle < -22.5) {
direction = 'forward_right'; // 右前
}
}
// 处理旋转按钮 (X键和Y键)
if (buttons[2].pressed) { // X键 - 左旋转
direction = 'rotate_left';
} else if (buttons[3].pressed) { // Y键 - 右旋转
direction = 'rotate_right';
}
// 处理录制按钮 (十字键上键) - 修复:检测按键按下事件
if (buttons[12].pressed) { // 十字键上键 - 录制
if (!recordButtonPressed) {
recordButtonPressed = true;
if (!window.isPlaying) {
if (window.isRecording) {
// 停止录制
window.isRecording = false;
status.innerHTML = `<p>录制完成,共记录 ${window.recordedActions.length} 个操作</p>`;
console.log('Recording stopped, actions:', window.recordedActions);
} else {
// 开始录制
window.isRecording = true;
window.recordedActions = [];
window.recordingStartTime = Date.now();
status.innerHTML = '<p>开始录制...</p>';
console.log('Recording started');
}
}
}
} else {
recordButtonPressed = false;
}
// 处理回放按钮 (十字键左键) - 修复:检测按键按下事件
if (buttons[14].pressed) { // 十字键左键 - 回放
if (!playbackButtonPressed) {
playbackButtonPressed = true;
if (!window.isRecording && !window.isPlaying && window.recordedActions.length > 0) {
window.isPlaying = true;
status.innerHTML = '<p>开始回放...</p>';
console.log('Starting playback');
// 按时间顺序回放操作
let currentTime = 0;
const totalDuration = window.recordedActions[window.recordedActions.length - 1].timestamp;
window.recordedActions.forEach((action, index) => {
if (index === 0) {
// 第一个操作立即执行
console.log('Executing action immediately:', action);
controlMotor(action.direction);
} else {
// 计算与前一个操作的时间差
const prevAction = window.recordedActions[index - 1];
const delay = action.timestamp - prevAction.timestamp;
currentTime += delay;
console.log('Scheduling action:', action, 'at delay:', currentTime);
setTimeout(() => {
console.log('Executing action:', action);
controlMotor(action.direction);
}, currentTime);
}
});
// 回放完成后,确保发送停止请求
setTimeout(() => {
console.log('Playback completed, sending stop command');
controlMotor('stop');
status.innerHTML = '<p>回放完成</p>';
console.log('Playback completed');
window.isPlaying = false;
}, totalDuration + 2000);
}
}
} else {
playbackButtonPressed = false;
}
// 如果方向改变,发送控制命令
if (direction !== lastDirection) {
// 如果正在录制,记录操作
if (window.isRecording) {
const action = {
direction: direction,
timestamp: Date.now() - window.recordingStartTime
};
window.recordedActions.push(action);
}
controlMotor(direction);
lastDirection = direction;
}
// 继续监听
requestAnimationFrame(updateGamepad);
}
// 控制电机的函数与control.js中的相同
function controlMotor(direction) {
// 根据方向设置状态消息
if (direction === 'stop') {
status.innerHTML = `<p>正在停止...</p>`;
} else {
let actionText = '';
switch (direction) {
case 'forward': actionText = '前进'; break;
case 'backward': actionText = '后退'; break;
case 'left': actionText = '左移'; break;
case 'right': actionText = '右移'; break;
case 'rotate_left': actionText = '左旋转'; break;
case 'rotate_right': actionText = '右旋转'; break;
case 'forward_left': actionText = '左前移动'; break;
case 'forward_right': actionText = '右前移动'; break;
case 'backward_left': actionText = '左后移动'; break;
case 'backward_right': actionText = '右后移动'; break;
default: actionText = '移动'; break;
}
status.innerHTML = `<p>正在${actionText}...</p>`;
}
// 记录操作(如果正在录制)
if (window.isRecording) {
const timestamp = Date.now() - window.recordingStartTime;
// 注意这里不再重复记录因为已经在updateGamepad中记录了
console.log('Recorded action:', { direction, timestamp });
} else {
console.log('Not recording, action:', direction);
}
// 发送AJAX请求到后端服务器
fetch('/control', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ direction: direction })
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
status.innerHTML = `<p>${data.message}</p>`;
} else {
status.innerHTML = `<p>错误: ${data.message}</p>`;
}
})
.catch(error => {
status.innerHTML = `<p>通信错误: ${error.message}</p>`;
});
}
// 初始化
status.innerHTML = '<p>请连接游戏手柄...</p>';
console.log('Joycon.js initialized');
});