249 lines
10 KiB
JavaScript
Raw Normal View History

// 确保在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');
});