Feature/Touch support #4
1 changed files with 122 additions and 1 deletions
123
index.html
123
index.html
|
|
@ -72,6 +72,11 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
|
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
|
||||||
}
|
}
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
#instructions {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -87,7 +92,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="instructions">
|
<div id="instructions">
|
||||||
<p><strong>Controls:</strong> WASD or Arrow Keys to move | Collect yellow coins | Avoid red obstacles!</p>
|
<p><strong>Controls:</strong> WASD or Arrow Keys to move | Touch and drag to move (mobile) | Collect yellow coins | Avoid red obstacles!</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
||||||
|
|
@ -319,6 +324,12 @@
|
||||||
this.keys = {};
|
this.keys = {};
|
||||||
this.coins = [];
|
this.coins = [];
|
||||||
this.obstacles = [];
|
this.obstacles = [];
|
||||||
|
this.touchActive = false;
|
||||||
|
this.touchStartX = 0;
|
||||||
|
this.touchStartY = 0;
|
||||||
|
this.touchCurrentX = 0;
|
||||||
|
this.touchCurrentY = 0;
|
||||||
|
this.touchId = null;
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
this.setupEventListeners();
|
this.setupEventListeners();
|
||||||
|
|
@ -427,6 +438,111 @@
|
||||||
});
|
});
|
||||||
window.addEventListener('resize', () => this.onWindowResize());
|
window.addEventListener('resize', () => this.onWindowResize());
|
||||||
document.getElementById('restartBtn').addEventListener('click', () => this.restart());
|
document.getElementById('restartBtn').addEventListener('click', () => this.restart());
|
||||||
|
|
||||||
|
// Touch event listeners
|
||||||
|
this.setupTouchControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
setupTouchControls() {
|
||||||
|
const canvas = this.renderer.domElement;
|
||||||
|
|
||||||
|
// Prevent default touch behaviors
|
||||||
|
canvas.addEventListener('touchstart', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
this.handleTouchStart(e);
|
||||||
|
}, { passive: false });
|
||||||
|
|
||||||
|
canvas.addEventListener('touchmove', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
this.handleTouchMove(e);
|
||||||
|
}, { passive: false });
|
||||||
|
|
||||||
|
canvas.addEventListener('touchend', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
this.handleTouchEnd(e);
|
||||||
|
}, { passive: false });
|
||||||
|
|
||||||
|
canvas.addEventListener('touchcancel', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
this.handleTouchEnd(e);
|
||||||
|
}, { passive: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTouchStart(e) {
|
||||||
|
if (this.touchActive) return;
|
||||||
|
|
||||||
|
const touch = e.touches[0];
|
||||||
|
const rect = this.renderer.domElement.getBoundingClientRect();
|
||||||
|
|
||||||
|
// Use center of screen as reference point
|
||||||
|
this.touchStartX = rect.left + rect.width / 2;
|
||||||
|
this.touchStartY = rect.top + rect.height / 2;
|
||||||
|
|
||||||
|
this.touchId = touch.identifier;
|
||||||
|
this.touchCurrentX = touch.clientX;
|
||||||
|
this.touchCurrentY = touch.clientY;
|
||||||
|
this.touchActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTouchMove(e) {
|
||||||
|
if (!this.touchActive) return;
|
||||||
|
|
||||||
|
const touch = Array.from(e.touches).find(t => t.identifier === this.touchId);
|
||||||
|
if (!touch) return;
|
||||||
|
|
||||||
|
this.touchCurrentX = touch.clientX;
|
||||||
|
this.touchCurrentY = touch.clientY;
|
||||||
|
|
||||||
|
this.updateTouchMovement();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTouchEnd(e) {
|
||||||
|
if (!this.touchActive) return;
|
||||||
|
|
||||||
|
// Check if the touch that ended is our tracked touch
|
||||||
|
const touch = Array.from(e.changedTouches).find(t => t.identifier === this.touchId);
|
||||||
|
if (!touch) return;
|
||||||
|
|
||||||
|
this.touchActive = false;
|
||||||
|
this.touchId = null;
|
||||||
|
this.touchCurrentX = this.touchStartX;
|
||||||
|
this.touchCurrentY = this.touchStartY;
|
||||||
|
this.updateTouchMovement();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTouchMovement() {
|
||||||
|
if (!this.touchActive) {
|
||||||
|
// Reset all movement keys
|
||||||
|
this.keys['w'] = false;
|
||||||
|
this.keys['s'] = false;
|
||||||
|
this.keys['a'] = false;
|
||||||
|
this.keys['d'] = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const deltaX = this.touchCurrentX - this.touchStartX;
|
||||||
|
const deltaY = this.touchCurrentY - this.touchStartY;
|
||||||
|
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||||
|
|
||||||
|
// Normalize movement direction
|
||||||
|
const threshold = 10; // Minimum movement to register
|
||||||
|
if (distance < threshold) {
|
||||||
|
this.keys['w'] = false;
|
||||||
|
this.keys['s'] = false;
|
||||||
|
this.keys['a'] = false;
|
||||||
|
this.keys['d'] = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate direction
|
||||||
|
const normalizedX = deltaX / distance;
|
||||||
|
const normalizedY = deltaY / distance;
|
||||||
|
|
||||||
|
// Update movement keys based on direction
|
||||||
|
this.keys['w'] = normalizedY < -0.3;
|
||||||
|
this.keys['s'] = normalizedY > 0.3;
|
||||||
|
this.keys['a'] = normalizedX < -0.3;
|
||||||
|
this.keys['d'] = normalizedX > 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePlayer() {
|
updatePlayer() {
|
||||||
|
|
@ -516,6 +632,11 @@
|
||||||
animate() {
|
animate() {
|
||||||
requestAnimationFrame(() => this.animate());
|
requestAnimationFrame(() => this.animate());
|
||||||
|
|
||||||
|
// Update touch movement if active
|
||||||
|
if (this.touchActive) {
|
||||||
|
this.updateTouchMovement();
|
||||||
|
}
|
||||||
|
|
||||||
this.updatePlayer();
|
this.updatePlayer();
|
||||||
this.updateCoins();
|
this.updateCoins();
|
||||||
this.updateObstacles();
|
this.updateObstacles();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue