如何实现Turtle角色按住按键时持续移动,无需重复按键?
Hey there! Great question—this is a super common (and totally solvable) issue when setting up basic player movement. The problem with relying solely on keydown events is that they only fire once when you press a key (or with a system-controlled delay for repeats), which isn’t ideal for smooth, continuous movement. Here’s the standard approach to fix this:
Core Idea
Instead of triggering movement directly from keydown events, we’ll track which keys are currently being held down with a state object, then update the player’s position in our game’s main loop based on that state.
Step 1: Set Up a Key State Object
First, create an object to keep track of whether each arrow key is pressed:
const keyStates = { ArrowLeft: false, ArrowRight: false, ArrowUp: false, ArrowDown: false };
Step 2: Update State on Key Press/Release
Add event listeners to update the state object when keys are pressed or released:
// Listen for key down events document.addEventListener('keydown', (event) => { // Check if the pressed key is one we care about if (keyStates.hasOwnProperty(event.key)) { keyStates[event.key] = true; // Optional: Prevent page scrolling if you don't want it event.preventDefault(); } }); // Listen for key up events document.addEventListener('keyup', (event) => { if (keyStates.hasOwnProperty(event.key)) { keyStates[event.key] = false; } });
Step 3: Handle Movement in Your Game Loop
Now, in your game’s main update/render loop (usually powered by requestAnimationFrame), check the key states and update the player’s position continuously:
Let’s assume you have a player object with x, y, and speed properties, and a way to render them (either on a canvas or as a DOM element):
// Example player object const player = { x: 100, // Starting X position (adjust as needed) y: window.innerHeight - 50, // Lock to bottom of screen (assuming 50px tall player) width: 50, height: 50, speed: 5 // Adjust this for faster/slower movement }; function gameLoop() { // Update player position based on key states if (keyStates.ArrowLeft) { player.x -= player.speed; // Add boundary check to prevent moving off-screen left player.x = Math.max(0, player.x); } if (keyStates.ArrowRight) { player.x += player.speed; // Boundary check for right side (screen width minus player width) player.x = Math.min(window.innerWidth - player.width, player.x); } // Uncomment if you need up/down movement too // if (keyStates.ArrowUp) { // player.y -= player.speed; // player.y = Math.max(0, player.y); // } // if (keyStates.ArrowDown) { // player.y += player.speed; // player.y = Math.min(window.innerHeight - player.height, player.y); // } // Render the player (adjust this based on your setup) // For DOM elements: const playerElement = document.getElementById('player'); playerElement.style.left = `${player.x}px`; playerElement.style.top = `${player.y}px`; // For Canvas: // ctx.clearRect(0, 0, canvas.width, canvas.height); // ctx.fillRect(player.x, player.y, player.width, player.height); // Repeat the loop requestAnimationFrame(gameLoop); } // Start the game loop gameLoop();
Extra Tips
- Boundary Checks: The
Math.maxandMath.minlines ensure your player can’t move outside the screen—adjust these values to match your game’s layout. - DOM vs Canvas: The example includes both DOM and canvas rendering notes—use whichever fits your project.
- Key Names: Using
event.key(likeArrowLeft) is more readable than oldkeyCodevalues, and works across most modern browsers.
This approach separates input handling from movement logic, which makes your code cleaner and ensures smooth, continuous movement whenever the player holds down an arrow key.
内容的提问来源于stack exchange,提问作者StealthTuba3480

