- Updated index.html to improve layout responsiveness using Bootstrap 5. - Added touch controls for mobile devices, including a D-Pad and action buttons. - Implemented visual feedback for touch interactions with scale animations. - Created a new test_controls.html for testing touch controls functionality. - Added a comprehensive MOBILE_README.md detailing mobile features, optimizations, and testing instructions. - Improved accessibility and usability with user-scalable settings and touch-action prevention. - Enhanced modal for profile creation with Bootstrap styling.
303 lines
10 KiB
HTML
303 lines
10 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
|
<title>Test Touch Controls</title>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
|
<style>
|
|
body {
|
|
background-color: #1e1e1e;
|
|
color: white;
|
|
padding: 20px;
|
|
}
|
|
|
|
.dpad-container {
|
|
position: relative;
|
|
width: 160px;
|
|
height: 160px;
|
|
margin: 20px auto;
|
|
}
|
|
|
|
.dpad-btn {
|
|
position: absolute;
|
|
width: 50px;
|
|
height: 50px;
|
|
background-color: #ff9f43;
|
|
border: 2px solid #1e1e1e;
|
|
border-radius: 8px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 1.5rem;
|
|
cursor: pointer;
|
|
user-select: none;
|
|
touch-action: none;
|
|
transition: transform 0.1s ease, opacity 0.1s ease;
|
|
}
|
|
|
|
.dpad-up { top: 0; left: 55px; }
|
|
.dpad-down { bottom: 0; left: 55px; }
|
|
.dpad-left { top: 55px; left: 0; }
|
|
.dpad-right { top: 55px; right: 0; }
|
|
.dpad-center {
|
|
top: 55px;
|
|
left: 55px;
|
|
background-color: #2d2d2d;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.action-buttons {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: 8px;
|
|
max-width: 300px;
|
|
margin: 20px auto;
|
|
}
|
|
|
|
.action-btn {
|
|
height: 55px;
|
|
font-size: 0.95rem;
|
|
background-color: #ff9f43 !important;
|
|
color: #1e1e1e !important;
|
|
border: none !important;
|
|
font-weight: bold;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 5px;
|
|
touch-action: none;
|
|
transition: transform 0.1s ease, opacity 0.1s ease;
|
|
}
|
|
|
|
.action-btn small {
|
|
font-size: 0.7rem;
|
|
font-weight: normal;
|
|
margin-top: 2px;
|
|
}
|
|
|
|
#log {
|
|
background-color: #000;
|
|
border: 1px solid #555;
|
|
border-radius: 5px;
|
|
padding: 10px;
|
|
height: 200px;
|
|
overflow-y: auto;
|
|
font-family: monospace;
|
|
font-size: 0.85rem;
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.log-entry {
|
|
margin: 2px 0;
|
|
}
|
|
|
|
.log-keydown { color: #4ade80; }
|
|
.log-keyup { color: #fbbf24; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h1 class="text-center mb-4">🎮 Test Touch Controls</h1>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h5 class="text-center text-muted mb-2">Movement</h5>
|
|
<div class="dpad-container">
|
|
<div class="dpad-btn dpad-up" data-key="ArrowUp">
|
|
<i class="bi bi-arrow-up"></i>
|
|
</div>
|
|
<div class="dpad-btn dpad-left" data-key="ArrowLeft">
|
|
<i class="bi bi-arrow-left"></i>
|
|
</div>
|
|
<div class="dpad-btn dpad-center"></div>
|
|
<div class="dpad-btn dpad-right" data-key="ArrowRight">
|
|
<i class="bi bi-arrow-right"></i>
|
|
</div>
|
|
<div class="dpad-btn dpad-down" data-key="ArrowDown">
|
|
<i class="bi bi-arrow-down"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<h5 class="text-center text-muted mb-2">Actions</h5>
|
|
<div class="action-buttons">
|
|
<button class="btn action-btn" data-key="Enter">
|
|
▶️<br><small>Start</small>
|
|
</button>
|
|
<button class="btn action-btn" data-key=" ">
|
|
💣<br><small>Bomb</small>
|
|
</button>
|
|
<button class="btn action-btn" data-key="m">
|
|
⚠️<br><small>Mine</small>
|
|
</button>
|
|
<button class="btn action-btn" data-key="g">
|
|
☁️<br><small>Gas</small>
|
|
</button>
|
|
<button class="btn action-btn" data-key="n">
|
|
☢️<br><small>Nuclear</small>
|
|
</button>
|
|
<button class="btn action-btn" data-key="p">
|
|
⏸️<br><small>Pause</small>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="log"></div>
|
|
<button class="btn btn-danger mt-2" onclick="clearLog()">Clear Log</button>
|
|
</div>
|
|
|
|
<script>
|
|
const logDiv = document.getElementById('log');
|
|
let logCount = 0;
|
|
|
|
function addLog(message, type) {
|
|
const entry = document.createElement('div');
|
|
entry.className = `log-entry log-${type}`;
|
|
entry.textContent = `[${++logCount}] ${message}`;
|
|
logDiv.appendChild(entry);
|
|
logDiv.scrollTop = logDiv.scrollHeight;
|
|
|
|
// Keep only last 50 entries
|
|
while (logDiv.children.length > 50) {
|
|
logDiv.removeChild(logDiv.firstChild);
|
|
}
|
|
}
|
|
|
|
function clearLog() {
|
|
logDiv.innerHTML = '';
|
|
logCount = 0;
|
|
}
|
|
|
|
// Listen to keyboard events
|
|
document.addEventListener('keydown', (e) => {
|
|
addLog(`KeyDown: key="${e.key}", code="${e.code}", keyCode=${e.keyCode}`, 'keydown');
|
|
});
|
|
|
|
document.addEventListener('keyup', (e) => {
|
|
addLog(`KeyUp: key="${e.key}", code="${e.code}", keyCode=${e.keyCode}`, 'keyup');
|
|
});
|
|
|
|
// Simulate keyboard events
|
|
function simulateKeyPress(key, type = 'keydown') {
|
|
const keyCodeMap = {
|
|
'ArrowUp': 38,
|
|
'ArrowDown': 40,
|
|
'ArrowLeft': 37,
|
|
'ArrowRight': 39,
|
|
' ': 32,
|
|
'Enter': 13,
|
|
'm': 77,
|
|
'M': 77,
|
|
'g': 71,
|
|
'G': 71,
|
|
'n': 78,
|
|
'N': 78,
|
|
'p': 80,
|
|
'P': 80
|
|
};
|
|
|
|
const keyCode = keyCodeMap[key] || key.toUpperCase().charCodeAt(0);
|
|
|
|
let code;
|
|
if (key.startsWith('Arrow')) {
|
|
code = key;
|
|
} else if (key === ' ') {
|
|
code = 'Space';
|
|
} else if (key === 'Enter') {
|
|
code = 'Enter';
|
|
} else {
|
|
code = `Key${key.toUpperCase()}`;
|
|
}
|
|
|
|
const event = new KeyboardEvent(type, {
|
|
key: key,
|
|
code: code,
|
|
keyCode: keyCode,
|
|
which: keyCode,
|
|
bubbles: true,
|
|
cancelable: true
|
|
});
|
|
|
|
document.dispatchEvent(event);
|
|
window.dispatchEvent(event);
|
|
}
|
|
|
|
// Setup touch controls
|
|
function setupTouchControls() {
|
|
document.querySelectorAll('.dpad-btn, .action-btn').forEach(btn => {
|
|
const key = btn.dataset.key;
|
|
if (!key) return;
|
|
|
|
let isPressed = false;
|
|
|
|
btn.addEventListener('touchstart', (e) => {
|
|
e.preventDefault();
|
|
if (isPressed) return;
|
|
isPressed = true;
|
|
btn.style.transform = 'scale(0.95)';
|
|
btn.style.opacity = '0.7';
|
|
simulateKeyPress(key, 'keydown');
|
|
}, { passive: false });
|
|
|
|
btn.addEventListener('touchend', (e) => {
|
|
e.preventDefault();
|
|
if (!isPressed) return;
|
|
isPressed = false;
|
|
btn.style.transform = 'scale(1)';
|
|
btn.style.opacity = '1';
|
|
simulateKeyPress(key, 'keyup');
|
|
}, { passive: false });
|
|
|
|
btn.addEventListener('touchcancel', (e) => {
|
|
e.preventDefault();
|
|
if (!isPressed) return;
|
|
isPressed = false;
|
|
btn.style.transform = 'scale(1)';
|
|
btn.style.opacity = '1';
|
|
simulateKeyPress(key, 'keyup');
|
|
}, { passive: false });
|
|
|
|
btn.addEventListener('mousedown', (e) => {
|
|
e.preventDefault();
|
|
if (isPressed) return;
|
|
isPressed = true;
|
|
btn.style.transform = 'scale(0.95)';
|
|
btn.style.opacity = '0.7';
|
|
simulateKeyPress(key, 'keydown');
|
|
});
|
|
|
|
btn.addEventListener('mouseup', (e) => {
|
|
e.preventDefault();
|
|
if (!isPressed) return;
|
|
isPressed = false;
|
|
btn.style.transform = 'scale(1)';
|
|
btn.style.opacity = '1';
|
|
simulateKeyPress(key, 'keyup');
|
|
});
|
|
|
|
btn.addEventListener('mouseleave', (e) => {
|
|
if (!isPressed) return;
|
|
isPressed = false;
|
|
btn.style.transform = 'scale(1)';
|
|
btn.style.opacity = '1';
|
|
simulateKeyPress(key, 'keyup');
|
|
});
|
|
|
|
btn.addEventListener('contextmenu', (e) => {
|
|
e.preventDefault();
|
|
});
|
|
});
|
|
}
|
|
|
|
// Initialize
|
|
setupTouchControls();
|
|
addLog('Touch controls initialized. Try pressing buttons!', 'keydown');
|
|
</script>
|
|
</body>
|
|
</html>
|