优化控制界面UI样式,增加外界手柄控制
This commit is contained in:
1 parent
7fbe4f59cd
commit
bd13a5aeb2
10 files changed
+779
-79
No files matched your search
@@ -424,6 +424,8 @@ function stopMotor() {
|
||||
const timestamp = Date.now() - window.recordingStartTime;
|
||||
window.recordedActions.push({ direction: 'stop', timestamp });
|
||||
console.log('Recorded action:', { direction: 'stop', timestamp });
|
||||
} else {
|
||||
console.log('Not recording, action:', 'stop');
|
||||
}
|
||||
|
||||
// 发送停止请求到服务器
|
||||
@@ -437,7 +439,8 @@ function stopMotor() {
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
// 停止成功,不显示消息
|
||||
// 停止成功,显示已停止消息
|
||||
status.innerHTML = `<p>${data.message}</p>`;
|
||||
} else {
|
||||
status.innerHTML = `<p>错误: ${data.message}</p>`;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
// 确保在DOM加载完成后执行
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
console.log('DOMContentLoaded - Joycon.js executing');
|
||||
|
||||
// 游戏手柄相关变量
|
||||
let gamepad = null;
|
||||
let lastDirection = 'stop';
|
||||
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 (!isPlaying) {
|
||||
if (isRecording) {
|
||||
// 停止录制
|
||||
isRecording = false;
|
||||
status.innerHTML = `<p>录制完成,共记录 ${recordedActions.length} 个操作</p>`;
|
||||
console.log('Recording stopped, actions:', recordedActions);
|
||||
} else {
|
||||
// 开始录制
|
||||
isRecording = true;
|
||||
recordedActions = [];
|
||||
recordingStartTime = Date.now();
|
||||
status.innerHTML = '<p>开始录制...</p>';
|
||||
console.log('Recording started');
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
recordButtonPressed = false;
|
||||
}
|
||||
|
||||
// 处理回放按钮 (十字键左键) - 修复:检测按键按下事件
|
||||
if (buttons[14].pressed) { // 十字键左键 - 回放
|
||||
if (!playbackButtonPressed) {
|
||||
playbackButtonPressed = true;
|
||||
if (!isRecording && !isPlaying && recordedActions.length > 0) {
|
||||
isPlaying = true;
|
||||
status.innerHTML = '<p>开始回放...</p>';
|
||||
console.log('Starting playback');
|
||||
|
||||
// 按时间顺序回放操作
|
||||
let currentTime = 0;
|
||||
const totalDuration = recordedActions[recordedActions.length - 1].timestamp;
|
||||
|
||||
recordedActions.forEach((action, index) => {
|
||||
if (index === 0) {
|
||||
// 第一个操作立即执行
|
||||
console.log('Executing action immediately:', action);
|
||||
controlMotor(action.direction);
|
||||
} else {
|
||||
// 计算与前一个操作的时间差
|
||||
const prevAction = 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');
|
||||
isPlaying = false;
|
||||
}, totalDuration + 2000);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
playbackButtonPressed = false;
|
||||
}
|
||||
|
||||
// 如果方向改变,发送控制命令
|
||||
if (direction !== lastDirection) {
|
||||
// 如果正在录制,记录操作
|
||||
if (isRecording) {
|
||||
const action = {
|
||||
direction: direction,
|
||||
timestamp: Date.now() - recordingStartTime
|
||||
};
|
||||
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 (isRecording) {
|
||||
const timestamp = Date.now() - 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');
|
||||
});
|
||||
@@ -1,12 +1,25 @@
|
||||
// 获取按钮和状态元素
|
||||
const forwardBtn = document.getElementById('forwardBtn');
|
||||
const backwardBtn = document.getElementById('backwardBtn');
|
||||
const recordBtn = document.getElementById('recordBtn');
|
||||
const playbackBtn = document.getElementById('playbackBtn');
|
||||
const status = document.getElementById('status');
|
||||
|
||||
// 录制相关变量
|
||||
let isRecording = false;
|
||||
let recordedActions = [];
|
||||
let recordingStartTime = 0;
|
||||
|
||||
// 实际控制函数
|
||||
function controlMotor(direction) {
|
||||
status.innerHTML = `<p>正在${direction === 'forward' ? '前进' : '后退'}...</p>`;
|
||||
|
||||
// 记录操作(如果正在录制)
|
||||
if (isRecording) {
|
||||
const timestamp = Date.now() - recordingStartTime;
|
||||
recordedActions.push({ direction, timestamp });
|
||||
}
|
||||
|
||||
// 发送AJAX请求到后端服务器
|
||||
fetch('/control', {
|
||||
method: 'POST',
|
||||
@@ -28,6 +41,50 @@ function controlMotor(direction) {
|
||||
});
|
||||
}
|
||||
|
||||
// 录制按钮点击事件
|
||||
recordBtn.addEventListener('click', () => {
|
||||
if (isRecording) {
|
||||
// 停止录制
|
||||
isRecording = false;
|
||||
recordBtn.textContent = '开始录制';
|
||||
status.innerHTML = `<p>录制完成,共记录 ${recordedActions.length} 个操作</p>`;
|
||||
} else {
|
||||
// 开始录制
|
||||
isRecording = true;
|
||||
recordedActions = [];
|
||||
recordingStartTime = Date.now();
|
||||
recordBtn.textContent = '停止录制';
|
||||
status.innerHTML = `<p>开始录制...</p>`;
|
||||
}
|
||||
});
|
||||
|
||||
// 回放按钮点击事件
|
||||
playbackBtn.addEventListener('click', () => {
|
||||
if (recordedActions.length === 0) {
|
||||
status.innerHTML = `<p>没有可回放的操作</p>`;
|
||||
return;
|
||||
}
|
||||
|
||||
status.innerHTML = `<p>开始回放...</p>`;
|
||||
|
||||
// 按时间顺序回放操作
|
||||
let lastTimestamp = 0;
|
||||
recordedActions.forEach((action, index) => {
|
||||
setTimeout(() => {
|
||||
controlMotor(action.direction);
|
||||
|
||||
// 最后一个操作完成后显示回放完成
|
||||
if (index === recordedActions.length - 1) {
|
||||
setTimeout(() => {
|
||||
status.innerHTML = `<p>回放完成</p>`;
|
||||
}, 2000);
|
||||
}
|
||||
}, action.timestamp - lastTimestamp);
|
||||
|
||||
lastTimestamp = action.timestamp;
|
||||
});
|
||||
});
|
||||
|
||||
// 按钮点击事件
|
||||
forwardBtn.addEventListener('click', () => {
|
||||
controlMotor('forward');
|
||||
|
||||
Reference in new issue
Block a user