Spaces:
Running
Running
I think the controller is not working propperly, can you make it more robust?
Browse files- index.html +124 -51
index.html
CHANGED
|
@@ -453,12 +453,11 @@ function addEnvironmentObjects() {
|
|
| 453 |
|
| 454 |
group.position.y = 0;
|
| 455 |
scene.add(group);
|
| 456 |
-
|
| 457 |
gameState.player = {
|
| 458 |
model: group,
|
| 459 |
-
speed: 0.
|
| 460 |
-
runSpeed: 0.
|
| 461 |
-
rotationSpeed: 0.
|
| 462 |
isMoving: false,
|
| 463 |
animations: {
|
| 464 |
idle: null,
|
|
@@ -468,8 +467,7 @@ function addEnvironmentObjects() {
|
|
| 468 |
},
|
| 469 |
currentAnimation: null
|
| 470 |
};
|
| 471 |
-
|
| 472 |
-
// Add a simple animation mixer for the player
|
| 473 |
mixer = new THREE.AnimationMixer(group);
|
| 474 |
|
| 475 |
// Create simple animations
|
|
@@ -600,7 +598,7 @@ function loadNPCCharacters() {
|
|
| 600 |
function animate() {
|
| 601 |
requestAnimationFrame(animate);
|
| 602 |
|
| 603 |
-
const delta = clock.getDelta();
|
| 604 |
|
| 605 |
// Update player animation mixer
|
| 606 |
if (mixer) {
|
|
@@ -615,13 +613,24 @@ function loadNPCCharacters() {
|
|
| 615 |
|
| 616 |
renderer.render(scene, camera);
|
| 617 |
}
|
| 618 |
-
|
| 619 |
if (!gameState.player) return;
|
| 620 |
|
| 621 |
const player = gameState.player;
|
| 622 |
let moving = false;
|
| 623 |
let moveDirection = new THREE.Vector3();
|
| 624 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 625 |
// Forward/backward movement
|
| 626 |
if (gameState.keys.w) {
|
| 627 |
moveDirection.z = -1;
|
|
@@ -646,50 +655,73 @@ function loadNPCCharacters() {
|
|
| 646 |
if (moving) {
|
| 647 |
moveDirection.normalize();
|
| 648 |
|
| 649 |
-
// Calculate speed
|
| 650 |
-
const speed = gameState.keys.shift ? player.runSpeed : player.speed;
|
| 651 |
|
| 652 |
-
// Apply movement relative to
|
| 653 |
-
const
|
| 654 |
-
|
| 655 |
-
|
| 656 |
-
|
| 657 |
|
| 658 |
-
const
|
| 659 |
-
|
| 660 |
-
|
| 661 |
-
right.normalize();
|
| 662 |
|
| 663 |
const moveVector = new THREE.Vector3();
|
| 664 |
-
moveVector.addScaledVector(
|
| 665 |
-
moveVector.addScaledVector(
|
| 666 |
|
| 667 |
player.model.position.add(moveVector);
|
| 668 |
|
| 669 |
-
// Update rotation
|
| 670 |
if (moveDirection.length() > 0.1) {
|
| 671 |
-
const targetRotation = Math.atan2(moveDirection.x, moveDirection.z);
|
| 672 |
-
player.model.rotation.y = targetRotation;
|
| 673 |
}
|
| 674 |
}
|
|
|
|
| 675 |
// Jumping - only trigger when not showing dialog and not already jumping
|
| 676 |
-
if (gameState.keys.space && !gameState.isJumping && !
|
| 677 |
gameState.isJumping = true;
|
| 678 |
setPlayerAnimation('jump');
|
| 679 |
-
|
| 680 |
-
|
| 681 |
-
|
| 682 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 683 |
}
|
| 684 |
-
|
|
|
|
| 685 |
if (moving !== player.isMoving || gameState.keys.shift) {
|
| 686 |
player.isMoving = moving;
|
| 687 |
updatePlayerAnimation();
|
| 688 |
}
|
| 689 |
|
| 690 |
-
// Update camera position to follow player
|
| 691 |
-
const
|
| 692 |
-
camera.position.
|
| 693 |
camera.lookAt(player.model.position);
|
| 694 |
}
|
| 695 |
function updatePlayerAnimation() {
|
|
@@ -769,32 +801,73 @@ function showDialog(npc) {
|
|
| 769 |
existingPrompt.remove();
|
| 770 |
}
|
| 771 |
}
|
| 772 |
-
function handleKeyDown(event) {
|
| 773 |
-
|
| 774 |
-
|
| 775 |
-
|
| 776 |
-
|
| 777 |
-
|
| 778 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 779 |
case ' ':
|
| 780 |
gameState.keys.space = true;
|
| 781 |
-
if
|
|
|
|
|
|
|
| 782 |
showDialog(gameState.nearbyNpc);
|
| 783 |
-
event.preventDefault(); // Prevent default space behavior
|
| 784 |
}
|
| 785 |
break;
|
| 786 |
}
|
| 787 |
}
|
| 788 |
-
function handleKeyUp(event) {
|
| 789 |
-
|
| 790 |
-
|
| 791 |
-
|
| 792 |
-
|
| 793 |
-
|
| 794 |
-
case '
|
| 795 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 796 |
}
|
| 797 |
}
|
| 798 |
-
|
| 799 |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=KBLLR/character-selector" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
|
| 800 |
</html>
|
|
|
|
| 453 |
|
| 454 |
group.position.y = 0;
|
| 455 |
scene.add(group);
|
|
|
|
| 456 |
gameState.player = {
|
| 457 |
model: group,
|
| 458 |
+
speed: 0.08,
|
| 459 |
+
runSpeed: 0.15,
|
| 460 |
+
rotationSpeed: 0.08,
|
| 461 |
isMoving: false,
|
| 462 |
animations: {
|
| 463 |
idle: null,
|
|
|
|
| 467 |
},
|
| 468 |
currentAnimation: null
|
| 469 |
};
|
| 470 |
+
// Add a simple animation mixer for the player
|
|
|
|
| 471 |
mixer = new THREE.AnimationMixer(group);
|
| 472 |
|
| 473 |
// Create simple animations
|
|
|
|
| 598 |
function animate() {
|
| 599 |
requestAnimationFrame(animate);
|
| 600 |
|
| 601 |
+
const delta = Math.min(clock.getDelta(), 0.1); // Cap delta to prevent large jumps
|
| 602 |
|
| 603 |
// Update player animation mixer
|
| 604 |
if (mixer) {
|
|
|
|
| 613 |
|
| 614 |
renderer.render(scene, camera);
|
| 615 |
}
|
| 616 |
+
function handlePlayerMovement(delta) {
|
| 617 |
if (!gameState.player) return;
|
| 618 |
|
| 619 |
const player = gameState.player;
|
| 620 |
let moving = false;
|
| 621 |
let moveDirection = new THREE.Vector3();
|
| 622 |
|
| 623 |
+
// Check if dialog is open - disable movement if dialog is active
|
| 624 |
+
const isDialogOpen = !document.getElementById('dialog-box').classList.contains('translate-y-full');
|
| 625 |
+
if (isDialogOpen) {
|
| 626 |
+
// Stop any movement and reset animation
|
| 627 |
+
if (player.isMoving) {
|
| 628 |
+
player.isMoving = false;
|
| 629 |
+
updatePlayerAnimation();
|
| 630 |
+
}
|
| 631 |
+
return;
|
| 632 |
+
}
|
| 633 |
+
|
| 634 |
// Forward/backward movement
|
| 635 |
if (gameState.keys.w) {
|
| 636 |
moveDirection.z = -1;
|
|
|
|
| 655 |
if (moving) {
|
| 656 |
moveDirection.normalize();
|
| 657 |
|
| 658 |
+
// Calculate speed with delta time for consistent movement
|
| 659 |
+
const speed = (gameState.keys.shift ? player.runSpeed : player.speed) * delta * 60;
|
| 660 |
|
| 661 |
+
// Apply movement relative to camera direction
|
| 662 |
+
const cameraForward = new THREE.Vector3();
|
| 663 |
+
camera.getWorldDirection(cameraForward);
|
| 664 |
+
cameraForward.y = 0;
|
| 665 |
+
cameraForward.normalize();
|
| 666 |
|
| 667 |
+
const cameraRight = new THREE.Vector3();
|
| 668 |
+
cameraRight.crossVectors(cameraForward, new THREE.Vector3(0, 1, 0));
|
| 669 |
+
cameraRight.normalize();
|
|
|
|
| 670 |
|
| 671 |
const moveVector = new THREE.Vector3();
|
| 672 |
+
moveVector.addScaledVector(cameraForward, moveDirection.z * speed);
|
| 673 |
+
moveVector.addScaledVector(cameraRight, moveDirection.x * speed);
|
| 674 |
|
| 675 |
player.model.position.add(moveVector);
|
| 676 |
|
| 677 |
+
// Update player rotation to face movement direction
|
| 678 |
if (moveDirection.length() > 0.1) {
|
| 679 |
+
const targetRotation = Math.atan2(moveDirection.x, moveDirection.z) + camera.rotation.y;
|
| 680 |
+
player.model.rotation.y = THREE.MathUtils.lerp(player.model.rotation.y, targetRotation, player.rotationSpeed * delta * 60);
|
| 681 |
}
|
| 682 |
}
|
| 683 |
+
|
| 684 |
// Jumping - only trigger when not showing dialog and not already jumping
|
| 685 |
+
if (gameState.keys.space && !gameState.isJumping && !isDialogOpen) {
|
| 686 |
gameState.isJumping = true;
|
| 687 |
setPlayerAnimation('jump');
|
| 688 |
+
|
| 689 |
+
// Create a more robust jump animation
|
| 690 |
+
let jumpStartTime = performance.now();
|
| 691 |
+
const jumpDuration = 1000; // 1 second
|
| 692 |
+
const originalY = player.model.position.y;
|
| 693 |
+
const jumpHeight = 1.5;
|
| 694 |
+
|
| 695 |
+
function performJump() {
|
| 696 |
+
const currentTime = performance.now();
|
| 697 |
+
const elapsed = currentTime - jumpStartTime;
|
| 698 |
+
const progress = Math.min(elapsed / jumpDuration, 1);
|
| 699 |
+
|
| 700 |
+
// Parabolic jump curve
|
| 701 |
+
const jumpProgress = 1 - Math.pow(2 * progress - 1, 2);
|
| 702 |
+
player.model.position.y = originalY + jumpHeight * jumpProgress;
|
| 703 |
+
|
| 704 |
+
if (progress < 1) {
|
| 705 |
+
requestAnimationFrame(performJump);
|
| 706 |
+
} else {
|
| 707 |
+
gameState.isJumping = false;
|
| 708 |
+
player.model.position.y = originalY;
|
| 709 |
+
updatePlayerAnimation();
|
| 710 |
+
}
|
| 711 |
+
}
|
| 712 |
+
|
| 713 |
+
performJump();
|
| 714 |
}
|
| 715 |
+
|
| 716 |
+
// Update animation based on movement
|
| 717 |
if (moving !== player.isMoving || gameState.keys.shift) {
|
| 718 |
player.isMoving = moving;
|
| 719 |
updatePlayerAnimation();
|
| 720 |
}
|
| 721 |
|
| 722 |
+
// Update camera position to follow player with smooth interpolation
|
| 723 |
+
const targetCameraPosition = player.model.position.clone().add(new THREE.Vector3(0, 5, 10));
|
| 724 |
+
camera.position.lerp(targetCameraPosition, 0.1 * delta * 60);
|
| 725 |
camera.lookAt(player.model.position);
|
| 726 |
}
|
| 727 |
function updatePlayerAnimation() {
|
|
|
|
| 801 |
existingPrompt.remove();
|
| 802 |
}
|
| 803 |
}
|
| 804 |
+
function handleKeyDown(event) {
|
| 805 |
+
// Prevent default for space to avoid page scrolling
|
| 806 |
+
if (event.key === ' ') {
|
| 807 |
+
event.preventDefault();
|
| 808 |
+
}
|
| 809 |
+
|
| 810 |
+
// Ignore key repeats
|
| 811 |
+
if (event.repeat) return;
|
| 812 |
+
|
| 813 |
+
const key = event.key.toLowerCase();
|
| 814 |
+
switch (key) {
|
| 815 |
+
case 'w':
|
| 816 |
+
gameState.keys.w = true;
|
| 817 |
+
break;
|
| 818 |
+
case 'a':
|
| 819 |
+
gameState.keys.a = true;
|
| 820 |
+
break;
|
| 821 |
+
case 's':
|
| 822 |
+
gameState.keys.s = true;
|
| 823 |
+
break;
|
| 824 |
+
case 'd':
|
| 825 |
+
gameState.keys.d = true;
|
| 826 |
+
break;
|
| 827 |
+
case 'shift':
|
| 828 |
+
gameState.keys.shift = true;
|
| 829 |
+
break;
|
| 830 |
case ' ':
|
| 831 |
gameState.keys.space = true;
|
| 832 |
+
// Check if we're near an NPC and dialog isn't already open
|
| 833 |
+
const isDialogOpen = !document.getElementById('dialog-box').classList.contains('translate-y-full');
|
| 834 |
+
if (gameState.nearbyNpc && !gameState.isJumping && !isDialogOpen) {
|
| 835 |
showDialog(gameState.nearbyNpc);
|
|
|
|
| 836 |
}
|
| 837 |
break;
|
| 838 |
}
|
| 839 |
}
|
| 840 |
+
function handleKeyUp(event) {
|
| 841 |
+
// Ignore key repeats
|
| 842 |
+
if (event.repeat) return;
|
| 843 |
+
|
| 844 |
+
const key = event.key.toLowerCase();
|
| 845 |
+
switch (key) {
|
| 846 |
+
case 'w':
|
| 847 |
+
gameState.keys.w = false;
|
| 848 |
+
break;
|
| 849 |
+
case 'a':
|
| 850 |
+
gameState.keys.a = false;
|
| 851 |
+
break;
|
| 852 |
+
case 's':
|
| 853 |
+
gameState.keys.s = false;
|
| 854 |
+
break;
|
| 855 |
+
case 'd':
|
| 856 |
+
gameState.keys.d = false;
|
| 857 |
+
break;
|
| 858 |
+
case 'shift':
|
| 859 |
+
gameState.keys.shift = false;
|
| 860 |
+
break;
|
| 861 |
+
case ' ':
|
| 862 |
+
gameState.keys.space = false;
|
| 863 |
+
break;
|
| 864 |
+
}
|
| 865 |
+
|
| 866 |
+
// Update animation when keys are released
|
| 867 |
+
if (gameState.player) {
|
| 868 |
+
updatePlayerAnimation();
|
| 869 |
}
|
| 870 |
}
|
| 871 |
+
</script>
|
| 872 |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=KBLLR/character-selector" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
|
| 873 |
</html>
|