|
|
<!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>
|
|
|
|